Wazuh criando regra no pfSense para bloquear IP de atacante

O cenário é o seguinte:

  • Debian Bullseye versão 5.10.92-1 com wazuh-manager 4.2.5-1 e elasticsearch, kibana e filebeat nas versões 7.14.2
  • pfSense CE 2.6.0-RELEASE
  • Ambos os servidores acima foram virtualizados em VirtualBox 6.1.32-2 em Arch Linux 5.16.13-arch1-1
  • O artigo parte do princípio que o wazuh-manager e o pfSense já estejam instalados, configurados e funcionais, como descrito acima
  • IP do servidor com wazuh-manager: 10.0.2.201/24
  • IP do servidor com pfSense: 10.0.2.200/24

..::| Instalando o agente no pfSense

Pra facilitar o trabalho de fazer as configurações no pfSense, habilite o acesso via SSH nesse servidor, indo em System -> Advanced -> marque a opção “Enable Secure Shell”:

Acesse o pfSense via SSH com o usuário root e instale o agente do Wazuh para FreeBSD 12 (base do pfSense):

pkg add https://pkg.freebsd.org/FreeBSD:12:amd64/quarterly/All/wazuh-agent-4.1.5.pkg

Configure o agente do Wazuh, editando o arquivo /var/ossec/etc/ossec.conf e alterando a palavra “IP” dentro da tag “<address>IP</address>” para o IP do servidor do Wazuh (debian), que nesse artigo é o 10.0.2.201, ficando assim:

Salve e saia do arquivo.

Agora vá na interface web do pfSense e instale a package “Shellcmd” para fazer com que o wazuh-agent inicie no boot desse servidor. Vá em System -> Package Manager -> Available Packages, procure por “Shellcmd” e o instale.

Depois de instalado, acesse-o em Services -> Shellcmd.

Clique no botão “+ Add” e preencha o campo “Command” com “/usr/local/etc/rc.d/wazuh-agent start” e depois clique me “Save”.

Agora crie uma regra para o agente se conectar com o wazuh-manager, indo em Firewall -> Rules -> LAN -> ADD e preencha da seguinte forma:

Lembre-se de substituir o IP 10.0.2.201 pelo do servidor onde está o wazuh-manager na sua arquitetura

Salve e aplique a regra. Tome cuidado para que ela não seja bloqueada por uma possível outra regra de bloqueio antes dessa.

Agora volte ao terminal conectado via SSH e habilite o agente:

/usr/local/etc/rc.d/wazuh-agent enable

Inicie o agente:

/usr/local/etc/rc.d/wazuh-agent start

Verifique se o agente iniciou normalmente:

/usr/local/etc/rc.d/wazuh-agent onestatus

Agora no painel do Wazuh, verifique se o novo agente se conectou ao servidor, indo no menu do Wazuh -> Management -> Status:

..::| Script de bloqueio

Agora volte para a conexão SSH com o servidor do pfSense para criarmos um script que será responsável pela criação de regras de bloqueio com base em regras acionadas no wazuh-manager.

Crie o arquivo /var/ossec/active-response/bin/easyrule-pf.sh com o seguinte conteúdo:

#!/bin/sh
# Script para adicionar IPs bloqueados pelo Wazuh no pfSense dentro do aliase "EasyRuleBlockHosts"
# Expect: srcip
# Author: Marcius da C. Silveira
# Last modified: Mar 3, 2022

ACAO=$1
USUARIO=$2
IP=$3


# logando as atividades desse script
echo "`date` $0 $1 $2 $3 $4 $5" >> /var/ossec/logs/active-responses.log


# Erro se o IP nao for mencionado nos argumentos
if [ "x${IP}" = "x" ]; then
   echo "$0: Falta o IP no terceiro argumento <acao> <usuario> (IP)"
   exit 1;
fi


# Coletando os nomes das interfaces do pfSense
INTF=`/usr/local/bin/xmllint --xpath 'pfsense/interfaces/child::*' /conf/config.xml | grep '^<' | tr -d '<' | tr -d '>'`
QTDINTF=`echo ${INTF} | wc -w`
# a ACAO sera feita para cada interface coletada acima
# caso deseje executar a ACAO para interfaces especificas, especifique elas na varialvel INTF colocando espacos entre cada uma, por exemplo:
# INTF="wan lan"
while [ ${QTDINTF} != 0 ]; do
	IF=`echo ${INTF} | cut -d ' ' -f ${QTDINTF}`
	# Se o argumento ACAO for "add"
	if [ "x${ACAO}" = "xadd" ]; then
		/usr/local/bin/easyrule	block $IF "${IP}"
	# Se o argumento ACAO for "delete"
	elif [ "x${ACAO}" = "xdelete" ]; then
		/usr/local/bin/easyrule unblock $IF "${IP}"

	# Se o argumento ACAO for invalido
	else
	   echo "$0: acao invalida: ${ACAO}"
	fi
 	QTDINTF=$((QTDINTF-1))
done

exit 1;

Dê as permissões 750 para esse arquivo:

chmod 750 /var/ossec/active-response/bin/easyrule-pf.sh

Reinicie o agente:

/usr/local/etc/rc.d/wazuh-agent restart

