Nginx mit Modsecurity Whitelists: Unterschied zwischen den Versionen

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen
Die Seite wurde neu angelegt: „ == Voraussetzungen == * Webserver mit ModSecurity (z. B. NGINX + ModSecurity v3) * OWASP CRS kann verwendet werden, aber nicht erforderlich * Pfad zur Haupt…“
 
Keine Bearbeitungszusammenfassung
 
Zeile 1: Zeile 1:
= ModSecurity Default-Deny-Policy =


== Voraussetzungen ==
== Voraussetzungen ==
* Webserver mit ModSecurity (z. B. NGINX + ModSecurity v3)
* NGINX mit ModSecurity v3
* OWASP CRS kann verwendet werden, aber nicht erforderlich
* Hauptkonfigurationsdatei: /etc/nginx/modsec/modsecurity.conf
* Pfad zur Hauptregeldatei z. B.: /etc/modsecurity/main.conf
* Eigene Regeln liegen in: /etc/nginx/modsec/custom-rules/


== Ziel ==
== Ziel ==
* Nur definierte Methoden und Pfade zulassen
* Default-Deny: Alles ist verboten
* Alles andere standardmäßig ablehnen
* Nur explizit definierte URIs für bestimmte Methoden sind erlaubt
* Pfad-Whitelist aus externer Datei laden
* Whitelist aus externen Dateien geladen


== Datei mit erlaubten URIs ==
== Allowlist-Dateien ==
Pfad: /etc/modsecurity/allowed_post_uris.txt


Inhalt:
/etc/nginx/modsec/allowed_post_uris.txt
/safe/upload
---------------------------------------
/safe/form
/safe/upload
/safe/login
/safe/form
/safe/login


== Regelwerk (Whitelist-Ansatz) ==
/etc/nginx/modsec/allowed_get_prefixes.txt
Datei: /etc/modsecurity/custom-rules/default-deny.conf
------------------------------------------
/safe/
/assets/
/static/
 
== Eigene Regeln ==
Datei: /etc/nginx/modsec/custom-rules/default-deny.conf


<pre>
<pre>
# Erlaube POST nur für explizit freigegebene URIs
# POST nur auf URIs aus Datei erlauben
SecRule REQUEST_METHOD "@streq POST" "chain,id:2000,phase:1,deny,status:403,msg:'POST not allowed on this URI'"
SecRule REQUEST_METHOD "@streq POST" \
     SecRule REQUEST_URI "!@pmFromFile /etc/modsecurity/allowed_post_uris.txt"
    "id:2000,phase:1,allow,log,skipAfter:ALLOWLIST_DONE,chain"
     SecRule REQUEST_URI "@pmFromFile /etc/nginx/modsec/allowed_post_uris.txt"


# Erlaube GET auf bestimmte Pfade
# GET nur auf Präfixe aus Datei erlauben
SecRule REQUEST_METHOD "@streq GET" "chain,id:2001,phase:1,pass,nolog,ctl:ruleEngine=Off"
SecRule REQUEST_METHOD "@streq GET" \
     SecRule REQUEST_URI "@beginsWith /safe/"
    "id:2001,phase:1,allow,log,skipAfter:ALLOWLIST_DONE,chain"
     SecRule REQUEST_URI "@pmFromFile /etc/nginx/modsec/allowed_get_prefixes.txt" "chain,capture"
    SecRule REQUEST_URI "@beginsWith %{MATCHED_VAR}"


# Optional: weitere erlaubte Methoden einfügen
# Alles andere blockieren (Default-Deny)
# z. B. HEAD, OPTIONS, PUT usw. je nach Bedarf
SecRule REQUEST_URI ".*" \
    "id:2999,phase:1,deny,status:403,log,msg:'Default deny policy'"


# Marker zur Trennung von Erlaubnis und Default-Ablehnung
# Marker für SkipAfter
SecMarker ALLOWLIST_DONE
SecMarker ALLOWLIST_DONE
# Alles andere wird abgelehnt
SecRule REQUEST_URI ".*" "id:2999,phase:1,deny,status:403,msg:'Blocked by default policy',skipAfter:ALLOWLIST_DONE"
</pre>
</pre>


== Einbindung in Hauptregeldatei ==
== Hauptkonfiguration ==
Pfad: /etc/modsecurity/main.conf
Datei: /etc/nginx/modsec/modsecurity.conf


