Prevenindo bruteforce em servidores Debian que rodam SSH e ProFTP

Publicado por Alex em 28/01/2011

[ Hits: 8.294 ]

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

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

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

Leitura recomendada

Desativar o Ctrl+Alt+Del (reboot)

Projeto Root - Senhas seguras com o KeePass

Resetar senha de root no Debian Squeeze

Docker - API Autenticada

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

  

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