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 apache2CentOS/RHEL
dnf install mod_security mod_security_crs
systemctl restart httpdGrundkonfiguration
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/modsecurityApache-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.logLog-Format
--a]--[timestamp]
--H--
Request-Header
--I--
Request-Body
--A--
Audit-Info (Rule-Matches)
--Z--
EndModSecurity 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 cacheBest 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 | headTroubleshooting
Debug-Modus
SecDebugLog /var/log/apache2/modsec_debug.log
SecDebugLogLevel 9False Positives finden
# Audit Log analysieren
grep "phase:2" /var/log/apache2/modsec_audit.log
# Regel identifizieren
grep "id:941100" /var/log/apache2/modsec_audit.logTest-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.