14. ModSecurity (2.6.7) en Apache

INTRODUCCIÓN


Lamentablemente los paquetes de Debian de ModSecurity corresponden a versiones un tanto ancestrales... así que vamos a proceder a instalar mod_security desde su código fuente. Seguiremos este magnifico tutorial.


INSTALACIÓN

Lo primero es bajar la ultima versión. Al momento de hacer este documento, se trata de la versión 2.6.7 desde Modsecurity-> Downloads.
Metemos el fichero en /usr/src/ y:

tar zxvf modsecurity-apache_2.6.7.tar.gz

Instalamos un par de herramientas & librerías que vamos a necesitar para instalar todo esto...

apt-get install libxml2-dev liblua5.1-0 lua5.1 apache2-threaded-dev build-essential libxml2 libxml2-dev libcurl3 libcurl3-dev

Compilamos modsecurity y lo instalamos…

cd modsecurity-apache_2.6.7
./configure
make
make install


Ahora debemos crear el archivo /etc/apache2/mods-available/mod_security2.load con el siguiente contenido:

LoadFile /usr/lib/libxml2.so
LoadFile /usr/lib/liblua5.1.so.0
LoadModule security2_module /usr/lib/apache2/modules/mod_security2.so


Hecho esto, habilitamos los módulos que usaremos.

a2enmod mod_security2
a2enmod unique_id


Configuramos lo mínimo-necesario para correr el mod-security.

cp modsecurity.conf-recommended /etc/apache2/conf.d/modsecurity.conf

Ahora bajamos el pack de reglas más actualizado desde la misma página web y lo ponemos en /etc/apache2 (en este caso, al momento de escribir este tutorial,era el modsecurity-crs_2.2.5)

cd /etc/apache2/
tar xzvf modsecurity-crs.tar.gz
mv modsecurity-crs_2.2.0 /etc/apache2/modsecurity_crs
rm -fr modsecurity-crs.tar.gz
chown root.root /etc/apache2/modsecurity_crs/ -R
cd /etc/apache2/modsecurity_crs
mv modsecurity_crs_10_config.conf.example modsecurity_crs_10_config.conf

Ahora ajustaremos la configuración de mod-security para apuntar los archivos de logs a donde queremos, e incluir el pack de reglas que acabamos de bajar. Para ello, editamos el archivo de configuración:

gedit  /etc/apache2/conf.d/modsecurity.conf

Buscamos las lineas:

# SecDebugLog /opt/modsecu
# SecDebugLogLevel 3


las descomentamos y las dejamos de la siguiente forma:

SecDebugLog /var/log/apache2/modsec_debug.log
SecDebugLogLevel 3

Luego buscamos las lineas:

# SecAuditLogType Serial
# SecAuditLog /var/log/modsec_audit.log


las descomentamos y las dejamos de la siguiente forma:

SecAuditLogType Serial
SecAuditLog /var/log/apache2/modsec_audit.log


Y al final de todo el archivo, agregamos las siguientes lineas, que servirán para cargar todas las reglas del pack que bajamos:

