🎨 Sysprovider Code
Sysprovider LogoWiki
🇪🇸Hosting español para ecommerce

Implementación de WAF con ModSecurity y reglas OWASP en Apache

Actualizado el 7 de junio de 2026

Introducción

En el panorama actual de amenazas cibernéticas, la seguridad de las aplicaciones web es un pilar fundamental para cualquier infraestructura de hosting. Un Web Application Firewall (WAF) actúa como una barrera de defensa en la capa de aplicación (OSI Layer 7), inspeccionando y filtrando el tráfico HTTP/HTTPS para bloquear ataques como SQL Injection, Cross-Site Scripting (XSS), Path Traversal, y Remote File Inclusion (RFI). ModSecurity, combinado con el conjunto de reglas OWASP Core Rule Set (CRS), representa la solución WAF de código abierto más madura y ampliamente adoptada para servidores Apache.

Este artículo proporciona una guía exhaustiva para implementar un WAF con ModSecurity y OWASP CRS en Apache, cubriendo desde la instalación hasta el ajuste fino para entornos de producción con alto rendimiento.

Arquitectura de ModSecurity en Apache

ModSecurity opera como un módulo de Apache (mod_security2) que se integra en el ciclo de procesamiento de peticiones. Su arquitectura se compone de:

  • Motor de procesamiento (SecRuleEngine): Decide si analizar, bloquear o solo registrar el tráfico.
  • Conjunto de reglas: Secuencias de condiciones y acciones (SecRule, SecAction) que definen el comportamiento.
  • Fases de procesamiento: Las reglas se ejecutan en fases específicas (REQUEST, REQUEST_HEADERS, REQUEST_BODY, RESPONSE, RESPONSE_HEADERS, RESPONSE_BODY, LOGGING).

Nota importante: ModSecurity no es un módulo de seguridad "plug-and-play". Sin una configuración y ajuste adecuados, puede generar falsos positivos que bloqueen tráfico legítimo o consuman recursos excesivos.

Instalación de ModSecurity en Apache

Requisitos previos

  • Apache 2.4.x con soporte para módulos dinámicos (mod_so).
  • Acceso root o sudo al servidor.
  • Sistema operativo basado en Debian/Ubuntu o RHEL/CentOS (los comandos varían ligeramente).

Instalación en Debian/Ubuntu

# Actualizar repositorios e instalar dependencias
sudo apt update
sudo apt install -y apache2 apache2-dev libapache2-mod-security2

# Habilitar el módulo
sudo a2enmod security2

# Verificar que el módulo esté cargado
sudo apachectl -M | grep security

Instalación en RHEL/CentOS 7/8

# Instalar EPEL y repositorios necesarios
sudo yum install -y epel-release
sudo yum install -y httpd httpd-devel mod_security

# Para CentOS 8/RHEL 8, usar dnf
sudo dnf install -y httpd httpd-devel mod_security

# Habilitar y arrancar Apache
sudo systemctl enable httpd
sudo systemctl start httpd

¿Por qué instalar apache2-dev o httpd-devel? Aunque no son estrictamente necesarios para la ejecución, contienen cabeceras y herramientas útiles para compilar módulos adicionales o realizar configuraciones avanzadas.

Verificación de la instalación

Crea un archivo phpinfo.php en el DocumentRoot y accede a él. Busca la sección "mod_security2" en la salida. Alternativamente:

# Crear un archivo de prueba
echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php

# Forzar una petición con un payload malicioso para probar
curl -X GET "http://localhost/info.php?param=<script>alert('XSS')</script>"

Si ModSecurity está activo pero sin reglas, verás la respuesta normal. Posteriormente, con reglas cargadas, esta petición será bloqueada.

Configuración Inicial de ModSecurity

El archivo de configuración principal se encuentra en /etc/modsecurity/modsecurity.conf (Debian) o /etc/httpd/conf.d/mod_security.conf (RHEL). La configuración mínima recomendada es:

