Prevenindo bruteforce em servidores Debian que rodam SSH e ProFTP

Publicado por Alex em 28/01/2011

[ Hits: 8.283 ]

Blog: http://linux4admins.blogspot.com/

 


Prevenindo bruteforce em servidores Debian que rodam SSH e ProFTP



Hoje eu não venho tirar dúvidas e sim compartilhar conhecimento.

Meu objetivo com esse tópico é mostrar como evitar ataques de Brute Force (força bruta) em serviços como SSH e FTP, que usam os arquivos contidos em /etc/hosts.allow ou /etc/hosts.deny e serviços que não usam TCP_WRAPPERS, como o pacote ProFTPd do Debian.

Os demais serviços que não usam /etc/hosts.allow ou /etc/hosts.deny não serão tratados, pois podem ser bloqueados com o iptables.

Presumo que o OpenSSH e o ProFTPd estejam devidamente instalados e rodando no seu sistema.

Primeiro passo

Instalar o Python, pois o BlockHosts é escrito nessa linguagem:

# aptitude install python

Depois de instalar o Python, vamos baixar com os seguintes comandos:

# wget http://www.aczoom.com/tools/blockhosts/BlockHosts-2.5.0.tar.gz
# tar xvfz BlockHosts-2.5.0.tar.gz
# cd BlockHosts-2.5.0


Para instalar o BlockHosts, use:

# python setup.py install --force

Depois de instalado, edite o /etc/clockhosts.cfg e modifique como o exemplo a seguir:

# nano /etc/blockhosts.cfg

[...]
HOSTS_BLOCKFILE = "/etc/hosts.allow"
[...]
HOST_BLOCKLINE = ["ALL: ", " : deny"]
[...]
COUNT_THRESHOLD = 3
[...]
AGE_THRESHOLD = 12
[...]
LOGFILES = [ "/var/log/auth.log", "/var/log/proftpd/proftpd.log", ]
[...]
MAIL = True
[...]
NOTIFY_ADDRESS = 'root@localhost.localdomain'
[...]
SMTP_SERVER = "localhost"
SENDER_ADDRESS = 'BlockHosts '
[...]
IPBLOCK = "iptables"
[...]

No HOSTS_BLOCKFILE podemos especificar /etc/hosts.allow ou /etc/hosts.deny. No meu caso eu escolhi o /etc/hosts.allow, mas fique a vontade para escolher entre ambos.

Na linha LOGFILES, indicamos o arquivo de log que o BlockHosts deve buscar. No caso do OpenSSH, os logs de falha de Login ficam em /var/log/auth.log e os logs do ProFTPd ficam em /var/log/proftpd/proftpd.log.

O COUNT_THRESHOLD seta o número de tentativas erradas durante o login vindas de um mesmo host e que o BlockHosts deve bloqueá-los.

Em AGE_THRESHOLD configuramos quanto tempo depois de bloqueados os hosts serão liberados.

IPBLOCK especifica se usaremos o iptables (usado nesse tutorial) ou o iproute e adicionando estes hosts em /etc/hosts.allow ou em /etc/hosts.deny, dependendo da sua escolha. Lembre-se, eu utilizei o /etc/hosts.allow.

Para editar o nosso /etc/hosts.allow ou /etc/hosts.deny, dependendo da sua escolha, faça um backup do mesmo. Edite apenas o arquivo que escolheu no inicio das configuraçoes. No meu caso copiei o /etc/hosts.allow.

# mv /etc/hosts.allow /etc/hosts.allow_orig

Crie um novo /etc/hosts.allow com o comando abaixo:

# nano /etc/hosts.allow

Copiar o conteúdo abaixo para o novo arquivo /etc/hosts.allow:

#
# hosts.allow This file describes the names of the hosts which are
# allowed to use the local INET services, as decided
# by the '/usr/sbin/tcpd' server.
#
# ----
# see "man 5 hosts_access" for details of the format of IP addresses,
#services, allow/deny options. Also see "man hosts_options"
#
# permanent whitelist addresses - this should always be allowed access