Include /etc/apache2/modsecurity_crs/*.conf
Include /etc/apache2/modsecurity_crs/base_rules/*.conf


Guardamos el archivo y salimos.

A continuacion preparamos los logs que vamos a usar y configuramos los permisos necesarios:

touch /var/log/apache2/modsec_debug.log
touch /var/log/apache2/modsec_audit.log
chown root.root /var/log/apache2/modsec_*
chmod 660 /var/log/apache2/modsec_*


Eso es todo, ahora podemos decirle a Apache que verifique los cambios:

apache2ctl configtest


Si todo esta OK, veremos un maravilloso:

Syntax OK

Si no es así y algo falla, deberemos revisar toda la configuración.

NO CONTINÚES HASTA VER EL “Syntax OK”!.

Ahora sí .. si todo esta bien, podemos reiniciar Apache2:

/etc/init.d/apache2 restart

MUY IMPORTANTE! Después de reiniciar, podemos mirar el errorlog de Apache, para ver si efectivamente cargó el ModSecurity.

tail /var/log/apache2/error.log

Y deberíamos ver algo similar a …

[Wed Jun 15 19:15:59 2011] [notice] ModSecurity for Apache/2.6.0 (http://www.modsecurity.org/) configured.
[Wed Jun 15 19:16:00 2011] [notice] ModSecurity: APR compiled version="1.2.12"; loaded version="1.2.12"
[Wed Jun 15 19:16:00 2011] [notice] ModSecurity: PCRE compiled version="7.6"; loaded version="7.6 2008-01-28"
[Wed Jun 15 19:16:00 2011] [notice] ModSecurity: LIBXML compiled version="2.6.32"
[Wed Jun 15 19:16:01 2011] [notice] Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny10 with Suhosin-Patch configured -- resuming normal operations


Eso es todo!  tenemos mod-security funcionando en nuestro Apache!.

Espero que os sirva.



CONFIGURACIÓN

Para configurar bien Modsecurity hay que prestar especial atención a los errores y avisos que el programa anota en los logs.
Modsecurity puede generar una gran cantidad de falsos positivos, es decir, que bloquee el acceso a nuestra página web aún cuando no haya ninguna anomalía o ataque al servidor.

Si cargamos varias páginas web desde nuestra intranet o desde el exterior veremos que modsecurity empieza a generar errores pero no bloquea ningún contenido. Recordemos que podemos ver los errores haciendo:

tail /var/log/apache2/error.log


Por defecto, ModSecurity tan solo anota en los logs, pero no efectúa bloqueos. Ello es debido a que en el fichero /etc/apache2/conf.d/modsecurity.conf la variable SecRuleEngine toma por defecto el valor DetectionOnly. Es conveniente no darle el valor On (que activa realmente Modsecurity) hasta que no estemos seguros de que todo este en orden.

Es necesario pues analizar los errores que se van generando y subsanarlos para que posteriormente Modsecurity no produzca falsos positivos.
En los errores, es necesario fijarse que regla es la se "viola". Para ello, en el error encontraremos el motivo del error, el fichero donde se encuentra la regla, y el numero de linea en el que se encuentra la regla.


Ejemplo 1

Por ejemplo, imaginemos que accedemos al servidor des de una intranet escribiendo la IP en formato numérico, por ejemplo, 192.168.0.12/index.html.
Modsecurity generara un error, pues desconfia totalmente de estos formatos. Si SecRuleEngine estuviera en On, no podriamos acceder a las webs del servidor des de intranet (suponemos que no se ha configurado un DNS...). Si miramos el error generado:

Message: Access denied with code 400 (phase 2). Pattern match "^[\d\.]+$" at REQUEST_HEADERS:Host. [file "/etc/apache2/mod-security/modsecurity_crs_21_protocol_anomalies.conf"] [line "60"] [id "960017"] [msg "Host header is a numeric IP address"] [severity "CRITICAL"] [tag "PROTOCOL_VIOLATION/IP_HOST"]

Vemos que vamos a tener que bloquear la regla que se encuentra en la linea 60 del fichero modsecurity_crs_21_protocol_anomalies.conf.
Basta con añadir un # al inicio de la regla y reiniciar apache (si es que queremos permitir el uso de IP numéricas).
Una solución mucho mejor es habilitar un servidor DNS o mas fácil aun definir las URLs en el fichero hosts tal y como explicamos en el apartado 15.

Ejemplo 2

Otro error común, aunque no tan fácil de entender, es:

Message: Rule 7f1b85aa3d18 [id "950901"][file "/etc/apache2/modsecurity_crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"][line "77"] - Execution error - PCRE limits exceeded (-8): (null).

Este se soluciona anadiendo estos conjuros al fichero modsecurity.conf:

SecPcreMatchLimit 150000
SecPcreMatchLimitRecursion 150000



Ejemplo 3


En un fichero html en el que se hay enlaces en la propia página, por motivos que desconozco produce otro error muy común:

Message: Access denied with code 403 (phase 4). Pattern match "(?:<(?:TITLE>Index of.*?<H|title>Index of.*?<h)1>Index of|>[To Parent Directory]<\\/[Aa]><br>)" at RESPONSE_BODY. [file "/etc/apache2/modsecurity_crs/base_rules/modsecurity_crs_50_outbound.conf"] [line "146"] [id "970013"] [rev "2.2.5"] [msg "Directory Listing"] [severity "ERROR"] [tag "LEAKAGE/INFO_DIRECTORY_LISTING"] [tag "WASCTC/WASC-13"] [tag "OWASP_TOP_10/A6"] [tag "PCI/6.5.6"]

En mi caso este error esta producido por ficheros html que contienen codigos </a><br>, así que hay que editar los ficheros y proceder a su corrección. El Directory Listing tambien tiene que estar bloqueado mediante otros procedimientos si se ha procedido a proteger correctamente al servidor apache contra ataques.

A veces puede ser que no toque mas remedio que desactivar una determinada regla. Por supuesto que antes de desactivar una regla es necesario pensar muy bien lo que se esta haciendo, pues de una manera u otra disminuimos la efectividad de Modsecurity. En mi caso, con estos cambios ha sido suficiente.

Para desactivar una regla para una determinada carpera o fichero, se puede añadir a modsecurity.conf instrucciones del estilo:

<LocationMatch "/wp-admin/post.php">
  SecRuleRemoveById 300015 300016 300017 950907
</LocationMatch>

<LocationMatch "/wp-includes/">
  SecRuleRemoveById 960010 960012 950006
</LocationMatch>

Cada numero corresponde al ID de cada error (se puede ver en los mensajes de error).


Otra posibilidad consiste en añadir las siguientes lineas a http.conf:

<Directory "/WhateverDirectoryIs">
<IfModule mod_security2.c>
SecRuleRemoveById 990011
SecRuleRemoveById 950004
</IfModule>
</Directory>



Si necessiteu resoldre algun dubte, poseu-vos en contacte a través d'aquest enllaç.