Agora vá até o servidor Debian onde está o wazuh-manager, e edite o arquivo /var/ossec/etc/ossec.conf acrescentando, depois do último “</command>“, o seguinte conteúdo:

  <command>
    <name>easyrule-pfsense</name>
    <executable>easyrule-pf.sh</executable>
    <timeout_allowed>yes</timeout_allowed>
  </command>

  <active-response>
    <command>easyrule-pfsense</command>
    <location>defined-agent</location>
    <agent_id>001</agent_id>
    <rules_id>5758</rules_id>
    <disabled>no</disabled>
  </active-response>

Nesse exemplo acima eu especifiquei o agente recém instalado no pfSense, cujo o código é 001. Caso queira que mais de um agente execute a ação de criar regras de bloqueio, adicione os códigos desses agentes os separando por uma vírgula (por exemplo: <agent_id>001,009,021</agent_id>). Nesse caso, lembre-se de colocar o script “easyrule-pf.sh” nesses outros servidores também, como descrito acima, assim como configurar suas permissões.

Aqui nesse exemplo eu também especifiquei uma regra que, quando acionada em algum ataque, irá executar o script “easyrule-pf.sh” no(s) agente(s) configurado(s) em “<agent_id>“. É possível colocar, ao invés de apenas uma regra, várias delas também as separando por vírgula, ou também um grupo de regras, mas nesse caso não se usa as tags “<rules_id></rules_id>“, e sim “<rules_group></rules_group>“, inserindo os nomes dos grupos que pretende usar (por exemplo: <rules_group>authentication_failed|authentication_failures</rules_group>). Mais informações sobre as possibilidades de configuração dos tipos de gatilhos você encontra aqui.

Reinicie o wazuh-manager:

systemctl restart wazuh-manager

..::| Testando

No exemplo acima, especifiquei uma regra cuja sua configuração detecta várias tentativas de login via SSH em um servidor. Para testar se o script que adiciona IP à regras de bloqueio no pfSense está funcionando, desabilitei a proteção SSH do pfSense indo em System -> Advanced, na primeira aba chamada “Admin Access“, e logo abaixo em “Login Protection” adicionei o IP da minha máquina no campo “Pass list“, para que o pfSense permita que eu faça várias tentativas de login pelo SSH ao invés de me bloquear automaticamente por ele mesmo.

Agora tente se conectar várias vezes seguidas via SSH com uma senha errada, para testar se a regra 5758 será acionada fazendo com que o active-response configurado acima crie uma regra de bloqueio nas abas de cada interface de rede do pfSense.

Veja que o script easyrule-pf.sh, usado no active-response, funcionou perfeitamente. Foi criada uma regra de bloqueio e um aliase chamado “EasyRuleBlockHosts” seguido do nome da interface, onde nele irá constar os IPs passados pelo wazuh-manager quando acionada a regra especificada nas configurações do active-response.

..::| Anti-lockout

Um detalhe importante, que deve ser observado, é quanto a regra criada na aba LAN:

Veja que o sistema “Anti-Lockout“, que por padrão vem ativado no pfSense para evitar que o administrador desse sistema não seja impedido de acessá-lo, ficará sempre em primeiro na lista de regras dessa aba. Como o teste que fiz acima era justamente para bloquear um acesso via SSH partindo de um IP na rede LAN do pfSense, a máquina usada no ataque não ficará bloqueada de fato, por conta desse “Anti-Lockout“.

Uma solução nesse caso é criar uma regra de liberação da porta 80 ao pfSense, colocando em primeiro na lista da aba LAN, acima da regra de bloqueio que usa o aliase “EasyRuleBlockHostsLAN“, assim:

Observe que a regra deve ficar sempre na primeira posição, e em segundo a regra criada pelo “easyrule-pf.sh

Depois desative o sistema “Anti-Lockout” (em System -> Advanced -> marcar a opção “Disable webConfigurator anti-lockout rule“). Nesse momento você notará que não haverá mais aquela regra padrão no topo da aba LAN, ficando parecida com a imagem acima.

..::| Conclusão e considerações finais

Com essa técnica será possível ter uma blacklist própria com base em ataques direcionados a sua rede, e replicar para todos os seus gateways o IP do atacante, bloqueando-o antes que o mesmo tente um novo ataque por outros caminhos.

É importante lembrar também que os IPs de atacantes, na maioria das vezes, não são sempre os mesmos. Ou seja, depois de alguns dias as operadoras fornecem um novo IP para seus usuários, e isso pode implicar em bloqueios errados, pois um cliente da sua empresa pode acabar recebendo um IP que foi usado recentemente em um ataque, impossibilitando-o de acessar um servidor da sua rede, por exemplo.

Por isso, é importante colocar um tempo de bloqueio para cada IP, e após esses dias tirá-lo dos aliases das regras criadas pelo “easyrule-pf.sh“. Isso é configurável através da opção “<timeout>” dentro do “<active-response></active-response>” no “/var/ossec/etc/ossec.conf” dentro do servidor do wazuh-manager, e colocar um valor em segundos (por exemplo, para 8 dias de bloqueio: <timeout>691200</timeout>).

Fontes:
https://techviewleo.com/how-to-install-wazuh-server-on-debian/
https://documentation.wazuh.com/
https://groups.google.com/g/wazuh/c/pc4IAOIjW-E?pli=1
https://freebsd.pkgs.org/12/freebsd-amd64/wazuh-agent-4.1.5.pkg.html
https://docs.netgate.com/pfsense/en/latest/development/boot-commands.html
https://documentation.wazuh.com/current/user-manual/capabilities/active-response/how-it-works.html#active-response-configuration
https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/active-response.html#reference-ossec-active-response