fail2ban: Evitando ataques en nuestro servidor web

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.

Para instalarlo en , 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>

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…


Etiquetas: , ,

10 Responses to “fail2ban: Evitando ataques en nuestro servidor web”

  1. Jose Miguel dice:

    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

    • raul dice:

      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!

  2. Jose Miguel dice:

    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 = ^ -.*\xe2\x80\x9d(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

    • raul dice:

      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 =

      • Jose Miguel dice:

        Gracias, ya me funciona. Es cierto no habia puesto el [definition]
        y esa era el problema. Que tonteria de fallo.

        Un saludo

        • Lazat dice:

          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 .

      • Jose Miguel dice:

        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

        • CapLinux dice:

          Tengo el mismo problema de Jose Miguel..

          Alguna solucion

          • raul dice:

            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!

  3. Eddy dice:

    Podrian mostrar una configuracion para servodor de corre en Zimbra 5

Comentar