Configurando Servidor Web Seguro com suporte a Php e Mysql utilizando Nginx + Naxsi + php-fpm

By | 2 de abril de 2014

Manter um Servidor Web tem se tornado uma tarefa cada vez mais complexa. A medida em que tudo se converge para a “nuvem”,  surgem cada vez mais aplicativos e serviços que utilizam HTTP para enviar/receber dados. E proporcionalmente a esse crescimento, surgem os problemas de Segurança.
Este artigo  mostra uma forma de configurar um Servidor Web Seguro com suporte á PHP e Mysql,  utilizando Nginx, Naxsi e php-fpm. Vamos entender qual a função de cada um:

  • Nginx: Servidor HTTP de alta performance,  muito conhecido pela sua estabilidade  e facilidade de configuração.
  • Naxsi: Firewall de aplicação Web de alta performance e baixa manutenção, para uso com Nginx.
  • Php-fpm: (FastCGI Process Manager) é uma alternativa para a implementação PHP FastCGI com alguns recursos adicionais (principalmente) usado em sites pessados.¹

Este tutorial foi feito utilizando CentOS 6.5.

1 –  Suprir dependências

# yum install git mysql mysql-server openssl openssl-devel wget make gcc
Obs: Um passo recomendado é utilizar o mysql_secure_installation:

# service mysqld start
# mysql_secure_installation

2 – Instalando Nginx e Nasxi

Muito embora o Nginx possa ser instalado via Yum, teremos que compilar ele manualmente. Isto porquê o nasxi deve ser compilado junto com o Nginx.
Obs: Substituir o “x” pela versão (utilizar sempre a ultima stable).

# wget http://nginx.org/download/nginx-1.x.x.tar.gz
# git clone https://github.com/nbs-system/naxsi
# tar zvfx nginx-1.x.x.tar.gz
# cd nginx-1.x.x
#./configure –conf-path=/etc/nginx/nginx.conf –add-module=../naxsi/naxsi_src/ –error-log-path=/var/log/nginx/error.log –http-client-body-temp-path=/var/lib/nginx/body –http-fastcgi-temp-path=/var/lib/nginx/fastcgi –http-log-path=/var/log/nginx/access.log –http-proxy-temp-path=/var/lib/nginx/proxy –lock-path=/var/lock/nginx.lock –pid-path=/var/run/nginx.pid –without-http_uwsgi_module –without-http_scgi_module –with-http_ssl_module  –with-ipv6 –prefix=/usr
# make && make install
# mkdir /var/lib/nginx
# useradd -s /bin/false -M -d /var/www  nginx
 

Caso esteja utilizando CentOS, utilizar o script de inicialização contido aqui .

Instalando php-fpm

# yum install php php-devel php-common php-gd php-mysql php-fpm

3 – Configurando ambiente

Configurando Nginx e Naxsi

Visando simplificar a configuração, iremos criar um nginx.conf “genérico”, e as configurações de cada site irão ficar em /etc/nginx/conf.d . As “rules” do naxsi de cada site irão ficar em /etc/nginx/rules.d/. Você pode clicar aqui para baixar o nginx.conf ou executar o comando abaixo:

# wget -O /etc/nginx/nginx.conf http://gesielbernardes.eti.br/wp-content/uploads/2014/04/nginx.conf_.txt

Vamos criar agora a estrutura do naxsi:

# cd ../naxsi
# cp naxsi_config/naxsi_core.rules /etc/nginx/naxsi_core.rules
# cd nx_util
# python setup.py build
# python setup.py install
# mkdir /etc/nginx/conf.d
# mkdir /etc/nginx/rules.d

 

4 – Adicionando Sites

Para cada site adicionado, o ideal é que seja criado um arquivo no nginx, um arquivo de regras do naxsi e um arquivo de configurações do php-fpm. Isso faz com que seja possível “isolar” os ambientes, fazendo com que a segurança seja um pouco mais reforçada. Para este tutorial, iremos adicionar um site chamado “meusite.com”. A página inicial consultara a data e hora no banco e exibirá juntamente com a pagina phpinfo. O código dela está abaixo:

