Press "Enter" to skip to content

Case – Bloqueando um HTTP DDoS com ModSecurity, Ossec e Iptables


Recentemente tive uma experiência pra lá de interessante e estressante. Num dia que aparentava estar muito tranquilo me avisam que detectaram uma lentidão muito grande ao acessar o site de um cliente.

Verificando algumas informações do sistema detectei cerca de 14000 conexões na porta 80 o que me deixou um pouco espantando porque era uma situação totalmente atipica

netstat awt | grep 80 | wc -l
14345

Isto estava causando um crash no servidor de banco porque ele não estava conseguindo dar vazão a tantas tentativas ocorrendo simultaneamente.

1a ação – Parar o serviço respirar fundo e tentar isolar o problema.

Como neste mesmo servidor existiam outros sites inicialmente tive que detectar qual era o site alvo, após alguns testes encontrei o infame.

2a ação – Mover o site para outro servidor e substituir o ip.

Movi o site para outra máquina evitando que os outros sites fossem afetados, porém quando liberei a porta 80 para o mundo o inferno começou novamente. O load average do servidor conseguiu chegar a 300 em questão de minutos.

3a ação – Estudar o log e tomar as medidas cabiveis

Numa rápida olhada no log do apache detectei a assinatura do ataque

111.111.111.111 – – [26/Apr/2011:17:01:00 -0300] “GET /?WWW.ATARDE.COM.BR HTTP/1.0” 400 415 “-” “User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Creative AutoUpdate v1.40.02)”

O IDS da rede detectou este ataque como DOUBLE USER-AGENT attack, como ele vinha de várias origens dinamicamente, bloquear os ips era uma tarefa árdua então tive que resolver no servidor mesmo.

ESCLARECIMENTO: A vitima não era o jornal ATarde. As requisições não sei por qual razão estavam usando a URL deste jornal.

iptables

4a ação – Medidas emergenciais

Como o tempo para raciocinar era muito pouco realizei algumas tentativas não tão eficazes porém contornava um pouco essa situação

Como a assinatura do ataque não mudava foi fácil criar uma regra de iptables através de expressão regular. Ela não é de minha autoria, sou péssimo nesse quesito

tail -f /var/log/apache2/www.hackme.com.br-access.log | grep [aA][Tt][aA][rR][dD][eE] | awk ‘{print “iptables -A INPUT -s “$1″ -j REJECT”}’ | sh &

Usar o REJECT não é muito elegante em se tratando de regras de firewall porque ele aumenta o consumo de memória porém o DROP não estava funcionando.

Exemplo de uma origem ( zumbi ) bloqueada:

REJECT all — 1-48.94.187.totvs.com.br anywhere reject-with icmp-port-unreachable

Com isso tive que fazer um upgrade de memória poque o iptables estava brocando tudo.

snort

5a ação – Medidas emergenciais ( Snort+FWsnort )

Resolvi por o snort em conjunto com o fwsnort para bloquear os ataques, da um pouco de trabalho mas ele conseguiu pegar algumas origens, o problema é que o próprio ataque já estava exaurindo os recursos da máquina juntamente com o iptables e eu ainda jogo o snort+mysql+fwsnort. Ai lascou tudo, tive que voltar a prancheta.

modsecurity

6a. ação – Algumas horas depois… ModSecurity e tunning do Apache

Vocês devem estar fazendo o seguinte questionamento: “Sim. E onde entra o Ossec nisso tudo????”

O Ossec estava bloqueando porém como a assinatura do ataque era um pouco específica ele não estava bloqueando todas as origens. Tentei criar uma personal rule mas já era 03:00 da madruga e eu não estava enxergando nem raciocinando.

Com certeza com a criação da regra baseada na assinatura do ataque ele seria muito mais efetivo. Como isso não era possível no momento parti para a guerra fazendo um tunning do Apache e usando o Modsecurity.

Tunning

vim /etc/apache2/apache2.conf

ServerLimit 4000
MaxClients 4000

ModSecurity

aptitude install libapache2-mod-security2

vim /etc/apache2/conf.d/modsecurity.conf

SecRuleEngine On

SecDebugLog /var/log/apache2/modsec_debug.log
SecDebugLogLevel 0

# Serial audit log
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus ^5
SecAuditLogParts ABIFHZ
SecAuditLogType Serial
SecAuditLog /var/log/apache2/modsec_audit.log

# if there where more than 5 requests per second for this IP
# set var block to 1 (expires in 5 seconds) and increase var blocks by one (expires in an hour)
SecRule ip:requests “@eq 5” “phase:1,pass,nolog,setvar:ip.block=1,expirevar:ip.block=5,setvar:ip.blocks=+1,expirevar:ip.blocks=3600”

# if user was blocked more than 5 times (var blocks>5), log and return http 403
SecRule ip:blocks “@ge 5” “phase:1,deny,nolog,logdata:’req/sec: %{ip.requests}, blocks: %{ip.blocks}’,status:403”

# if user is blocked (var block=1), log and return http 403
SecRule ip:block “@eq 1” “phase:1,deny,nolog,logdata:’req/sec: %{ip.requests}, blocks: %{ip.blocks}’,status:403”

SecRule REQUEST_LINE “^GET?WWW.ATARDE.COM.BR$ HTTP”
“nolog,deny,setvar:ip.ddos=+1,deprecatevar:ip.ddos=100/10”

A regra abaixo foi a que bloqueou os ataques. As outras foram só para encher linguiça.

SecRule REQUEST_LINE “^GET?WWW.ATARDE.COM.BR$ HTTP” “nolog,deny,setvar:ip.ddos=+1,deprecatevar:ip.ddos=100/10”

As referências abaixo me ajudaram muito:

http://blog.cherouvim.com/simple-dos-protection-with-mod_security/
http://spamcleaner.org/en/misc/flood-http-mod_security.html
http://www.howtoforge.com/apache2_mod_security_debian_etch

Às 04:00 da madruga as coisas se estabilizaram, o acesso ao site foi normalizado e o load não passava de 1.00. Com certeza essa não foi a forma mais elegante de bloquear este tipo de ataque, acredito que um IPS na borda ajudaria muito na resolução e prevenção, porém temos que trabalhar com as ferramentas disponíveis e usar a criatividade.

8 Comments

  1. Monty Monty April 30, 2011

    Que aventura hein? :o)
    Obrigado por compartilhar esse caso. Foi muito intrutivo.

  2. Shark Shark April 30, 2011

    FDP…acabou com minha brincadeira!

  3. alexos alexos May 1, 2011

    Opa Shark

    Valeu pela companhia e força durante esse momento desesperador.
    auhuahahuahuaha

    Abs

    Alexos

  4. Rafael Gomes Rafael Gomes May 5, 2011

    Porra! Se isso acabou com o problema do ATarde realmente foi um grande feito.

    Parabéns man!

  5. Alexos Alexos May 5, 2011

    AHUAHAUHAUHAH

    Isso não foi feito no ATarde não man. Somente as requisições GET vinham com este endereço. Não sei o porque!

  6. Renato Langona Renato Langona October 10, 2011

    Como de costume, excelente artigo!

  7. alexos alexos October 12, 2011

    Valeu Renato!!

  8. Bruno Anjos Bruno Anjos December 4, 2011

    Em primeiro lugar parabéns pelo troubleshoot.
    Não sei um IPS na borda seria o mais elegante – soube de um caso de ataque deste gênero onde o IPS não ajudou muito.

Comments are closed.