jueves, 6 de marzo de 2014

Protegiendo nuestro servidor con fail2ban - Parte 1 "Protegiendo SSH"

Hoy les traigo una aplicación muy interesante que nos ayudará a proteger nuestro servidor. Es un hecho que si nuestro servidor está en internet, se encuentra expuesto todo el tiempo a un sin número de robots que buscan huecos por donde colarse (desde scanners de sitios web, hasta ataques de diccionario a cuentas de usuarios). Esta aplicación se llama Fail2ban.

El funcionamiento de Fail2ban es muy sencillo y se puede resumir en los siguientes pasos:

1-Lectura de logs y comparación con expresiones regulares
2-Aplicación de una acción por un tiempo determinado
3-Remoción de la acción una vez pasado el tiempo

Entonces se puede decir que Fail2ban nos presenta una forma sencilla de detectar patrones en los logs y tomar acciones en consecuencia, acciones que luego pueden ser revertidas. Estas acciones pueden ser desde aplicar reglas en el firewall, enviar un correo electrónico, reiniciar un servicio, lo que sea que precisen.

En esta "Parte 1" vamos a ver cómo instalarlo y configurarlo para proteger nuestro servidor de ataques de diccionario al servicio SSH.

La instalación es sencilla ya que se encuentra en los repositorios de prácticamente cualquier distro, en este caso usamos Ubuntu 12.04.4 LTS

root@ubuntu:~# apt-get install -y fail2ban

Una vez instalado podemos ver los archivos de configuración ubicados en /etc/fail2ban

root@ubuntu:~# ls /etc/fail2ban/
action.d  fail2ban.conf  filter.d  jail.conf
root@ubuntu:~# 

fail2ban.conf: contiene los parámetros generales de configuración del servicio, como las opciones de logging.
jail.conf: aquí es donde definiremos las jaulas (jails) que fail2ban procesará. El archivo se encuetra divido en la etiqueta [DEFAULT] que contiene variables generales que aplican a todas las jails y luego una etiqueta del tipo [JAIL_NAME] por cada jail creada. Una jail está compuesta mínimamente por las variables enabled, port, filter y logpath, además se puede sobreescribir las variables del tag [DEFAULT] para personalizar aún mas la jaula. 
action.d: en este directorio se encuentran los archivos que definen las acciones disponibles a tomar dentro de las jails.
filter.d: en este directorio se encuentran los filtros disponibles para utilizar en las jails.

El jail que utilizaremos es el llamado ssh, cuya configuración es:

[ssh]

enabled  = true
port     = ssh
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 6

enabled: nos permite activar y desactivar el jail de manera sencilla, solo admite el valore true o false.
port: indica el puerto del servicio que se está queriendo proteger, en este caso ssh es luego reemplazado por 22.
filter: define el archivo (dentro de /etc/fail2ban/filter.d) que contendrá las expresiones regulares que se utilizaran para esta jaula. Las expresiones regulares nos permitiran definir qué tipo de logs serán una detección positiva de un problemas (failregex) y cuales no (ignoreregex).
logpath: esta variable indica el archivo de donde se leerán los logs a analizar. Ubuntu envía los logs de autenticación al archivo /var/log/auth.log, por lo tanto es el archivo indicado.
maxretry: indica la cantidad de veces que se aceptarán coincidencias en las expresiones regulares de la jaula, cuando este límite se alcanza, dentro del margen de tiempo (variable XXX) se ejecutará la acción definida para la jaula (en este caso XXX).

Como se podrán imaginar nos faltan algunas cosas, si recuerdan uno de los pasos del funcionamiento de fail2ban consistía en ejecutar una acción y en este jail no vemos nada de esto. Esto se debe a que estamos utilizando la acción poder defecto provista por el tag [DEFAULT], esta acción se encargará de insertar en el firewall una regla que denegará el acceso a puerto SSH a la IP que haga un número excesivo de intentos de acceso fallidos. Cuál es el número excesivo? 6, como indica la variable maxretry de la jail ssh. Otro valor interesante y que no se encuentra especificado entre los valores default, es el intervalo de tiempo que se analizará. Este intervalo está definido por la variable findtime (valor por defecto 600 segundos), de esta forma podemos indicarle al jail que busque intentos fallidos de logs en los últimos 600 segundos (10 minutos) y que si encuentra mas de 6 de una misma IP aplique la acción default.

Antes de comenzar a probar el funcionamiento reiniciemos el servicio para corroborar que esté todo funcionando correctamente:

root@ubuntu:/home/juan# service fail2ban restart
 * Restarting authentication failure monitor fail2ban                    [ OK ] 
root@ubuntu:/home/juan# 

Excelente! Ahora podemos ver que fail2ban agregó una nueva cadena a iptables:

root@ubuntu:/home/juan# iptables-save 
# Generated by iptables-save v1.4.12 on Thu Mar  6 05:10:23 2014
*filter
:INPUT ACCEPT [41:3079]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [23:2444]
:fail2ban-ssh - [0:0]
-A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh
-A fail2ban-ssh -j RETURN
COMMIT
# Completed on Thu Mar  6 05:10:23 2014
root@ubuntu:/home/juan#

fail2ban-ssh es la cadena correspondiente al jail ssh y es donde se insertarán las IPs que sean detectadas como peligrosas por el jail.