ALL: 127.0.0.1 : allow
# ALL: 192.168.0. : allow
# permanent blacklist addresses - this should always be denied access
# ALL: 10. : deny
# ----------------------------------------
# next section is the blockhosts section - it will add/delete entries in
# between the two marker lines (#---- BlockHosts Additions)
#---- BlockHosts Additions
#---- BlockHosts Additions
# ----------------------------------------
# finally, the command to execute the blockhosts script, based on
# connection to particular service or services:
sshd: ALL: spawn /usr/bin/blockhosts.py --verbose --mail --iptables \
--echo "%c-%s" --check-ip "%h" >> /var/log/blockhosts.log 2>&1 & \
: allow
#---
# add --iproute to enable null-routing, or add --iptables to enable packet
# filtering, which blocks all network communication from blocked hosts
#---
# remove >> /var/log/blockhosts.log 2>&1 if no logging to blockhosts.log
# is needed - without this, it will still log to syslog (minimally)
#sshd: ALL: spawn /usr/bin/blockhosts.py --verbose --echo "%c-%s" & : allow
#---
# above commands will use default config file - /etc/blockhosts.cfg, edit
# it as needed to specify local configuration options
# See "man hosts.allow" for info on %c and %s identifiers
# for non-verbose, with identification, to syslog only (/var/log/messages),
# triggered on any service (using ALL as first word):
#ALL: ALL: spawn /usr/bin/blockhosts.py --echo "%c-%s" & : allow
#----
# To test hosts.allow, and to find out exact names of SSH/FTP services,
# add this line to the beginning of hosts.allow, use ssh/ftp to connect
# to your server, and then look at the log (/var/log/messages or
# blockhosts.log) to see the name of the invoked service.
# IMPORTANT: after your test is done, remove this line from hosts.allow!
# Otherwise everyone will always have access.
#ALL : ALL: spawn (/usr/bin/blockhosts.py --verbose --echo "%c-%s" >> /var/log/blockhosts.log 2>&1 )& :
allow

Entendendo o arquivo e editando as regras:

Na primeira seção, insira o IP dos hosts que você quer liberar (whitelist), 127.0.0.1 por exemplo. Podemos liberar os IPs de uma sub-rede, para isso, devemos descomentar a linha # ALL: 192.168.0. : allow e adicionar duas linhas, onde serão adicionados os hosts ou ips bloqueados:

#---- BlockHosts Additions
#---- BlockHosts Additions

A seguir mostrarei uma etapa muito importante, com ela, sempre que alguém tenta fazer login usando o SSH, /usr/bin/blockhosts.py é iniciado, verifica os arquivos de log do /etc/blockhosts.cfg, e bloqueia todos os hosts com tentativas de login excedidas no COUNT_THRESHOLD, adicionando o arquivo /etc/hosts.allow e usando o resultado com o iptables que impedem esses ips ou hosts acessarem o sistema).

Todas as ações serão registradas em /var/log/blockhosts.log.

Nessa etapa, iniciaremos o BlockHosts com a opção dry-run, com isso podemos analisar se aconteceu algum erro na configuração. Usa-se o seguinte comando:

# blockhosts.py --dry-run --verbose

O sistema deve retornar um resultado como o que se segue:

# blockhosts.py --dry-run --verbose
blockhosts 2.5.0 started: 2010-08-18 14:16:56 CEST
... loaded /etc/hosts.allow, starting counts: blocked 0, watched 0
no logoffsets found, will read from beginning in logfile: /var/log/auth.log
... loading log file /var/log/auth.log, offset: 0
no logoffsets found, will read from beginning in logfile: /var/log/proftpd/proftpd.log
... loading log file /var/log/proftpd/proftpd.log, offset: 0
... discarding all host entries older than 2010-08-18 02:16:56 CEST
... final counts: blocked 0, watched 1
#---- BlockHosts Additions
#bh: ip: 192.168.0.2 : 1 : 2010-08-18 14:16:56 CEST

