Ao desenvolver ou manter aplicações web, em algum momento você terá que lidar com a necessidade de usar WAF (Web Application Firewall). Se você não tem experiência com essa classe de solução ou está cansado de constantes falsos positivos, vou te explicar como simplificar a tarefa, além de compartilhar algumas dicas e truques. Usaremos o Nemesida WAF Free como ferramenta - uma versão gratuita do Nemesida WAF.
Visualização, ou vamos começar pelo final
Você pode monitorar o trabalho do Nemesida WAF Free através de um navegador, assim após uma breve configuração do sistema teremos acesso à interface web, onde estarão disponíveis informações sobre ataques bloqueados, motivos do bloqueio, informações sobre endereços IP, etc. Além disso, serão exibidas seções com estatísticas resumidas na forma de gráficos, diagramas e dados sobre o tráfego do módulo VTS (se usado). Estande de
demonstração: demo.lk.nemesida-security.com (demo@pentestit.ru / pentestit)
Vamos prosseguir com a instalação.
Instalando Nemesida WAF Free
Apesar do fato de que a versão gratuita é um fork da versão completa, ela contém um grande conjunto de recursos para detectar, bloquear e visualizar ataques em aplicativos da web. Por aplicativo da web, entendemos tudo o que é construído no protocolo HTTP: sites, contas pessoais, lojas online, sites de treinamento, APIs e tudo mais.
No parágrafo anterior, dividi especificamente a funcionalidade de bloqueio de ataques em detecção e bloqueio, uma vez que existem 2 (até três) modos de operação do produto: IDS, IPS e PseudoIDS (modo LM).
Modo IDS
O modo IDS permite usar WAF em uma cópia de tráfego, detectando, mas não bloqueando ataques. Este modo de funcionamento é útil, por exemplo, para o arranque inicial ou para monitorização passiva, para evitar qualquer bloqueio de pedidos ou um aumento, embora desprezível, do tempo de resposta. Para a configuração de exemplo, usaremos Nginx para o servidor de envio (embora você possa usar qualquer outro, por exemplo, Apache2 ou IIS).
Configurando o servidor de envio:
location / {
mirror /mirror;
...
}
location = /mirror {
internal;
proxy_pass http://192.168.0.1$request_uri;
}
(em vez de 192.168.0.1, você deve especificar o endereço do servidor com Nemesida WAF instalado)
Após fazer alterações e reiniciar o servidor web, as solicitações que chegam a este servidor serão transmitidas para o servidor 192.168.0.1 com Nemesida WAF instalado (sua configuração é simples e será descrita a seguir). Este esquema de trabalho permite monitorar ataques sem bloqueá-los, mas ao mesmo tempo, sem afetar o servidor principal.
Modo IPS e PseudoIDS
Os 2 modos de operação restantes pressupõem o uso de WAF "inversamente", enquanto no modo IPS os incidentes de segurança detectados são bloqueados, no modo PseudoIDS são registrados, mas não bloqueados. O último modo é conveniente porque a alternância entre esses dois modos é feita usando opções simples: a capacidade de alternar para o modo PseudoIDS pelo nome do servidor (opção
nwaf_host_lm
) e pelo endereço IP do cliente (opção
nwaf_ip_lm
).
Em geral, Nemesida WAF Free fornece muitos parâmetros para “ajustar” o sistema: funcionalidade flexível para criar suas próprias regras de bloqueio e exclusão, a capacidade de adicionar um IP de cliente à “lista de exclusões”, a opção de configurar um ban para todos e para cada host virtual individual, etc. ... Toda essa economia pode ser controlada por meio do arquivo de configuração na versão gratuita e na versão completa também por meio de chamadas de API.
Vamos voltar ao procedimento de instalação. Nemesida WAF é apresentado na forma de vários componentes:
- Módulo dinâmico para Nginx
- API Nemesida WAF (aceita eventos do Nemesida WAF e os coloca no Postgres para posterior exibição no LC ou integração com sistemas SIEM)
- Conta pessoal (interface web para monitoramento de incidentes)
- Módulo de aprendizado de máquina Nemesida AI
- Vulnerability Scanner Nemesida WAF Scanner
- Nemesida WAF Signtest - interface da web para gerenciar um módulo de aprendizado de máquina
No Nemesida WAF Free, precisamos apenas dos três primeiros - o próprio módulo dinâmico, a API Nemesida WAF e a conta pessoal. Todos os componentes estão disponíveis como distribuições de instalação e permitem que você conecte Nemesida WAF a uma instância Nginx já instalada, a partir da versão 1.12 (versões Stable, Mainline e Plus do Nginx são suportadas).
Módulo dinâmico Nemesida WAF
Para aqueles que não estão instalando o kit de distribuição pela primeira vez, o processo de instalação e execução do módulo dinâmico leva cerca de 5 a 10 minutos. O módulo WAF da Nemesida dinâmico pode ser conectado a um Nginx já instalado (ou compilado da fonte com seus próprios módulos).
Os repositórios Nemesida WAF estão disponíveis para os seguintes sistemas operacionais: Debian 9/10, Ubuntu 16.04 / 18.04 / 20.04, Centos 7/8. As instruções em vídeo para instalar e configurar os componentes pela primeira vez são publicadas no canal do Youtube. Recomendamos que você se familiarize com um deles, mas recomendamos instalar e configurar de acordo com a documentação do site principal, pois alguns parâmetros podem ficar desatualizados, outros podem ser adicionados.
Instalando o módulo dinâmico Nemesida WAF (vídeo)
Depois que o Nginx for configurado, conecte o repositório Nemesida WAF correspondente ao seu sistema operacional e prossiga com a instalação. O produto também é atualizado a partir do repositório. As instruções de instalação estão disponíveis em: github.com/nemesida-waf/nemesida_waf_free .
API Nemesida WAF e conta pessoal
Depois que o módulo dinâmico for instalado e iniciado, é hora de prosseguir com a instalação dos dois componentes restantes: Nemesida WAF API e conta pessoal.
A API Nemesida WAF é apresentada na forma de uma API escrita usando Flask e é projetada para receber eventos do Nemesida WAF, Nemesida WAF Scanner e Nemesida AI, e então colocar esses eventos no banco de dados. PostgreSQL é usado como um DBMS. Na versão gratuita do Nemesida WAF, apenas informações sobre solicitações bloqueadas serão transmitidas para o banco de dados.
Após a API Nemesida WAF ser configurada e conectada ao PostgreSQL, é hora de começar a iniciar sua conta pessoal. De acordo com a documentação, instalamos, configuramos, realizamos a migração, especificamos o usuário e senha para entrar.
Por experiência, instalar os dois últimos componentes causa mais dificuldades (geralmente alguns passos são ignorados, por exemplo, eles se esquecem de migrar ou permitir a conexão ao Postgres), então para um início rápido, preparamos um Dispositivo Virtual (disco virtual com componentes Debian 10 e Nemesida WAF, 3 GB para descompactando), e também fez 2 imagens Docker : para o módulo dinâmico e para a Nemesida WAF API / conta pessoal.
Bem, a parte mais chata acabou, agora podemos testar o WAF em ação.
Primeiro hack
Para testar a operação de um WAF já configurado, não é necessário lembrar as diferentes variações de ataque. Criamos uma assinatura de teste que verificará se o Nemesida WAF está funcionando e se os ataques bloqueados são exibidos no LC. O conjunto atual de assinaturas usadas pode sempre ser visualizado em rlinfo.nemesida-security.com .
Enviamos uma solicitação (fiz isso por meio do console, mas é melhor fazê-lo por meio do navegador para maior clareza):
curl --noproxy '*' example.com/nwaftest
ou, se você quiser algo mais próximo da realidade:
curl --noproxy '*' example.com/?cmd=;+cat+/etc/passwd
Em resposta, recebemos um código de resposta 403:
<html> <head><title>403 Forbidden</title></head> <body> <center><h1>403 Forbidden</h1></center> <hr><center>nginx/1.18.0</center> </body> </html>
E em alguns segundos deve aparecer um ataque no LC:
Se a solicitação não está bloqueada - WAF está conectado ou configurado incorretamente (talvez o endereço ou host tenha sido adicionado ao WL / LM), se a solicitação foi bloqueada, mas não há informações no LC - verifique a exatidão da interação com Nemesida WAF API e LC. Em qualquer caso, você sempre pode fazer uma pergunta no fórum .
Página 403 personalizada
Por padrão, a página 403 (página com código de resposta 403) é pouco atraente e mesquinha com informações. Nemesida WAF em conjunto com Nginx permite torná-lo bonito e mais informativo.
Para que seu servidor atenda a tal página, você deve:
1. Criar um arquivo de configuração para páginas personalizadas (por exemplo, em
/etc/nginx/snippets/custom_pages.conf
);
Adicione os parâmetros necessários ao Nginx
— 222 403 405
;
( example.com/403.html — ), ID ($request_id), ($host), , IP ($remote_addr) ( ) Nemesida WAF ($nwaf_block_type). Nemesida WAF , , 1 2 — , 3 — , 4 — ..
## Error pages
error_page 403 405 = 222 /403.html;
## Locations
location /403.html {
internal;
root /var/www/custom_pages/;
proxy_no_cache 1;
proxy_cache_bypass 1;
add_header X-Request-ID $request_id always;
add_header Host $host always;
add_header X-Remote-IP $remote_addr always;
add_header NemesidaWAF-BT $nwaf_block_type always;
}
:
error_page 403 405 = 222 /403.html;
— 222 403 405
/403.html
;
/403.html
( example.com/403.html — ), ID ($request_id), ($host), , IP ($remote_addr) ( ) Nemesida WAF ($nwaf_block_type). Nemesida WAF , , 1 2 — , 3 — , 4 — ..
2. Conecte o arquivo criado:
Conecte o arquivo criado à configuração Nginx
(,
):
/etc/nginx/conf.d/example.com.conf
):
server {
...
## Custom pages
include snippets/custom_pages.conf;
....
}
3. Crie uma página personalizada (por exemplo
/var/www/custom_pages/403.html
) com o seguinte conteúdo (por exemplo):
Exemplo de página 403 personalizada
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="refresh" content="7; URL=/" />
<style type="text/css">
.error {color:#000; font-family:Arial, sans-serif; text-align: center; position: absolute; top: 50%; left: 50%; -moz-transform: translateX(-50%) translateY(-50%); -webkit-transform: translateX(-50%) translateY(-50%); transform: translateX(-50%) translateY(-50%);}
.error-fon {font-weight:bold; color:#d0e3f7;}
.error-text-top {font-size:16px; color:#434141}
hr { display: block; height: 10px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
</style>
<title>403 Access denied</title>
</head>
<body>
<div class="error">
<div class="error-fon">
<font style="font-size:240px;">403</font>
<br>
<font style="font-size:40px;">ACCESS IS BLOCKED</font>
</div>
<br>
<div class="error-text-wrap">
<div class="error-text-top">
<p>
<hr>
<p style="text-align: justify;">
Suspicious activity. If the request is blocked by mistake, please email us at <a href="mailto:blocked@example.com">blocked@example.com</a> and be sure to include technical information below (domain, IP, request ID), or try again in 5 minutes.
<br><br>
. , , <a href="mailto:blocked@example.com">blocked@example.com</a>, (domain, IP, request ID), 5 .
</p>
<hr>
<table style="text-align: left; margin: auto">
<tr>
<td>
<code style="font-size:14px;"> Domain:</code>
</td>
<td>
<code style="font-size:14px;"> <span id="domain">-</span> </code>
</td>
</tr>
<tr>
<td>
<code style="font-size:14px;"> IP address:</code>
</td>
<td>
<code style="font-size:14px;"> <span id="ip">-</span> </code>
</td>
</tr>
<tr>
<td>
<code style="font-size:14px;"> Request ID:</code>
</td>
<td>
<code style="font-size:14px;"> <span id="id">-</span> </code>
</td>
</tr>
</table>
</p>
</div>
<script type="application/javascript">
function replace() {
window.location.replace('/');
}
const req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
const req_id = req.getResponseHeader('x-request-id');
const req_domain = req.getResponseHeader('host');
let req_ip = req.getResponseHeader('x-remote-ip');
const req_bt = req.getResponseHeader('nemesidawaf-bt');
if (req_bt == 6)
{
req_ip = req_ip + " (banned)";
}
if (req_bt ==7)
{
req_ip = req_ip + " (banned, bruteforce)";
}
document.getElementById('domain').innerHTML = req_domain;
document.getElementById('ip').innerHTML = req_ip;
document.getElementById('id').innerHTML = req_id;
if (req_bt != 6 & req_bt !=7)
{
setTimeout(replace,3000);
}
</script>
</div>
</div>
</body>
</html>
Depois de reiniciar o Nginx (com Nemesida WAF instalado), todas as páginas com os códigos de resposta 403 e 405 ficarão assim:
Neste caso, a página personalizada será atualizada a cada 7 segundos e se o IP do cliente não for banido, a página raiz do site retornará.
Banimento automático
Você provavelmente já ouviu ou mesmo usa sistemas de banimento automático como o Fail2ban e sabe sobre suas vantagens e desvantagens. Nemesida WAF usa um mecanismo de proibição integrado e fácil de configurar que permite definir um período de bloqueio arbitrário para hosts de servidores virtuais. O bloqueio ocorre por endereço IP, e as seguintes opções estão disponíveis para controle:
- O número de ataques de IP que levam ao bloqueio;
- Período de bloqueio;
- O host virtual para o qual os ataques são direcionados (opcional).
O parâmetro de bloqueio automático é controlado pelo parâmetro
nwaf_limit
disponível no arquivo
/etc/nginx/nwaf/conf/global/nwaf.conf
. O uso deste parâmetro será útil nos casos em que o site está sendo varrido em busca de vulnerabilidades ou ao tentar promover uma vulnerabilidade descoberta.
Enquanto listas
O trabalho do WAF baseia-se no princípio de analisar solicitações e respostas que chegam ao servidor nos casos em que contêm sinais de um ataque ou anomalias. O uso de algoritmos de aprendizado de máquina, juntamente com a tecnologia de normalização aprimorada na versão completa do Nemesida WAF, nos permite detectar tais ataques com precisão e com um número ultra mínimo de falsos positivos (cerca de 0,01%), mas na versão gratuita para reduzir o número de falsos positivos, encontramos limitações inerentes à arquitetura análise de assinatura. Assim, a versão gratuita tem mais falsos positivos, e você tem que usar listas de exclusão (ou "listas brancas") para resolver este problema. A criação de regras de exclusão também está disponível no Nemesida WAF.
Na maioria das vezes, falsos positivos aparecem quando o administrador / moderador de um recurso da web faz uma atualização ou alteração por meio da interface da web, transmitindo construções que são atípicas para o usuário no corpo da solicitação: Uma solicitação legítima será bloqueada porque contém uma entrada de função , embora tais solicitações não sejam típicas para visitantes comuns recurso da web. Nos casos em que os administradores do aplicativo não podem interagir com ele ignorando WAF, você pode adicionar o endereço IP a partir do qual eles acessam o recurso à lista de exceções ou mudar o endereço para o modo PseudoIDS (opção ) para capturar eventos sem bloqueio. Mas você deve sempre ser cuidadoso o suficiente com tais ações.
...
$html = curl_exec($ch);
curl_close($ch);
return json_decode($html,true);
...
json_decode()
nwaf_ip_lm
A propósito, Nemesida WAF permite adicionar não apenas endereços IP, mas também sub-redes, se necessário.
Conclusão
Independentemente de quão bem o código foi escrito em sua opinião, ele usa funções de filtragem de entrada e estruturas especiais como HTML Purifier, projetadas para remover, se não todo o código malicioso, então a maior parte dele, você precisa usar WAF para aumentar o nível de segurança.
Se você pretende usar o WAF pela primeira vez, ou está cansado de adições intermináveis de regras de exclusão, recomendamos experimentar o Nemesida WAF Free grátis. Para uso profissional (bloqueio de ataques complexos, ataques de força bruta, inundação de SMS; busca de vulnerabilidades; a presença de um sistema de patch virtual, etc.), é necessária uma versão completa do Nemesida WAF com um módulo de aprendizado de máquina e um scanner de vulnerabilidade. No entanto, para a maioria dos ataques não direcionados e varreduras em massa, Nemesida WAF Free será uma ferramenta boa e conveniente.
No artigo, tentei revelar as situações que mais frequentemente surgem ao usar soluções desta classe. Ficarei feliz se você lembrar mais nos comentários.