ModSecurity ist eine Open-Source Web Application Firewall (WAF). Sie schützt Webanwendungen vor SQL Injection, Cross-Site Scripting (XSS) und vielen anderen Angriffen.

Installation

Debian/Ubuntu

# ModSecurity für Apache
apt install libapache2-mod-security2

# Modul aktivieren
a2enmod security2

# Core Rule Set (CRS)
apt install modsecurity-crs

systemctl restart apache2

CentOS/RHEL

dnf install mod_security mod_security_crs

systemctl restart httpd

Grundkonfiguration

ModSecurity aktivieren

# Konfiguration kopieren
cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

# Aktivieren
vi /etc/modsecurity/modsecurity.conf
# /etc/modsecurity/modsecurity.conf

# Detection Mode (nur logging)
SecRuleEngine DetectionOnly

# Oder Blocking Mode (aktiver Schutz)
SecRuleEngine On

# Request Body Inspection
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072

# Response Body Inspection
SecResponseBodyAccess On
SecResponseBodyLimit 524288

# Debug Log
SecDebugLog /var/log/apache2/modsec_debug.log
SecDebugLogLevel 0

# Audit Log
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/apache2/modsec_audit.log

# Temporäre Dateien
SecTmpDir /tmp
SecDataDir /var/cache/modsecurity

Apache-Konfiguration

# /etc/apache2/mods-enabled/security2.conf