# /etc/modsecurity/modsecurity.conf

# Activar el motor. "On" para producción, "DetectionOnly" para pruebas.

SecRuleEngine On

# Configurar el directorio de logs

SecAuditEngine RelevantOnly

SecAuditLogRelevantStatus "^(?:5|4(?!04))"

SecAuditLogParts ABIJDEFHZ

SecAuditLogType Serial

SecAuditLog /var/log/modsec_audit.log

# Configurar almacenamiento de datos persistentes

SecDataDir /tmp/modsecurity/data

# Tamaño máximo del cuerpo de la petición (en bytes)

SecRequestBodyLimit 13107200

# Tamaño máximo de archivos subidos (en bytes)

SecRequestBodyInMemoryLimit 131072

# Tiempo de espera para leer el cuerpo de la petición

SecRequestBodyReadTimeout 10

# Configuración de respuesta

SecResponseBodyLimit 524288

SecResponseBodyMimeType text/plain text/html text/xml application/json

# Desactivar la inspección de imágenes y otros binarios

SecRuleRemoveById 200000

Explicación de directivas clave

DirectivaValorPropósito
SecRuleEngine OnOn/DetectionOnly/OffEn producción, "On" bloquea. "DetectionOnly" solo logea.
SecAuditEngine RelevantOnlyRelevantOnly/On/OffLogea solo peticiones con código de estado >= 4xx o 5xx.
SecRequestBodyLimit13107200 (13 MB)Evita ataques de denegación de servicio por cuerpos enormes.
SecResponseBodyMimeTypeLista de MIMEEvita inspeccionar binarios (imágenes, videos) para ahorrar CPU.
SecDataDirRutaDirectorio para almacenar datos persistentes (IPs bloqueadas, etc.).

Alerta de rendimiento: SecResponseBodyAccess On (por defecto) permite a ModSecurity leer el cuerpo de la respuesta. Si tienes aplicaciones que generan grandes respuestas HTML/JSON, considera desactivarlo (Off) o limitar los tipos MIME inspeccionados.

Instalación de OWASP Core Rule Set (CRS)

OWASP CRS es el conjunto de reglas de referencia para ModSecurity. Proporciona protección contra las vulnerabilidades del OWASP Top 10.

Descarga y ubicación

# Crear directorio para reglas (ajustar según distribución)
sudo mkdir -p /etc/modsecurity/crs

# Descargar la última versión estable (v3.3.x al momento de escribir)
cd /tmp
wget https://github.com/coreruleset/coreruleset/archive/refs/tags/v3.3.5.tar.gz
tar -xzf v3.3.5.tar.gz

# Copiar archivos de configuración y reglas
sudo cp -r coreruleset-3.3.5/rules /etc/modsecurity/crs/
sudo cp coreruleset-3.3.5/crs-setup.conf.example /etc/modsecurity/crs/crs-setup.conf

Configuración del CRS

Edita /etc/modsecurity/crs/crs-setup.conf y ajusta los parámetros según tu entorno. Las opciones más relevantes son:

# /etc/modsecurity/crs/crs-setup.conf

# -- Configuración de bloqueo por anomalías --
# Puntuación por defecto para bloquear una petición (anomaly threshold)

SecAction \
  "id:900000,\
   phase:1,\
   nolog,\
   pass,\
   t:none,\
   setvar:tx.blocking_paranoia_level=1,\
   setvar:tx.executing_paranoia_level=1,\
   setvar:tx.anomaly_score_threshold=5,\
   setvar:tx.inbound_anomaly_score_threshold=5,\
   setvar:tx.outbound_anomaly_score_threshold=4"

# -- Umbral de paranoia --
# Nivel 1: Básico, pocos falsos positivos
# Nivel 2: Moderado, más detección
# Nivel 3: Alto, puede bloquear peticiones legítimas
# Nivel 4: Extremo, solo para pruebas

