Nginx mit Modsecurity zusammen Whitelists: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
 
Zeile 1: Zeile 1:
= NGINX mit ModSecurity und Whitelist-Policy =
+
= NGINX mit ModSecurity und Default-Deny-Whitelist =
  
 
Diese Anleitung zeigt den Aufbau einer Web Application Firewall mit NGINX und ModSecurity v3.   
 
Diese Anleitung zeigt den Aufbau einer Web Application Firewall mit NGINX und ModSecurity v3.   
Im ersten Schritt wird ModSecurity mit OWASP Core Rule Set (CRS) als Reverse Proxy aktiviert. 
+
ModSecurity wird als Reverse Proxy aktiviert, das OWASP Core Rule Set (CRS) eingebunden und zusätzlich eine Whitelist-Policy eingerichtet.   
Im zweiten Schritt folgt die Whitelist-Policy, bei der nur definierte Methoden und Pfade erlaubt sind.   
+
Dadurch gilt: **Alles ist standardmäßig verboten, nur definierte URIs (Whitelist) sind erlaubt.**
Alles andere wird standardmäßig blockiert.
 
  
 
== Voraussetzungen ==
 
== Voraussetzungen ==
Bevor es losgeht, muss das System vorbereitet sein. Wir arbeiten hier mit Ubuntu 22.04 oder Debian 12, einem funktionierenden Backend (z. B. Web-App auf Port 8080) und internen TLS-Zertifikaten.
 
 
* Ubuntu 22.04 oder Debian 12
 