<IfModule security2_module>
    SecDataDir /var/cache/modsecurity
    IncludeOptional /etc/modsecurity/*.conf
    Include /usr/share/modsecurity-crs/crs-setup.conf
    Include /usr/share/modsecurity-crs/rules/*.conf
</IfModule>

OWASP Core Rule Set (CRS)

CRS konfigurieren

# /usr/share/modsecurity-crs/crs-setup.conf

# Paranoia Level (1-4)
SecAction "id:900000,phase:1,nolog,pass,t:none,setvar:tx.paranoia_level=1"

# Anomaly Scoring
SecAction "id:900110,phase:1,nolog,pass,t:none,setvar:tx.inbound_anomaly_score_threshold=5"
SecAction "id:900120,phase:1,nolog,pass,t:none,setvar:tx.outbound_anomaly_score_threshold=4"

# Erlaubte HTTP-Methoden
SecAction "id:900200,phase:1,nolog,pass,t:none,setvar:'tx.allowed_methods=GET HEAD POST OPTIONS'"

# Content-Types
SecAction "id:900220,phase:1,nolog,pass,t:none,setvar:'tx.allowed_request_content_type=application/x-www-form-urlencoded|multipart/form-data|text/xml|application/xml|application/json'"

Paranoia Levels

| Level | Beschreibung | |-------|--------------| | 1 | Basis-Schutz, wenige False Positives | | 2 | Erweitert, mehr Regeln | | 3 | Streng, mehr False Positives | | 4 | Paranoid, viele False Positives |

Regeln verstehen

Regel-Syntax

SecRule VARIABLE OPERATOR [ACTIONS]

# Beispiel
SecRule ARGS "@contains <script>" "id:1001,phase:2,deny,status:403,msg:'XSS Attack'"

Wichtige Variablen

| Variable | Beschreibung | |----------|--------------| | ARGS | Request-Parameter | | REQUEST_HEADERS | Request-Header | | REQUEST_URI | Request-URL | | REQUEST_BODY | Request-Body | | RESPONSE_BODY | Response-Body | | REMOTE_ADDR | Client-IP | | TX | Transaktionsvariablen |

Operatoren

| Operator | Beschreibung | |----------|--------------| | @contains | Enthält String | | @rx | Regex-Match | | @eq | Gleich (numerisch) | | @gt | Größer als | | @beginsWith | Beginnt mit | | @endsWith | Endet mit | | @detectSQLi | SQL Injection Detection | | @detectXSS | XSS Detection |

Phasen

| Phase | Zeitpunkt | |-------|-----------| | 1 | Request Headers | | 2 | Request Body | | 3 | Response Headers | | 4 | Response Body | | 5 | Logging |

Eigene Regeln

Einfache Regeln

# /etc/modsecurity/rules/custom.conf

# IP blockieren
SecRule REMOTE_ADDR "@ipMatch 192.168.1.100" "id:100001,phase:1,deny,status:403,msg:'Blocked IP'"

# Bestimmten User-Agent blockieren
SecRule REQUEST_HEADERS:User-Agent "@contains BadBot" "id:100002,phase:1,deny,status:403,msg:'Bad Bot blocked'"

# SQL Injection in Parametern
SecRule ARGS "@detectSQLi" "id:100003,phase:2,deny,status:403,msg:'SQL Injection detected'"

# XSS in Parametern
SecRule ARGS "@detectXSS" "id:100004,phase:2,deny,status:403,msg:'XSS detected'"

Rate Limiting

# IP-basiertes Rate Limiting
SecAction "id:100100,phase:1,nolog,pass,initcol:ip=%{REMOTE_ADDR}"
SecAction "id:100101,phase:1,nolog,pass,setvar:ip.counter=+1,deprecatevar:ip.counter=1/60"
SecRule IP:COUNTER "@gt 100" "id:100102,phase:1,deny,status:429,msg:'Rate limit exceeded'"

Geoblocking

# GeoIP-basiertes Blocking (benötigt libmaxminddb)
SecGeoLookupDB /usr/share/GeoIP/GeoLite2-Country.mmdb
SecRule REMOTE_ADDR "@geoLookup" "id:100200,phase:1,nolog,pass"
SecRule GEO:COUNTRY_CODE "@streq RU" "id:100201,phase:1,deny,status:403,msg:'Country blocked'"

Ausnahmen (Whitelisting)

Regel deaktivieren

# Global
SecRuleRemoveById 941100

# Für bestimmten Pfad
<Location /admin/upload>
    SecRuleRemoveById 200002
    SecRuleRemoveById 200003
</Location>

IP Whitelisting

SecRule REMOTE_ADDR "@ipMatch 10.0.0.0/8,192.168.1.0/24" "id:100300,phase:1,nolog,allow,ctl:ruleEngine=Off"

Pfad-Ausnahmen

<Location /api/webhook>
    SecRuleEngine Off
</Location>

# Oder bestimmte Regeln deaktivieren
<Location /api/upload>
    SecRuleRemoveById 200002
    SecRuleRemoveByTag "OWASP_CRS/WEB_ATTACK/SQL_INJECTION"
</Location>

Parameter-Ausnahmen

# Bestimmten Parameter ausschließen
SecRuleUpdateTargetById 942100 "!ARGS:content"
SecRuleUpdateTargetById 941100 "!ARGS:html_content"

Logging und Monitoring

Audit Log analysieren

# Audit Log lesen
tail -f /var/log/apache2/modsec_audit.log

# Nach Regel-ID suchen
grep "id:941100" /var/log/apache2/modsec_audit.log

# Blocked Requests
grep "403" /var/log/apache2/modsec_audit.log

Log-Format

--a]--[timestamp]
--H--
Request-Header

--I--
Request-Body

--A--
Audit-Info (Rule-Matches)

--Z--
End

ModSecurity Console

# Mit jq parsen
cat /var/log/apache2/modsec_audit.log | grep -A20 "\-\-A\-\-"

Virtual Host Konfiguration

Pro Virtual Host

<VirtualHost *:443>
    ServerName secure.example.com

    # ModSecurity aktivieren
    SecRuleEngine On

    # Eigene Regeln für diesen VHost
    Include /etc/modsecurity/vhosts/secure.conf

    # Strikte Konfiguration
    SecAction "id:900000,phase:1,nolog,pass,setvar:tx.paranoia_level=2"
</VirtualHost>

<VirtualHost *:443>
    ServerName legacy.example.com

    # ModSecurity nur im Detection-Modus
    SecRuleEngine DetectionOnly
</VirtualHost>

Anwendungsspezifisch

# Für WordPress
<Location /wp-admin>
    SecRuleRemoveById 920350
    SecRuleRemoveById 942100
</Location>

# Für Drupal
<Location /admin>
    SecRuleRemoveByTag "OWASP_CRS"
    SecRuleEngine DetectionOnly
</Location>

Performance

Optimierung

# Request Body Limit reduzieren
SecRequestBodyLimit 10485760
SecRequestBodyNoFilesLimit 65536

# Response Body nur für bestimmte Content-Types
SecResponseBodyMimeType text/html text/plain application/json

# Regeln reduzieren
SecRuleRemoveByTag "OWASP_CRS/LEAKAGE"

Caching

# GeoIP Caching
SecGeoLookupDB /usr/share/GeoIP/GeoLite2-Country.mmdb cache

Best Practices

Schrittweise Einführung

# Phase 1: Detection Only
SecRuleEngine DetectionOnly

# Phase 2: Low Paranoia, Detection
SecAction "id:900000,phase:1,nolog,pass,setvar:tx.paranoia_level=1"
SecRuleEngine DetectionOnly

# Phase 3: Low Paranoia, Blocking
SecRuleEngine On

# Phase 4: Higher Paranoia mit Ausnahmen
SecAction "id:900000,phase:1,nolog,pass,setvar:tx.paranoia_level=2"

Monitoring

# Blocked Requests zählen
grep -c "403" /var/log/apache2/modsec_audit.log

# Top blockierte Regeln
grep "id:" /var/log/apache2/modsec_audit.log | sort | uniq -c | sort -rn | head

Troubleshooting

Debug-Modus

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

False Positives finden

# Audit Log analysieren
grep "phase:2" /var/log/apache2/modsec_audit.log

# Regel identifizieren
grep "id:941100" /var/log/apache2/modsec_audit.log

Test-Request

# SQL Injection Test
curl "http://example.com/?id=1' OR '1'='1"

# XSS Test
curl "http://example.com/?q=<script>alert(1)</script>"

Zusammenfassung

| Direktive | Funktion | |-----------|----------| | SecRuleEngine | On/Off/DetectionOnly | | SecRule | Regel definieren | | SecAction | Aktion definieren | | SecRuleRemoveById | Regel deaktivieren |

| Phase | Beschreibung | |-------|--------------| | 1 | Request Headers | | 2 | Request Body | | 3 | Response Headers | | 4 | Response Body | | 5 | Logging |

| Log | Pfad | |----|------| | Audit | /var/log/apache2/modsec_audit.log | | Debug | /var/log/apache2/modsec_debug.log |

Fazit

ModSecurity mit dem OWASP Core Rule Set bietet umfassenden Schutz vor Web-Angriffen. Die schrittweise Einführung im Detection-Modus minimiert Störungen. False Positives erfordern Anpassungen, aber der Aufwand lohnt sich. Regelmäßige Log-Analyse hilft bei der Optimierung. Für kritische Anwendungen ist eine WAF heute unverzichtbar.