# cat /var/www/html/index.php
<?php

$db = mysqli_connect(“localhost”,”meuuser”,”minhasenha”,”mysql”);
$consulta = “SELECT NOW()”;
$result = mysqli_query($db,$consulta);
$data = mysqli_fetch_row($result);
echo $data[0];
phpinfo();

?>

Agora vamos adicionar o site no Nginx:

# vi /etc/nginx/conf.d/meusite.conf
####################################
server {
listen 80;
        server_name meusite.com.br;

location / {
root /var/www/meusite/;
index index.php index.html ;
include /etc/nginx/rules.d/meusite.rules;

}

location ~ \.(php|html)$ {
root /var/www/meusite ;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.html;
fastcgi_param SCRIPT_FILENAME /var/www/meusite/$fastcgi_script_name;
include fastcgi_params;
include /etc/nginx/rules.d/meusite.rules;
access_log /var/log/nginx/access_meusite.log;
error_log /var/log/nginx/error_meusite.log;
}

}
#######################################

Nesse exemplo acima, as extensões “.html” e “.php” serão passadas ao php-fpm, enquanto o restante do conteúdo será processado pelo nginx. Agora será necessário criar o arquivo de regras do naxsi para este site. O padrão é o conteúdo abaixo:

# vi /etc/nginx/rules.d/meusite.rules
#####################
LearningMode; #Enables learning mode
SecRulesEnabled;
#SecRulesDisabled;
DeniedUrl “/RequestDenied”;
## check rules
CheckRule “$SQL >= 8” BLOCK;
CheckRule “$RFI >= 8” BLOCK;
CheckRule “$TRAVERSAL >= 4” BLOCK;
CheckRule “$EVADE >= 4” BLOCK;
CheckRule “$XSS >= 8” BLOCK;
########################

A opção “LearningMode” refere-se ao modo de aprendizagem. O naxsi é um WAF baseado em detecção de anomalias, portanto, para que ele possa identificar o que é “anormal”, é necessário gerar uma whitelist. Posteriormente, iremos ver como gerar essa whitelist.

Resta agora configurar o php-fpm. Iremos utilizar o arquivo default para esse exemplo, mas é recomendável criar um arquivo para cada site. Mantenha o conteúdo do arquivo e modifique APENAS as opções abaixo:

# vi /etc/php-fpm.d/www.conf
user = nginx
group = nginx
chdir = /var/www/meusite/

Basta agora apenas iniciar os serviços:

# service mysqld start
# service php-fpm start
# service nginx start

E pronto. O Servidor já está funcionando com suporte á PHP e Mysql

print

 

Por fim, resta apenas gerar a whitelist do naxsi. Com os site em funcionamento, navegue por ele, simulando um acesso. Teste de diversos navegadores, se possível em sistemas operacionais diferentes. Agora vamos gerar o relatório a partir dos logs:

# nx_util.py -l /var/log/nginx/error_meusite.log -o

Ele vai processar os arquivos e apresentar sugestões de regras, algo com abaixo:

BasicRule wl:1011 “mz:$HEADERS_VAR:cookie”;
BasicRule wl:1010 “mz:$HEADERS_VAR:cookie”;

Essas sugestões você adiciona no seu arquivo de rules do site, neste caso em /etc/nginx/rules.d/meusite.rules. No mundo ideal, isso seria o suficiente. Todavia, a amostragem (acessos de teste) nem sempre são suficientes para gerar a whitelist. Ideal é se ele ficasse no modo de aprendizagem um determinado tempo, algo como uma semana, para que seja gerada uma whitelist ampla. Vale ressaltar que, neste caso, deve-se tomar cuidado para não incluir um ataque em uma whitelist.

Posteriormente, veremos  como utilizar SSL , e também outros ajustes que podem tornar o ambiente ainda mais seguro.

 

Referências:

¹ http://www.php.net/manual/pt_BR/install.fpm.php
Naxsi Wiki