<pre>
<pre>
# Optional: OWASP CRS laden
SecRuleEngine On
Include /usr/share/modsecurity-crs/crs-setup.conf
SecRequestBodyAccess On
Include /usr/share/modsecurity-crs/rules/*.conf
SecResponseBodyAccess Off
 
# Optionale CRS-Regeln (nur wenn gewünscht)
#Include /usr/share/modsecurity-crs/crs-setup.conf
#Include /usr/share/modsecurity-crs/rules/*.conf


# Eigene Regeln einbinden
# Eigene Default-Deny-Policy laden
Include /etc/modsecurity/custom-rules/default-deny.conf
Include /etc/nginx/modsec/custom-rules/default-deny.conf
</pre>
</pre>


== NGINX-Integration ==
== NGINX-Einbindung ==
In der vHost-Konfiguration oder nginx.conf:
In der vHost- oder http/server/location-Konfiguration:


<pre>
<pre>
modsecurity on;
modsecurity on;
modsecurity_rules_file /etc/modsecurity/main.conf;
modsecurity_rules_file /etc/nginx/modsec/modsecurity.conf;
</pre>
</pre>


== Neustart / Reload ==
== Neustart / Reload ==
* systemctl reload nginx
* Syntaxprüfung: nginx -t
* Fehlerprüfung mit: nginx -t
* Reload: systemctl reload nginx


== Testbeispiele ==
== Testfälle ==
{| class="wikitable"
{| class="wikitable"
! Methode !! URI !! Erwartung
! Methode !! URI !! Erwartung
Zeile 72: Zeile 84:
| POST || /badpath || 403 Forbidden
| POST || /badpath || 403 Forbidden
|-
|-
| GET || /safe/form || 200 OK
| GET || /safe/test || 200 OK
|-
|-
| GET || /admin || 403 Forbidden
| GET || /admin || 403 Forbidden
|}
|}
== Hinweise ==
* @pmFromFile lädt zeilenweise rohe Pfadstrings ohne Regex.
* Jede Methode (POST, GET, PUT, ...) benötigt eigene Allow-Regel.
* Die Catch-All-Regel am Ende macht daraus eine echte Default-Deny-Policy.
* Die Regel-ID 2999 muss höher sein als alle anderen.
== Erweiterung ==
* Cookie-Integritätsschutz: REQUEST_COOKIES validieren
* CSRF-Token-Validierung über eigene Variablen
* Separate Whitelist-Dateien für verschiedene Methoden
== Fazit ==
Diese Konfiguration erreicht eine vergleichbare Zugriffskontrolle wie die Sophos XG Webserver Protection – vollständig transparent, erweiterbar und ohne GUI-Zwang.

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

ModSecurity Default-Deny-Policy

Voraussetzungen

  • NGINX mit ModSecurity v3
  • Hauptkonfigurationsdatei: /etc/nginx/modsec/modsecurity.conf
  • Eigene Regeln liegen in: /etc/nginx/modsec/custom-rules/

Ziel

  • Default-Deny: Alles ist verboten
  • Nur explizit definierte URIs für bestimmte Methoden sind erlaubt
  • Whitelist aus externen Dateien geladen

Allowlist-Dateien

/etc/nginx/modsec/allowed_post_uris.txt


/safe/upload /safe/form /safe/login

/etc/nginx/modsec/allowed_get_prefixes.txt


/safe/ /assets/ /static/

Eigene Regeln

Datei: /etc/nginx/modsec/custom-rules/default-deny.conf

# POST nur auf URIs aus Datei erlauben
SecRule REQUEST_METHOD "@streq POST" \
    "id:2000,phase:1,allow,log,skipAfter:ALLOWLIST_DONE,chain"
    SecRule REQUEST_URI "@pmFromFile /etc/nginx/modsec/allowed_post_uris.txt"

# GET nur auf Präfixe aus Datei erlauben
SecRule REQUEST_METHOD "@streq GET" \
    "id:2001,phase:1,allow,log,skipAfter:ALLOWLIST_DONE,chain"
    SecRule REQUEST_URI "@pmFromFile /etc/nginx/modsec/allowed_get_prefixes.txt" "chain,capture"
    SecRule REQUEST_URI "@beginsWith %{MATCHED_VAR}"

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

# Marker für SkipAfter
SecMarker ALLOWLIST_DONE

Hauptkonfiguration

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

SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess Off

# Optionale CRS-Regeln (nur wenn gewünscht)
#Include /usr/share/modsecurity-crs/crs-setup.conf
#Include /usr/share/modsecurity-crs/rules/*.conf

# Eigene Default-Deny-Policy laden
Include /etc/nginx/modsec/custom-rules/default-deny.conf

NGINX-Einbindung

In der vHost- oder http/server/location-Konfiguration:

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

Neustart / Reload

  • Syntaxprüfung: nginx -t
  • Reload: systemctl reload nginx

Testfälle

Methode URI Erwartung
POST /safe/upload 200 OK
POST /badpath 403 Forbidden
GET /safe/test 200 OK
GET /admin 403 Forbidden