#bh: logfile: /var/log/auth.log
#bh: offset: 6763
#bh: first line:Feb 16 13:22:10 server1 login[1992]: pam_unix(login:session): session opened for user root
by (uid=0)

#bh: logfile: /var/log/proftpd/proftpd.log
#bh: offset: 884
#bh: first line:Feb 16 14:59:18 server1.example.com proftpd[13157] server1.example.com:
ProFTPD 1.3.1 (stable) (built Fri Feb 6 12:26:25 GMT 2009) standalone mode STARTUP

#---- BlockHosts Additions

# ----------------------------------------
# finally, the command to execute the blockhosts script, based on
# connection to particular service or services:

sshd: ALL: spawn /usr/bin/blockhosts.py --verbose --mail --iptables \
--echo "%c-%s" --check-ip "%h" >> /var/log/blockhosts.log 2>&1 & \
: allow

#---
# add --iproute to enable null-routing, or add --iptables to enable packet
# filtering, which blocks all network communication from blocked hosts
#---
# remove >> /var/log/blockhosts.log 2>&1 if no logging to blockhosts.log
# is needed - without this, it will still log to syslog (minimally)
#sshd: ALL: spawn /usr/bin/blockhosts.py --verbose --echo "%c-%s" & : allow
#---
# above commands will use default config file - /etc/blockhosts.cfg, edit
# it as needed to specify local configuration options

# See "man hosts.allow" for info on %c and %s identifiers

# for non-verbose, with identification, to syslog only (/var/log/messages),
# triggered on any service (using ALL as first word):
#ALL: ALL: spawn /usr/bin/blockhosts.py --echo "%c-%s" & : allow
#----
# To test hosts.allow, and to find out exact names of SSH/FTP services,
# add this line to the beginning of hosts.allow, use ssh/ftp to connect
# to your server, and then look at the log (/var/log/messages or
# blockhosts.log) to see the name of the invoked service.
# IMPORTANT: after your test is done, remove this line from hosts.allow!
# Otherwise everyone will always have access.
#ALL : ALL: spawn (/usr/bin/blockhosts.py --verbose --echo "%c-%s" >> /var/log/blockhosts.log 2>&1 )& :
allow

# -------------------------------------------------------------------------
Commands (tentative) to run for IPTables filtering:
... created user-defined chain blockhosts
... creating jump from INPUT to blockhosts chain
... creating jump from FORWARD to blockhosts chain
... no email to send.


Se tudo estiver ok, sem erros e nada pendente, estamos prontos para executar o BlockHosts sem a opçao --dry-run.

# blockhosts.py --verbose

O resultado será parecido com o que se segue:

# blockhosts.py --verbose
blockhosts 2.5.0 started: 2010-08-18 14:20:20 CEST
... loaded /etc/hosts.allow, starting counts: blocked 0, watched 0
no logoffsets found, will read from beginning in logfile: /var/log/auth.log
... loading log file /var/log/auth.log, offset: 0
no logoffsets found, will read from beginning in logfile: /var/log/proftpd/proftpd.log
... loading log file /var/log/proftpd/proftpd.log, offset: 0
... discarding all host entries older than 2010-08-18 02:20:20 CEST
... final counts: blocked 0, watched 1
... created user-defined chain blockhosts
... creating jump from INPUT to blockhosts chain
... creating jump from FORWARD to blockhosts chain
... no email to send.


Nesse ponto, o sistema já está parcialmente protegido, uma vez que o BlockHosts não está configurado para analisar logins falhos no ProFTPd, pois o mesmo não é um serviço TCP_WRAPPERS.

Resolvemos esse problema usando uma rotina no cron, que inicia o BlockHosts a cada 5 minutos, por exemplo.

Segundo passo

Criando um job no Cron para serviços não TCP_WRAPPERS.

