Fail2Ban es un pequeño script programado en python que se encarga de observar los logs en busca de “patrones” sospechosos, y es capaz de tomar medidas para bloquear a los atacantes ya sea con iptables o lanzando un comando de nuestra elección.
Instalando Fail2Ban
Para instalarlo en CentOS, podemos instalar el repositorio de EPEL siguiendo los siguientes pasos:
rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm
Una vez instalado el repositorio, instalamos fail2ban:
yum -y install fail2ban
El directorio de configuracion de fail2ban es /ec/fail2ban/ allí encontraremos 2 directorios: action.d y filter.d.
En action.d, encontraremos las acciones que fail2ban realizará cuando alguno de nuestros filtros “cace” alguna IP haciendo maldades. Estas acciones pasan por filtrado con iptables, envio de mails de aviso etc, mientras que en filter.d, tenemos todos los filtros que utilizaremos a modo de “trampa” para cazar a nuestros atacantes.
En nuestro caso, vamos a configurar fail2ban en un servidor web, al que ultimamente se le ha detectado un alto numero de intentos de ataque de inyección, tanto SQL como XSS, y como mínimo pretendemos bloquear los accesos que hemos detectado en los logs.
Para eso tendremos que editar el fichero jail.conf del directorio /etc/fail2ban/ en este fichero tendremos todas las trampas o “jails” y sus correspondientes acciones, acompañados de unos parametros por defecto, de entrada, es recomendable que agreguemos en la linea “ignoreip” nuestra ip local, o la de algun servidor con el que podamos conectar en caso de que por error nos bloqueemos nosotros mismos.
ignoreip = 127.0.0.1 <nuestra ip>
Configura Fail2Ban
Una vez hecho esto, revisamos todas las entradas de este fichero, la primera entrada que encontramos es la de ssh, esta “jail” en nuestro caso es asi:
[ssh-iptables] enabled = true filter = sshd action = iptables[name=SSH, port=ssh, protocol=tcp] sendmail-whois[name=SSH, dest=root, sender=fail2ban@mail.com] logpath = /var/log/secure maxretry = 5
Tenemos por orden los siguientes campos:
- El nombre
- Si está habilitado
- La accion a ejecutar (una por linea), en este caso filtramos con el “action” iptables el puerto ssh y mandamos un mail con el action sendmail-whois a fail2ban@mail.com
- Indicamos el fichero de logs que leera el filtro /var/log/secure es donde logea SSH.
- Y le indicamos el numero de intentos con el que ejecutamos la accion (en este caso 5)
Nosotros no tenemos acceso SSH al exterior en nuestras máquinas de modo que vamos a dejar “enabled=false“, y procederemos a configurar las siguientes “jails” que si que son interesantes para el servicio web:
[apache-tcpwrapper] enabled = true filter = apache-auth action = hostsdeny logpath = /var/www/vhosts/*/statistics/logs/error_log maxretry = 6 [apache-badbots] enabled = true filter = apache-badbots action = iptables-multiport[name=BadBots, port="http,https"] sendmail-buffered[name=BadBots, lines=5, dest=you@mail.com] logpath = /var/www/vhosts/*/statistics/logs/access_log bantime = 172800 maxretry = 1 # Para prevenir ataques de inyeccion de codigo [php-url-fopen] enabled = true port = http,https filter = php-url-fopen logpath = /var/www/vhosts/*/statistics/logs/access_log maxretry = 1 # Evitamos ataques de ips que accedan a urls que contengan passthru o system o similares [apache-hacks] enabled = true port = http,https filter = apache-hacks action = iptables-multiport[name=AtaqueApache, port="http,https"] sendmail-buffered[name=AtaqueApache, lines=5, dest=you@mail.com] logpath = /var/www/vhosts/*/statistics/logs/access_log maxretry = 3
Lo realmente importante aqui, es cambiar las lineas logpath, ya que nuestro servidor es un plesk la ruta de los logs es “/var/www/vhosts/*/statistics/logs/access_log” o “/var/www/vhosts/*/statistics/logs/error_log” el resto, son cambios en el mail de destino al que mandaremos el mail, y los nombres de los filtros a aplicar, nosotros aplicamos estos:
apache-tcpwrapper:
Bloquea con el fichero /etc/hosts.deny los hosts que se intentan conectar a dominios protegidos con contraseña (estos fallos de autenticación aparecen en el error_log)
apache-badbots
Bloquea por iptables los hosts que se conectan haciendo uso de un “User Agent” sospechoso, y nos envia un mail para avisarnos.
php-url-fopen
Bloqueamos los hosts, que intentan una inyeccion de código del tipo: GET /index.php?n=http://www.dominio.com/fichero.htm
apache-hacks
Bloquea los hosts que acceden a urls sospechosas, haciendo un SCAN o directamente acceden a urls intentando inyectar llamadas al sistema desde php (system, passthru…) esta regla se va rellenando con las expresiones que vamos encontrando en los logs, al final del post, adjuntamos el contenido del filtro en nuestro caso.
En el ultimo caso, hemos creado un fichero apache-hacks.conf en el directorio filters.d, para empezar podemos agregar entradas como estas:
failregex = ^<HOST> -.*”(GET|POST).*?.*passthru.* HTTP/.*$
^<HOST> -.*”(GET|POST).*?.*system.* HTTP/.*$
Y mas adelante agregar nuevas reglas.
Con estos 4 casos, podemos evitar algunos de los intentos de ataque mas comunes, pero no podemos ni por un momento pensar que con solo aplicar esto estamos a salvo.
En otro post vamos a explicar las medidas de seguridad básicas que todo servidor de alojamiento tiene que aplicar para no ser demasiado vulnerable, mod_security, apache ITK, Hardening de PHP, SuHoshin…
Hola, podrias indicarme lo que hay que poner en el fichero apache-hacks.conf, porque al copiar la entrada que pones me da error al recargar la pagina. Gracias
Hola Jose Miguel,
Has comprobado que el fichero tenga una única expresión regular por linea? te da algun mensaje el fichero de logs (/var/log/fail2ban.log)?
Saludos!
Hola de nuevo, gracias por contestar tan ràpido. Te pongo el error que me da
File “/usr/bin/fail2ban-client”, line 400, in
if client.start(sys.argv):
File “/usr/bin/fail2ban-client”, line 369, in start
return self.__processCommand(args)
File “/usr/bin/fail2ban-client”, line 201, in __processCommand
ret = self.__readConfig()
File “/usr/bin/fail2ban-client”, line 374, in __readConfig
ret = self.__configurator.getOptions()
File “/usr/share/fail2ban/client/configurator.py”, line 68, in getOptions
return self.__jails.getOptions(jail)
File “/usr/share/fail2ban/client/jailsreader.py”, line 67, in getOptions
ret = jail.getOptions()
File “/usr/share/fail2ban/client/jailreader.py”, line 79, in getOptions
ret = self.__filter.read()
File “/usr/share/fail2ban/client/filterreader.py”, line 56, in read
return ConfigReader.read(self, “filter.d/” + self.__file)
File “/usr/share/fail2ban/client/configreader.py”, line 62, in read
SafeConfigParserWithIncludes.read(self, [bConf, bLocal])
File “/usr/share/fail2ban/client/configparserinc.py”, line 108, in read
fileNamesFull += SafeConfigParserWithIncludes.getIncludes(filename)
File “/usr/share/fail2ban/client/configparserinc.py”, line 79, in getIncludes
parser.read(resource)
File “/usr/lib64/python2.6/ConfigParser.py”, line 286, in read
self._read(fp, filename)
File “/usr/lib64/python2.6/ConfigParser.py”, line 482, in _read
raise MissingSectionHeaderError(fpname, lineno, line)
ConfigParser.MissingSectionHeaderError: File contains no section headers.
file: /etc/fail2ban/filter.d/apache-hacks.conf, line: 2
‘failregex = ^ -.*xe2x80x9d(GET|POST).*\?.*passthru.* HTTP\/.*$n’
Y he copiado y pegado el texto que tu tienes en tu blog, en dos lineas y tambien lo que he puesto en jail.local
[apache-hacks]
enabled = true
port = http,https
filter = apache-hacks
action = iptables-multiport[name=AtaqueApache, port=”http,https”]
sendmail-buffered[name=AtaqueApache, lines=5, dest=XXXXX@XXXX.XXX]
logpath = /var/www/vhosts/*/statistics/logs/access_log
maxretry = 3
Gracias por tu ayuda
Hola,
Creo que el error es que el fichero apache-hacks.conf no tiene la estructura de un fichero de configuracion fail2ban válido, en el post solo he puesto las lineas relativas a la expresión regular, el fichero completo seria algo asi (es posible que tu error sea que falta el [definition] del principio):
# Fail2Ban configuration file
[Definition]
# Option: failregex
# Notes.: regex to match this kind of request:
failregex = ^ -.*”(GET|POST).*?.*passthru.* HTTP/.*$
^ -.*”(GET|POST).*?.*system.* HTTP/.*$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
ignoreregex =
Gracias, ya me funciona. Es cierto no habia puesto el [definition]
y esa era el problema. Que tonteria de fallo.
Un saludo
Just a tip: you can also put that code in a RC file for the Python console, so you can acsecs your lp object in every Python console, without needing to run lpshell .
Hola, perdoname de nuevo, pero no me habia dado cuenta de este error
fail2ban.filter : ERROR No ‘host’ group in ‘^ -.*”(GET|POST).*?.*passthru.* HTTP/.*$’
fail2ban.filter : ERROR No ‘host’ group in ‘^ -.*”(GET|POST).*?.*system.* HTTP/.*$’
Gracias de nuevo
Tengo el mismo problema de Jose Miguel..
Alguna solucion
Hola,
El problema es que en mi comentario he pegado la expresión regular del post sin el tag “<HOST>” que es obligatorio, prueba con la expresión regular siguiente:
failregex = ^<HOST> -.*”(GET|POST).*?.*passthru.* HTTP/.*$
^<HOST> -.*”(GET|POST).*?.*system.* HTTP/.*$
Un saludo!
Podrian mostrar una configuracion para servodor de corre en Zimbra 5