Incluir el CRS en la configuración de Apache

Crea un archivo de inclusión en el directorio de configuración de Apache:

# /etc/apache2/mods-available/security2.conf (Debian)
# o /etc/httpd/conf.d/mod_security.conf (RHEL)

<IfModule security2_module>
    # Configuración base
    IncludeOptional /etc/modsecurity/modsecurity.conf
    
    # Configuración del CRS (debe ir antes de las reglas)
    IncludeOptional /etc/modsecurity/crs/crs-setup.conf
    
    # Reglas del CRS
    IncludeOptional /etc/modsecurity/crs/rules/*.conf
</IfModule>

Orden de inclusión crucial: El archivo crs-setup.conf debe cargarse ANTES que las reglas individuales, ya que define variables de entorno (tx.*) que las reglas utilizan.

Ajuste Fino y Gestión de Falsos Positivos

Una implementación sin ajustes puede bloquear funcionalidades legítimas. El CRS permite varios mecanismos de personalización.

Paranoia Levels

NivelDescripciónRecomendación
1Reglas básicas, muy bajo falso positivoProducción inicial
2Añade reglas para ataques más específicosProducción avanzada
3Reglas muy estrictas, puede bloquear tráfico normalSolo con ajuste fino
4Máxima seguridad, bloquea casi todoSolo pruebas/staging

Para cambiar el nivel, modifica en crs-setup.conf:

setvar:tx.executing_paranoia_level=2

Reglas de Exclusión (Whitelisting)

Cuando una regla específica bloquea tráfico legítimo (falso positivo), puedes desactivarla o crear una excepción.

# Desactivar una regla específica (ejemplo: regla 942100 - SQL Injection)

SecRuleRemoveById 942100

# Desactivar para una ubicación específica
<LocationMatch "/api/legacy/">
    SecRuleRemoveById 942100
</LocationMatch>

# Crear una regla de exclusión condicional

SecRule REQUEST_URI "@beginsWith /wp-admin" \
    "id:1000,\
     phase:1,\
     pass,\
     nolog,\
     ctl:ruleRemoveById=942100"

Ajuste de Puntuación de Anomalías

El CRS asigna puntuaciones a cada regla. Cuando la suma supera el umbral (anomaly_score_threshold), la petición es bloqueada. Puedes ajustar este umbral:

# Aumentar el umbral para reducir falsos positivos
setvar:tx.inbound_anomaly_score_threshold=10

Monitoreo y Logging

Formato de Logs

ModSecurity genera logs detallados en /var/log/modsec_audit.log (o configurado). Cada entrada tiene un formato estructurado:

--a82b5a5e-A--
[01/Jan/2024:12:00:00 +0000] XXXXXXXXXX 192.168.1.1 12345 192.168.1.100 80
--a82b5a5e-B--

GET /index.php?param=<script> HTTP/1.1

Host: example.com

User-Agent: Mozilla/5.0
--a82b5a5e-F--

HTTP/1.1 403 Forbidden
--a82b5a5e-H--

Message: Warning. Pattern match "(?:\\b(?:(?:s(?:elect|cript)|...)" at ARGS:param. [file "/etc/modsecurity/crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "120"] [id "942100"]

Action: Intercepted (phase 2)
--a82b5a5e-Z--

Herramientas de Análisis

  • modsec-helper: Script para parsear logs de auditoría y resumir reglas activadas.
  • GoAccess: Puede procesar logs de Apache, pero no logs de ModSecurity directamente. Se recomienda usar mlogc (ModSecurity Log Collector) para centralizar logs.
  • ELK Stack: Ideal para entornos empresariales. Envía logs de ModSecurity a Logstash usando el formato JSON.

Para habilitar logs en JSON:


SecAuditLogFormat JSON

SecAuditLog /var/log/modsec_audit.json

Optimización del Rendimiento para Producción

ModSecurity puede consumir hasta un 30% más de CPU si no se optimiza. Estrategias clave:

1. Desactivar la inspección de recursos estáticos

# No inspeccionar imágenes, CSS, JS, etc.

SecRule REQUEST_URI "@endsWith .jpg" "phase:1,id:1,pass,nolog,ctl:ruleEngine=Off"

SecRule REQUEST_URI "@endsWith .png" "phase:1,id:2,pass,nolog,ctl:ruleEngine=Off"

SecRule REQUEST_URI "@endsWith .css" "phase:1,id:3,pass,nolog,ctl:ruleEngine=Off"

SecRule REQUEST_URI "@endsWith .js"  "phase:1,id:4,pass,nolog,ctl:ruleEngine=Off"

2. Usar SecRuleEngine DetectionOnly en fases tempranas

Si tienes un balanceador de carga (HAProxy, Nginx) que ya filtra tráfico malicioso, puedes configurar ModSecurity solo para logging en Apache y dejar el bloqueo en el balanceador.

3. Ajustar SecRequestBodyAccess

# Desactivar inspección del cuerpo de peticiones POST si no es necesario

SecRequestBodyAccess Off

Advertencia: Desactivar SecRequestBodyAccess evita la detección de ataques en el cuerpo POST (como SQLi en formularios). Solo hazlo si tienes otro mecanismo de defensa.

4. Caché de reglas (SecRuleEngine)

ModSecurity no tiene caché de reglas nativo, pero puedes usar mod_cache de Apache para servir páginas cacheadas sin pasar por el WAF.

5. Monitorear con mod_status

# Habilitar status page
<Location "/server-status">
    SetHandler server-status
    Require ip 127.0.0.1
</Location>

Luego, monitorea el uso de CPU por proceso de Apache. Si ves procesos con alta carga constantemente, revisa los logs de ModSecurity para identificar reglas costosas.

Integración con Entornos de Alta Disponibilidad

En un clúster con balanceo de carga, la configuración de ModSecurity debe ser consistente en todos los nodos. Recomendaciones:

  • Sincronizar reglas: Usa un repositorio Git centralizado y despliega con Ansible/Puppet.
  • Logs centralizados: Envía logs de auditoría a un servidor central (rsyslog, syslog-ng, Logstash).
  • Estado compartido: Si usas bloqueo por IP (mod_evasive o SecRule con IP), considera usar Redis para compartir estado entre nodos.

Ejemplo de configuración con Redis para persistencia compartida

# Instalar módulo de ModSecurity para Redis (requiere compilación)
# En la configuración de reglas

SecCollectionTimeout 600

SecConnEngine On

SecConnReadStateLimit 10

# No hay soporte nativo para Redis en ModSecurity 2.x, pero puedes usar
# scripts externos o migrar a ModSecurity 3 (libmodsecurity3) que sí lo soporta.

Troubleshooting Común

Problema: El sitio se vuelve inaccesible después de activar ModSecurity

# Verificar logs de error de Apache
tail -f /var/log/apache2/error.log

# Temporalmente desactivar el motor

SecRuleEngine DetectionOnly

# Identificar la regla conflictiva
grep "ModSecurity:" /var/log/apache2/error.log

Problema: Alto consumo de memoria

# Reducir el tamaño del búfer de respuesta

SecResponseBodyLimit 131072  # 128 KB

# Desactivar la inspección de respuestas

SecResponseBodyAccess Off

Problema: Reglas que no se aplican

# Verificar que los archivos de reglas tengan permisos de lectura
ls -la /etc/modsecurity/crs/rules/

# Verificar la sintaxis de la configuración
apachectl configtest

Conclusión

Implementar un WAF con ModSecurity y OWASP CRS en Apache es una tarea que requiere

¿Necesitas ayuda?Son dos de nuestros técnicos, Agustín y Mikel, y están disponibles para resolver cualquier problema.

Hablar con ellos ahora
Agustín y Mikel