No mas teoría xD, probemos si realmente funciona (recuerden que no hemos cambiado absolútamente nada en el archivo jail.conf). Nuestro escenario de prueba consiste en las IPs:

172.16.62.149 - servidor a proteger ubuntu
172.16.62.1 - atacante moon

Supongamos que el atacante ya hizo un escaneo previo de la red y encontró varias direcciones IP con el servicio SSH escuchando en el puerto 22. Una de esas direcciones es nuestro servidor, asumiendo que los usuarios suelen usar contraseñas débiles, el paso siguiente sería comenzar a probar pares usuario/contraseña hasta que eventualmente adivine alguno y consiga acceso.

Simulamos un robot haciendo 6 intentos fallidos de autenticación de la siguiente manera:

juan@moon:~$ ssh pepe@172.16.62.149
pepe@172.16.62.149's password: 
Permission denied, please try again.
pepe@172.16.62.149's password: 
Permission denied, please try again.
pepe@172.16.62.149's password: 
Permission denied (publickey,password).
juan@moon:~$ ssh pepe@172.16.62.149
pepe@172.16.62.149's password: 
Permission denied, please try again.
pepe@172.16.62.149's password: 
Permission denied, please try again.
pepe@172.16.62.149's password: 
Connection closed by 172.16.62.149
juan@moon:~$ 

como pueden ver, luego del sexto intento fallido hemos perdido acceso al puerto 22.
Desde el servidor podemos ver claramente la nueva regla que fue agregada a iptables:

root@ubuntu:/home/juan# iptables-save 
# Generated by iptables-save v1.4.12 on Thu Mar  6 05:10:23 2014
*filter
:INPUT ACCEPT [41:3079]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [23:2444]
:fail2ban-ssh - [0:0]
-A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh
-A fail2ban-ssh -s 172.16.62.1/32 -j DROP
-A fail2ban-ssh -j RETURN
COMMIT
# Completed on Thu Mar  6 05:10:23 2014
root@ubuntu:/home/juan#

la regla descarta expecíficamente los paquetes de origen 172.16.62.1 que se dirijen al puerto 22. La forma correcta de ver en qué estado se encuentra una jail en particular es la siguiente:

root@ubuntu:/home/juan# fail2ban-client status ssh
Status for the jail: ssh
|- filter
|  |- File list: /var/log/auth.log 
|  |- Currently failed: 1
|  `- Total failed: 7
`- action
   |- Currently banned: 1
   |  `- IP list: 172.16.62.1
   `- Total banned: 1
root@ubuntu:/home/juan# 

Bien, funciona!! pero qué sucedió?

Escencialmente lo que sucedió fue lo siguiente:

-La jail ssh estaba pendiente de los logs que se escribían en /var/log/auth.log
-En un momento determinado detecto que en los últimos 5 minutos alguien había realizado al menos 6 intentos fallidos de login al servidor. Esto lo podemos ver fácilmente acá:

root@ubuntu:/home/juan# cat /var/log/auth.log |grep "Failed password"
Mar  6 04:39:26 ubuntu sshd[976]: Failed password for juan from 172.16.62.1 port 37492 ssh2
Mar  6 05:13:28 ubuntu sshd[1514]: Failed password for invalid user pepe from 172.16.62.1 port 37539 ssh2
Mar  6 05:13:31 ubuntu sshd[1514]: Failed password for invalid user pepe from 172.16.62.1 port 37539 ssh2
Mar  6 05:13:35 ubuntu sshd[1514]: Failed password for invalid user pepe from 172.16.62.1 port 37539 ssh2
Mar  6 05:13:40 ubuntu sshd[1516]: Failed password for invalid user pepe from 172.16.62.1 port 37542 ssh2
Mar  6 05:13:43 ubuntu sshd[1516]: Failed password for invalid user pepe from 172.16.62.1 port 37542 ssh2
root@ubuntu:/home/juan# 

-Aplicó la acción correspondiente a la jail, esto lo podemos ver en el archivo de logs de fail2ban (/var/log/fail2ban.log)

...
2014-03-06 05:13:42,764 fail2ban.actions: WARNING [ssh] Ban 172.16.62.1
...

-Diez minutos después fail2ban quita la regla del firewall y todo vuelve a la normalidad

...
2014-03-06 05:23:43,610 fail2ban.actions: WARNING [ssh] Unban 172.16.62.1
...

Como verán, su funcionamiento es sencillo. Si abren el archivo /etc/fail2ban/filter.d/sshd.conf podrán ver las distintas expresiones regulares que serán consideradas como ataques,  una de ellas es:


 ^%(__prefix_line)sFailed (?:password|publickey) for .* from (?: port \d*)?(?: ssh\d*)?$

Algunas consideraciones sobre esta implementación:


-Frena a los atacantes por solo 10 minutos (se podría incrementar este valor sin complicaciones), lo cual a veces es mas que suficiente para engañar a los robots y hacerles creer que el host se apagó y que no deberían perder tiempo intentando.
-No protege a usuarios con claves triviales como usuario juan y password juan, y demás cosas que pueden ser adivinadas en unos pocos intentos.

Recomendaciones:

-Si administras servidores utilizando SSH, usa un par de claves pub/priv en lugar de contraseña.
-No permitir el acceso de root por SSH.

Veremos que se me ocurre para la parte 2!!! Saludos!

No hay comentarios:

Publicar un comentario