* Ubuntu 22.04 oder Debian 12
* Backend-Dienst z. B. unter http://127.0.0.1:8080 erreichbar
+
* Funktionierendes Backend (z. B. http://127.0.0.1:8080)
 
* TLS-Zertifikate (crt.pem, privkey.pem, ca.crt) aus interner CA
 
* TLS-Zertifikate (crt.pem, privkey.pem, ca.crt) aus interner CA
  
 
== Installation ==
 
== Installation ==
Zunächst werden die benötigten Pakete installiert und ein Konfigurationsverzeichnis angelegt.
 
 
* Pakete installieren
 
* Pakete installieren
 
  sudo apt update
 
  sudo apt update
 
  sudo apt install nginx libmodsecurity3 libnginx-mod-http-modsecurity git apache2-utils -y
 
  sudo apt install nginx libmodsecurity3 libnginx-mod-http-modsecurity git apache2-utils -y
  
* Verzeichnis für Konfiguration anlegen
+
* Verzeichnisstruktur anlegen
  sudo mkdir -p /etc/nginx/modsecurity
+
  sudo mkdir -p /etc/nginx/modsec/custom-rules
  
 
== OWASP Core Rule Set installieren ==
 
== OWASP Core Rule Set installieren ==
Das OWASP CRS (Core Rule Set) enthält die eigentlichen Standard-Regeln gegen typische Webangriffe. Es wird von GitHub geholt und aktiviert.
 
 
* In das ModSecurity-Verzeichnis wechseln
 
* In das ModSecurity-Verzeichnis wechseln
  cd /etc/nginx/modsecurity
+
  cd /etc/nginx/modsec
  
 
* CRS klonen
 
* CRS klonen
Zeile 33: Zeile 29:
  
 
== ModSecurity konfigurieren ==
 
== ModSecurity konfigurieren ==
Die Hauptkonfiguration legt fest, dass ModSecurity Anfragen inspiziert und Logs schreibt. Außerdem wird das CRS eingebunden.
+
Datei: /etc/nginx/modsec/modsecurity.conf
* Basis-Konfiguration /etc/nginx/modsecurity/modsecurity.conf
 
 
<pre>
 
<pre>
 
SecRuleEngine On
 
SecRuleEngine On
Zeile 43: Zeile 38:
 
SecAuditLog /var/log/nginx/modsec_audit.log
 
SecAuditLog /var/log/nginx/modsec_audit.log
 
SecAuditLogParts ABIJDEFHZ
 
SecAuditLogParts ABIJDEFHZ
 
SecDebugLog /var/log/nginx/modsec_debug.log
 
SecDebugLogLevel 3
 
  
 
SecTmpDir /tmp/
 
SecTmpDir /tmp/
 
SecDataDir /tmp/
 
SecDataDir /tmp/
  
# Beispiel-Testregel (optional)
+
# Erst unsere Whitelist/Default-Deny laden
SecRule ARGS "@contains script" \
+
Include /etc/nginx/modsec/custom-rules/default-deny.conf
     "id:9999,phase:1,deny,log,status:403,msg:'Test rule triggered'"
+
 
 +
# Danach CRS – wirkt nur auf NICHT-Whitelist-URIs
 +
Include /etc/nginx/modsec/coreruleset/crs-setup.conf
 +
Include /etc/nginx/modsec/coreruleset/rules/*.conf
 +
</pre>
 +
 
 +
== Whitelist-Policy ==
 +
* Datei mit erlaubten URIs /etc/nginx/modsec/allowed_uris.txt
 +
<pre>
 +
/upload
 +
</pre>
 +
 
 +
* Regelwerk /etc/nginx/modsec/custom-rules/default-deny.conf
 +
<pre>
 +
# Whitelist: URIs aus Datei von Inspektion ausnehmen (inkl. CRS)
 +
SecRule REQUEST_URI "@pmFromFile /etc/nginx/modsec/allowed_uris.txt" \
 +
     "id:2000,phase:1,pass,log,ctl:ruleEngine=Off"
  
# OWASP CRS laden
+
# Default-Deny: alles andere blockieren
Include /etc/nginx/modsecurity/coreruleset/crs-setup.conf
+
SecRule REQUEST_URI ".*" \
Include /etc/nginx/modsecurity/coreruleset/rules/*.conf
+
    "id:2999,phase:1,deny,status:403,log,msg:'Default deny policy'"
 
</pre>
 
</pre>
  
 
== NGINX-Snippet ==
 
== NGINX-Snippet ==
Damit ModSecurity aktiviert wird, bindet NGINX ein Snippet ein. Das erleichtert die Konfiguration in den VHosts.
+
Datei: /etc/nginx/modsec/main.conf
Datei: /etc/nginx/modsecurity/main.conf
 
 
<pre>
 
<pre>
 
modsecurity on;
 
modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;
+
modsecurity_rules_file /etc/nginx/modsec/modsecurity.conf;
 
</pre>
 
</pre>
  
 
== NGINX-Site konfigurieren ==
 
== NGINX-Site konfigurieren ==
Die Site-Definition sorgt dafür, dass HTTP auf HTTPS umgeleitet wird und alle Anfragen durch ModSecurity laufen. Zusätzlich wird ein Zugriff auf das Auditlog im Browser angeboten.
+
Datei: /etc/nginx/sites-available/default
* Standard-VHost anpassen /etc/nginx/sites-available/default
 
 
<pre>
 
<pre>
# HTTP → HTTPS Redirect
 
 
server {
 
server {
 
     listen 80;
 
     listen 80;
Zeile 78: Zeile 83:
 
}
 
}
  
# HTTPS-Server mit TLS und ModSecurity
 
 
server {
 
server {
 
     listen 443 ssl;
 
     listen 443 ssl;
Zeile 89: Zeile 93:
 
     error_log  /var/log/nginx/error.log warn;
 
     error_log  /var/log/nginx/error.log warn;
  
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+
     include /etc/nginx/modsec/main.conf;
    add_header Cache-Control "no-store, no-cache, must-revalidate";
 
 
 
    error_page 403 /403.html;
 
    location = /403.html {
 
        root /var/www/html;
 
        internal;
 
    }
 
 
 
     include /etc/nginx/modsecurity/main.conf;
 
  
 
     location / {
 
     location / {
Zeile 120: Zeile 115:
  
 
== Logging ==
 
== Logging ==
Logs sind wichtig, um Angriffe und Blockierungen nachzuvollziehen. Dazu werden Logformate und Rechte angepasst.
 
 
* Log-Format ergänzen (/etc/nginx/nginx.conf im http{}-Block)
 
* Log-Format ergänzen (/etc/nginx/nginx.conf im http{}-Block)
 
<pre>
 
<pre>
Zeile 131: Zeile 125:
 
* Log-Dateien anlegen
 
* Log-Dateien anlegen
 
<pre>
 
<pre>
sudo touch /var/log/nginx/modsec_audit.log /var/log/nginx/modsec_debug.log
+
sudo touch /var/log/nginx/modsec_audit.log
sudo chown www-data:adm /var/log/nginx/modsec_*.log
+
sudo chown www-data:adm /var/log/nginx/modsec_audit.log
sudo chmod 640 /var/log/nginx/modsec_*.log
+
sudo chmod 640 /var/log/nginx/modsec_audit.log
 
</pre>
 
</pre>
  
* Fehlerseite anlegen /var/www/html/403.html
+
== Fehlerseite ==
 +
/var/www/html/403.html
 
<pre>
 
<pre>
 
<html>
 
<html>
 
  <head><title>403 Forbidden</title></head>
 
  <head><title>403 Forbidden</title></head>
 
  <body>
 
  <body>
  <h1>Oops! Zugriff verweigert</h1>
+
  <h1>Zugriff verweigert</h1>
 
  <p>Deine Anfrage wurde von der Web Application Firewall blockiert.</p>
 
  <p>Deine Anfrage wurde von der Web Application Firewall blockiert.</p>
 
  </body>
 
  </body>
Zeile 147: Zeile 142:
 
</pre>
 
</pre>
  
== Zugriff auf Audit-Log per Browser ==
+
== Audit-Log im Browser ==
Damit Teilnehmer ohne Shell-Zugriff das Log sehen können, wird es über eine URL abrufbar gemacht – geschützt durch Passwort.
 
 
* Benutzerdatei anlegen
 
* Benutzerdatei anlegen
<pre>
+
sudo htpasswd -c /etc/nginx/.htpasswd admin
sudo htpasswd -c /etc/nginx/.htpasswd admin
 
</pre>
 
  
* Aufruf im Browser
+
* Aufruf
  https://<server>/_waflog
+
  https://<server>/_waflog
Benutzer: admin, Passwort wie vergeben
 
 
 
* Nutzen
 
* Anzeige, welche Requests geblockt wurden (Regel-ID, URI, Methode)
 
* Für Schulungen sofort sichtbar, warum eine Anfrage blockiert wurde
 
* Auch ohne SSH-Zugang direkt im Browser nutzbar
 
 
 
== Whitelist-Policy ==
 
Standardmäßig prüfen die CRS-Regeln sehr viele Muster. Mit einer Whitelist-Policy wird das Verhalten verschärft: nur definierte Methoden und Pfade dürfen durch, alles andere wird geblockt.
 
* Datei mit erlaubten POST-URIs /etc/nginx/modsecurity/allowed_post_uris.txt
 
<pre>
 
/safe/upload
 
/safe/form
 
/safe/login
 
</pre>
 
 
 
* Regelwerk /etc/nginx/modsecurity/custom-rules/default-deny.conf
 
<pre>
 
# Erlaube POST nur für explizit freigegebene URIs
 
SecRule REQUEST_METHOD "@streq POST" "chain,id:2000,phase:1,deny,status:403,msg:'POST not allowed on this URI'"
 
    SecRule REQUEST_URI "!@pmFromFile /etc/nginx/modsecurity/allowed_post_uris.txt"
 
 
 
# Erlaube GET nur unterhalb von /safe/
 
SecRule REQUEST_METHOD "@streq GET" "chain,id:2001,phase:1,allow,log,skipAfter:ALLOWLIST_DONE"
 
    SecRule REQUEST_URI "@beginsWith /safe/"
 
 
 
# Marker
 
SecMarker ALLOWLIST_DONE
 
 
 
# Catch-All: alles andere blockieren
 
SecRule REQUEST_URI ".*" "id:2999,phase:1,deny,status:403,msg:'Blocked by default policy',skipAfter:ALLOWLIST_DONE"
 
</pre>
 
 
 
* Einbindung in /etc/nginx/modsecurity/modsecurity.conf
 
<pre>
 
Include /etc/nginx/modsecurity/custom-rules/default-deny.conf
 
</pre>
 
  
 
== Aktivierung ==
 
== Aktivierung ==
Zum Schluss Konfiguration testen und NGINX neu laden.
+
* Syntax prüfen
<pre>
+
sudo nginx -t
sudo nginx -t
+
* Reload
sudo systemctl reload nginx
+
sudo systemctl reload nginx
</pre>
 
  
 
== Testbeispiele ==
 
== Testbeispiele ==
Mit diesen Beispielen lässt sich prüfen, ob die Whitelist-Policy greift.
 
 
{| class="wikitable"
 
{| class="wikitable"
 
! Methode !! URI !! Erwartung
 
! Methode !! URI !! Erwartung
 
|-
 
|-
| POST || /safe/upload || 200 OK
+
| POST || /upload || 200 OK
 
|-
 
|-
| POST || /badpath || 403 Forbidden
+
| GET  || /upload || 200 OK
 
|-
 
|-
| GET || /safe/form || 200 OK
+
| GET || /admin  || 403 Forbidden
 
|-
 
|-
| GET || /admin || 403 Forbidden
+
| POST || /bad    || 403 Forbidden
 
|}
 
|}
  
== curl-Tests ==
+
== Audit-Log verfolgen ==
Die folgenden Befehle simulieren die Requests aus der Tabelle. <server> muss durch die IP oder den Hostnamen des Systems ersetzt werden.
 
<pre>
 
# Erwartet 200 (erlaubter POST)
 
curl -k -i -X POST https://<server>/safe/upload
 
 
 
# Erwartet 403 (POST nicht erlaubt)
 
curl -k -i -X POST https://<server>/badpath
 
 
 
# Erwartet 200 (erlaubtes GET)
 
curl -k -i https://<server>/safe/form
 
 
 
# Erwartet 403 (GET nicht erlaubt)
 
curl -k -i https://<server>/admin
 
</pre>
 
 
 
== Audit-Log überwachen ==
 
Um live zu sehen, welche Requests geblockt werden, kann das Audit-Log verfolgt werden.
 
 
<pre>
 
<pre>
 
sudo tail -f /var/log/nginx/modsec_audit.log
 
sudo tail -f /var/log/nginx/modsec_audit.log
Zeile 238: Zeile 174:
  
 
== Ergebnis ==
 
== Ergebnis ==
* ModSecurity + CRS schützt vor typischen Angriffen.
+
* CRS schützt vor typischen Angriffen auf nicht-Whitelist-URIs
* Die Whitelist-Policy setzt zusätzlich eine Default-Deny-Strategie um.
+
* Default-Deny blockt alles, was nicht explizit erlaubt ist
* Nur definierte Methoden und Pfade sind erlaubt, alle anderen Anfragen werden blockiert.
+
* Whitelist erlaubt gezielt z. B. `/upload`
* Das Audit-Log unter /var/log/nginx/modsec_audit.log dokumentiert alle geblockten Requests.
+
* Audit-Log zeigt geblockte Requests
* Zugriff auf Audit-Log über Browser möglich: https://<server>/_waflog (mit Basic-Auth).
 
* Optional Debug-Log: /var/log/nginx/modsec_debug.log.
 
 
 
[[KATEGORIE:WAF]]
 

Aktuelle Version vom 5. September 2025, 07:31 Uhr

NGINX mit ModSecurity und Default-Deny-Whitelist

Diese Anleitung zeigt den Aufbau einer Web Application Firewall mit NGINX und ModSecurity v3. ModSecurity wird als Reverse Proxy aktiviert, das OWASP Core Rule Set (CRS) eingebunden und zusätzlich eine Whitelist-Policy eingerichtet. Dadurch gilt: **Alles ist standardmäßig verboten, nur definierte URIs (Whitelist) sind erlaubt.**

Voraussetzungen

  • Ubuntu 22.04 oder Debian 12
  • Funktionierendes Backend (z. B. http://127.0.0.1:8080)
  • TLS-Zertifikate (crt.pem, privkey.pem, ca.crt) aus interner CA

Installation

  • Pakete installieren
sudo apt update
sudo apt install nginx libmodsecurity3 libnginx-mod-http-modsecurity git apache2-utils -y
  • Verzeichnisstruktur anlegen
sudo mkdir -p /etc/nginx/modsec/custom-rules

OWASP Core Rule Set installieren

  • In das ModSecurity-Verzeichnis wechseln
cd /etc/nginx/modsec
  • CRS klonen
sudo git clone https://github.com/coreruleset/coreruleset.git
  • Setup-Datei aktivieren
sudo cp coreruleset/crs-setup.conf.example coreruleset/crs-setup.conf

ModSecurity konfigurieren

Datei: /etc/nginx/modsec/modsecurity.conf

SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off

SecAuditEngine RelevantOnly
SecAuditLog /var/log/nginx/modsec_audit.log
SecAuditLogParts ABIJDEFHZ

SecTmpDir /tmp/
SecDataDir /tmp/

# Erst unsere Whitelist/Default-Deny laden
Include /etc/nginx/modsec/custom-rules/default-deny.conf

# Danach CRS – wirkt nur auf NICHT-Whitelist-URIs
Include /etc/nginx/modsec/coreruleset/crs-setup.conf
Include /etc/nginx/modsec/coreruleset/rules/*.conf

Whitelist-Policy

  • Datei mit erlaubten URIs /etc/nginx/modsec/allowed_uris.txt
/upload
  • Regelwerk /etc/nginx/modsec/custom-rules/default-deny.conf
# Whitelist: URIs aus Datei von Inspektion ausnehmen (inkl. CRS)
SecRule REQUEST_URI "@pmFromFile /etc/nginx/modsec/allowed_uris.txt" \
    "id:2000,phase:1,pass,log,ctl:ruleEngine=Off"

# Default-Deny: alles andere blockieren
SecRule REQUEST_URI ".*" \
    "id:2999,phase:1,deny,status:403,log,msg:'Default deny policy'"

NGINX-Snippet

Datei: /etc/nginx/modsec/main.conf

modsecurity on;
modsecurity_rules_file /etc/nginx/modsec/modsecurity.conf;

NGINX-Site konfigurieren

Datei: /etc/nginx/sites-available/default

server {
    listen 80;
    server_name <server>;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name <server>;

    ssl_certificate     /etc/nginx/fullchain.pem;
    ssl_certificate_key /etc/nginx/privkey.pem;

    access_log /var/log/nginx/access.log waf_combined;
    error_log  /var/log/nginx/error.log warn;

    include /etc/nginx/modsec/main.conf;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    # Audit-Log im Browser abrufbar (Basic-Auth)
    location /_waflog {
        alias /var/log/nginx/modsec_audit.log;
        types { }
        default_type text/plain;

        auth_basic "ModSecurity Auditlog";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}

Logging

  • Log-Format ergänzen (/etc/nginx/nginx.conf im http{}-Block)
log_format waf_combined '$remote_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent" '
                        'ModSecID=$request_id Host="$host" URI="$request_uri"';
  • Log-Dateien anlegen
sudo touch /var/log/nginx/modsec_audit.log
sudo chown www-data:adm /var/log/nginx/modsec_audit.log
sudo chmod 640 /var/log/nginx/modsec_audit.log

Fehlerseite

/var/www/html/403.html

<html>
 <head><title>403 Forbidden</title></head>
 <body>
 <h1>Zugriff verweigert</h1>
 <p>Deine Anfrage wurde von der Web Application Firewall blockiert.</p>
 </body>
</html>

Audit-Log im Browser

  • Benutzerdatei anlegen
sudo htpasswd -c /etc/nginx/.htpasswd admin
  • Aufruf
https://<server>/_waflog

Aktivierung

  • Syntax prüfen
sudo nginx -t
  • Reload
sudo systemctl reload nginx

Testbeispiele

Methode URI Erwartung
POST /upload 200 OK
GET /upload 200 OK
GET /admin 403 Forbidden
POST /bad 403 Forbidden

Audit-Log verfolgen

sudo tail -f /var/log/nginx/modsec_audit.log

Ergebnis

  • CRS schützt vor typischen Angriffen auf nicht-Whitelist-URIs
  • Default-Deny blockt alles, was nicht explizit erlaubt ist
  • Whitelist erlaubt gezielt z. B. `/upload`
  • Audit-Log zeigt geblockte Requests