Para bloquear os ips ou hosts que não usam serviços TCP_WRAPPERS, como o ProFTPd no Debian, use o seguinte comando:

# blockhosts.py --ipblock=iptables --verbose

Deve-se criar um script para automatizar essa tarefa em /usr/bin/blockhosts.py.

# nano /usr/bin/blockhosts.py

Adicione o conteúdo abaixo:

#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/usr/bin/blockhosts.py --ipblock=iptables --verbose >> /var/log/blockhosts.log 2>&1

Esse script tem o propósito de passar o PATH (caminho) correto para o script /usr/bin/blockhosts.py, pois se usá-lo diretamente no cron job, nos deparamos com erros como iptables não encontrado.

Adicione privilégio de execução ao script:

# chmod 700 /usr/local/sbin/blockhosts

Criando uma tarefa no cron com o comando a seguir:

# crontab -e

Adicione a tarefa a abaixo:

*/5 * * * * /usr/local/sbin/blockhosts &> /dev/null

Terceiro passo

Testando:

Para ver se está tudo ok e o BlockHosts está funcionando, tente logar no servidor usando SSH e FTP com um usuário e senha errados. Depois de algumas tentativas erradas, o servidor deverá refugar, o que significa que seu ip foi bloqueado. Para acessar o servidor, deve-se alterar o ip do cliente e tentar acessar o servidor novamente, com login correto e executar iptables -L.

Você poderá observar que o ip do possível atacante foi "dropado" (rejeitado).

# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
blockhosts  all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
blockhosts  all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain blockhosts (2 references)
target     prot opt source               destination
DROP       all  --  IP DO POSSIVEL ATACANTE        anywhere

Agora observe em /etc/hosts.allow que o mesmo endereço ip está listado na seção #---- BlockHosts Additions:

# nano /etc/hosts.allow

O resultado:

[...]
#---- BlockHosts Additions
ALL: 192.168.0.199 : deny
#bh: ip: 192.168.0.199 : 24 : 2010-08-18 14:37:53 CEST
#bh: ip: 192.168.0.2 : 1 : 2010-08-18 14:20:20 CEST
#bh: logfile: /var/log/auth.log
#bh: offset: 7619
#bh: first line:Feb 16 13:22:10 server1 login[1992]: pam_unix(login:session): session opened for user root
by (uid=0)
#bh: logfile: /var/log/proftpd/proftpd.log
#bh: offset: 8588
#bh: first line:Feb 16 14:59:18 server1.example.com proftpd[13157] server1.example.com: ProFTPD 1.3.1
(stable) (built Fri Feb 6 12:26:25 GMT 2009) standalone mode STARTUP
#---- BlockHosts Additions
[...]

Para finalizar, podemos observar também /var/log/blockhosts.log:

# tail /var/log/blockhosts.log
... discarding all host entries older than 2010-08-18 02:40:02 CEST
... final counts: blocked 1, watched 2
... no email to send.
blockhosts 2.5.0 started: 2010-08-18 14:45:01 CEST
... loaded /etc/hosts.allow, starting counts: blocked 1, watched 2
... loading log file /var/log/auth.log, offset: 7619
... loading log file /var/log/proftpd/proftpd.log, offset: 8588
... discarding all host entries older than 2010-08-18 02:45:01 CEST
... final counts: blocked 1, watched 2
... no email to send.


Se tudo foi feito conforme indicado, ok, tudo pronto e funcionando... considere-se com uma proteção anti-bruteForce!

Referências:
Outras dicas deste autor

SqStat - Monitorando logs do Squid em tempo real!!!

Evitando a perda de dados - Backup via rede com DD e Netcat

Leitura recomendada

Escondendo a versão do Apache

Segurança na Internet

CA confiável com certificados digitais

Iptables + honeypot + IDS

Gerador de backdoor indetectável

  

Comentários

Nenhum comentário foi encontrado.



Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts