Nginx

Tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

Fehlende root-Direktive

Bei der Konfiguration des Nginx-Servers spielt die root-Direktive eine wichtige Rolle, da sie das Basisverzeichnis definiert, aus dem Dateien ausgeliefert werden. Betrachten Sie das folgende Beispiel:

server {
root /etc/nginx;

location /hello.txt {
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8080/;
}
}

In dieser Konfiguration ist /etc/nginx als root-Verzeichnis festgelegt. Diese Einrichtung erlaubt den Zugriff auf Dateien innerhalb des angegebenen root-Verzeichnisses, wie z. B. /hello.txt. Es ist jedoch wichtig zu beachten, dass nur ein spezifischer location (/hello.txt) definiert ist. Es gibt keine Konfiguration für den root-Standort (location / {...}). Dieses Fehlen bedeutet, dass die root-Direktive global gilt und Anfragen an den Root-Pfad / Zugriff auf Dateien unter /etc/nginx ermöglichen.

Eine kritische Sicherheitsüberlegung ergibt sich aus dieser Konfiguration. Eine einfache GET-Anfrage, wie GET /nginx.conf, könnte sensible Informationen offenlegen, indem die Nginx-Konfigurationsdatei unter /etc/nginx/nginx.conf ausgeliefert wird. Das Setzen des root auf ein weniger sensibles Verzeichnis, wie /etc, könnte dieses Risiko mindern, erlaubt aber möglicherweise weiterhin unbeabsichtigten Zugriff auf andere kritische Dateien, einschließlich anderer Konfigurationsdateien, access logs und sogar verschlüsselter Anmeldeinformationen, die für HTTP basic authentication verwendet werden.

Alias LFI-Fehlkonfiguration

In den Konfigurationsdateien von Nginx ist eine genaue Prüfung der “location”-Direktiven geboten. Eine Schwachstelle, bekannt als Local File Inclusion (LFI), kann unbeabsichtigt durch eine Konfiguration eingeführt werden, die der folgenden ähnelt:

location /imgs {
alias /path/images/;
}

Diese Konfiguration ist anfällig für LFI attacks, da der Server Anfragen wie /imgs../flag.txt so interpretiert, als versuche man, auf Dateien außerhalb des vorgesehenen Verzeichnisses zuzugreifen, und sie effektiv zu /path/images/../flag.txt auflöst. Dieser Fehler erlaubt es Angreifern, Dateien vom Dateisystem des Servers abzurufen, die über das Web nicht zugänglich sein sollten.

Um diese Schwachstelle zu mindern, sollte die Konfiguration wie folgt angepasst werden:

location /imgs/ {
alias /path/images/;
}

Weitere Informationen: https://www.acunetix.com/vulnerabilities/web/path-traversal-via-misconfigured-nginx-alias/

Accunetix-Tests:

alias../ => HTTP status code 403
alias.../ => HTTP status code 404
alias../../ => HTTP status code 403
alias../../../../../../../../../../../ => HTTP status code 400
alias../ => HTTP status code 403

Unsichere Pfadbeschränkung

Sieh dir die folgende Seite an, um zu lernen, wie man Direktiven wie diese umgeht:

location = /admin {
deny all;
}

location = /admin/ {
deny all;
}

Proxy / WAF Protections Bypass

Unsichere Variablenverwendung / HTTP Request Splitting

Caution

Anfällige Variablen $uri und $document_uri — das lässt sich beheben, indem man sie durch $request_uri ersetzt.

Auch ein Regex kann anfällig sein, z.B.:

location ~ /docs/([^/])? { … $1 … } - Anfällig

location ~ /docs/([^/\s])? { … $1 … } - Nicht anfällig (prüft Leerzeichen)

location ~ /docs/(.*)? { … $1 … } - Nicht anfällig

Eine Schwachstelle in der Nginx-Konfiguration wird im folgenden Beispiel gezeigt:

location / {
return 302 https://example.com$uri;
}

Die Zeichen \r (Carriage Return) und \n (Line Feed) kennzeichnen Zeilenumbrüche in HTTP-Anfragen, und ihre URL-kodierten Formen werden als %0d%0a dargestellt. Wenn diese Zeichen in einer Anfrage (z. B. http://localhost/%0d%0aDetectify:%20clrf) an einen fehlkonfigurierten Server enthalten sind, führt das dazu, dass der Server einen neuen Header namens Detectify ausgibt. Das geschieht, weil die Variable $uri die URL-kodierten Zeilenumbrüche dekodiert und dadurch ein unerwarteter Header in der Antwort entsteht:

HTTP/1.1 302 Moved Temporarily
Server: nginx/1.19.3
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: https://example.com/
Detectify: clrf

Erfahre mehr über die Risiken von CRLF injection und response splitting unter https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/.

Also this technique is explained in this talk with some vulnerable examples and dectection mechanisms. Zum Beispiel: Um diese Fehlkonfiguration aus Blackbox-Sicht zu erkennen, könntest du folgende Requests senden:

  • https://example.com/%20X - Any HTTP code
  • https://example.com/%20H - 400 Bad Request

Wenn verwundbar, wird die erste Antwort zurückgegeben, da “X” jede HTTP-Methode sein kann, und die zweite wird einen Fehler zurückgeben, da H keine gültige Methode ist. Der Server erhält also etwas wie: GET / H HTTP/1.1 und das löst den Fehler aus.

Weitere Erkennungsbeispiele wären:

  • http://company.tld/%20HTTP/1.1%0D%0AXXXX:%20x - Any HTTP code
  • http://company.tld/%20HTTP/1.1%0D%0AHost:%20x - 400 Bad Request

Einige in diesem Vortrag gezeigte verwundbare Konfigurationen waren:

  • Beachte, wie $uri unverändert in der finalen URL gesetzt wird.
location ^~ /lite/api/ {
proxy_pass http://lite-backend$uri$is_args$args;
}
  • Beachte, dass $uri erneut in der URL vorkommt (diesmal innerhalb eines Parameters)
location ~ ^/dna/payment {
rewrite ^/dna/([^/]+) /registered/main.pl?cmd=unifiedPayment&context=$1&native_uri=$uri break;
proxy_pass http://$back;
  • Jetzt in AWS S3
location /s3/ {
proxy_pass https://company-bucket.s3.amazonaws.com$uri;
}

Beliebige Variable

Es wurde festgestellt, dass vom Benutzer bereitgestellte Daten unter bestimmten Umständen als Nginx-Variable behandelt werden können. Die Ursache dieses Verhaltens bleibt etwas schwer fassbar, ist jedoch weder selten noch einfach zu überprüfen. Diese Anomalie wurde in einem Sicherheitsbericht auf HackerOne hervorgehoben, der here eingesehen werden kann. Weitere Untersuchungen der Fehlermeldung führten zur Identifizierung ihres Auftretens innerhalb des SSI filter module of Nginx’s codebase, wobei Server Side Includes (SSI) als Ursache ausgemacht wurden.

Um diese Fehlkonfiguration zu erkennen, kann der folgende Befehl ausgeführt werden, bei dem ein Referer-Header gesetzt wird, um das Ausgeben von Variablen zu testen:

$ curl -H ‘Referer: bar’ http://localhost/foo$http_referer | grep ‘foobar’

Scans auf Systemen nach dieser Fehlkonfiguration zeigten mehrere Fälle, in denen Nginx-Variablen von einem Benutzer ausgegeben werden konnten. Ein Rückgang der Anzahl verwundbarer Instanzen deutet jedoch darauf hin, dass die Bemühungen, dieses Problem zu patchen, teilweise erfolgreich waren.

Verwendung von try_files mit $URI$ARGS variables

Die folgende Nginx-Fehlkonfiguration kann zu einer LFI-Schwachstelle führen:

location / {
try_files $uri$args $uri$args/ /index.html;
}

In unserer Konfiguration haben wir die Direktive try_files, die verwendet wird, um das Vorhandensein von Dateien in einer festgelegten Reihenfolge zu prüfen. Nginx liefert die erste Datei aus, die es findet. Die Grundsyntax der Direktive try_files ist wie folgt:

try_files file1 file2 ... fileN fallback;

Nginx überprüft das Vorhandensein jeder Datei in der angegebenen Reihenfolge. Wenn eine Datei existiert, wird sie sofort ausgeliefert. Existiert keine der angegebenen Dateien, wird die Anfrage an die Fallback-Option weitergeleitet, die eine andere URI oder eine bestimmte Fehlerseite sein kann.

Wenn jedoch in dieser Direktive die Variablen $uri$args verwendet werden, versucht Nginx, nach einer Datei zu suchen, die mit der Request-URI kombiniert mit beliebigen Query-String-Argumenten übereinstimmt. Daher können wir diese Konfiguration ausnutzen:

http {
server {
root /var/www/html/public;

location / {
try_files $uri$args $uri$args/ /index.html;
}
}
}

Mit folgendem Payload:

GET /?../../../../../../../../etc/passwd HTTP/1.1
Host: example.com

Mit unserem payload entkommen wir dem Root-Verzeichnis (in der Nginx-Konfiguration definiert) und laden die Datei /etc/passwd. In den Debug-Logs können wir beobachten, wie Nginx die Dateien ausprobiert:

...SNIP...

2025/07/11 15:49:16 [debug] 79694#79694: *4 trying to use file: "/../../../../../../../../etc/passwd" "/var/www/html/public/../../../../../../../../etc/passwd"
2025/07/11 15:49:16 [debug] 79694#79694: *4 try file uri: "/../../../../../../../../etc/passwd"

...SNIP...

2025/07/11 15:49:16 [debug] 79694#79694: *4 http filename: "/var/www/html/public/../../../../../../../../etc/passwd"

...SNIP...

2025/07/11 15:49:16 [debug] 79694#79694: *4 HTTP/1.1 200 OK

PoC againts Nginx using the configuration mentioned above: Example burp request

Rohes Auslesen von Backend-Antworten

Nginx bietet über proxy_pass eine Funktion, die das Abfangen von vom Backend erzeugten Fehlern und HTTP-Headern ermöglicht, mit dem Ziel, interne Fehlermeldungen und Header zu verbergen. Dies wird dadurch erreicht, dass Nginx bei Backend-Fehlern eigene Error-Pages ausliefert. Es ergeben sich jedoch Probleme, wenn Nginx auf eine ungültige HTTP-Anfrage trifft. Eine solche Anfrage wird unverändert an das Backend weitergeleitet, und die rohe Antwort des Backends wird anschließend ohne Eingreifen von Nginx direkt an den Client gesendet.

Betrachten wir ein Beispiel mit einer uWSGI-Anwendung:

def application(environ, start_response):
start_response('500 Error', [('Content-Type', 'text/html'), ('Secret-Header', 'secret-info')])
return [b"Secret info, should not be visible!"]

Um dies zu verwalten, werden spezifische Direktiven in der Nginx-Konfiguration verwendet:

http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
  • proxy_intercept_errors: Diese Direktive erlaubt Nginx, eine benutzerdefinierte Antwort für Backend-Antworten mit einem Statuscode größer als 300 zu liefern. Sie stellt sicher, dass für unsere Beispiel-uWSGI-Anwendung eine 500 Error-Antwort abgefangen und von Nginx behandelt wird.
  • proxy_hide_header: Wie der Name schon sagt, blendet diese Direktive bestimmte HTTP-Header vor dem Client aus und erhöht so Privatsphäre und Sicherheit.

Wenn eine gültige GET-Anfrage gestellt wird, verarbeitet Nginx sie normal und gibt eine standardmäßige Fehlerantwort zurück, ohne geheime Header preiszugeben. Eine ungültige HTTP-Anfrage umgeht jedoch diesen Mechanismus, was zur Offenlegung roher Backend-Antworten führt, einschließlich geheimer Header und Fehlermeldungen.

merge_slashes auf off setzen

Standardmäßig ist Nginx’ merge_slashes-Direktive auf on gesetzt, was mehrere Vorwärtsslashes in einer URL zu einem einzigen Slash komprimiert. Diese Funktion kann zwar die URL-Verarbeitung vereinfachen, aber unbeabsichtigt Schwachstellen in Anwendungen hinter Nginx verbergen, insbesondere solche, die anfällig für local file inclusion (LFI)-Angriffe sind. Sicherheitsexperten Danny Robinson and Rotem Bar haben auf die potenziellen Risiken dieses Standardverhaltens hingewiesen, besonders wenn Nginx als reverse-proxy fungiert.

Um diese Risiken zu mindern, wird empfohlen, die merge_slashes-Direktive auszuschalten für Anwendungen, die für diese Schwachstellen anfällig sind. Dadurch leitet Nginx Anfragen an die Anwendung weiter, ohne die URL-Struktur zu verändern, und verschleiert somit keine zugrunde liegenden Sicherheitsprobleme.

For more information check Danny Robinson and Rotem Bar.

Maclicious-Antwort-Header

Wie in this writeup gezeigt, gibt es bestimmte Header, die, wenn sie in der Antwort des Webservers vorhanden sind, das Verhalten des Nginx-Proxys ändern. Sie können sie in the docs nachprüfen:

  • X-Accel-Redirect: Veranlasst Nginx, eine Anfrage intern an einen angegebenen Ort weiterzuleiten.
  • X-Accel-Buffering: Steuert, ob Nginx die Antwort puffern soll oder nicht.
  • X-Accel-Charset: Legt die Zeichencodierung für die Antwort fest, wenn X-Accel-Redirect verwendet wird.
  • X-Accel-Expires: Setzt die Ablaufzeit für die Antwort, wenn X-Accel-Redirect verwendet wird.
  • X-Accel-Limit-Rate: Begrenzt die Übertragungsrate für Antworten, wenn X-Accel-Redirect verwendet wird.

Zum Beispiel löst der Header X-Accel-Redirect eine interne Weiterleitung in nginx aus. Eine nginx-Konfiguration mit z. B. root / und einer Antwort des Webservers mit X-Accel-Redirect: .env bewirkt daher, dass nginx den Inhalt von /.env ausliefert (Path Traversal).

Standardwert in der map-Direktive

In der Nginx-Konfiguration spielt die map-Direktive oft eine Rolle bei der Zugriffssteuerung. Ein häufiger Fehler ist, keinen Standardwert anzugeben, was zu unautorisiertem Zugriff führen kann. Zum Beispiel:

http {
map $uri $mappocallow {
/map-poc/private 0;
/map-poc/secret 0;
/map-poc/public 1;
}
}
server {
location /map-poc {
if ($mappocallow = 0) {return 403;}
return 200 "Hello. It is private area: $mappocallow";
}
}

Ohne ein default kann ein böswilliger Benutzer die Sicherheit umgehen, indem er auf eine undefinierte URI innerhalb von /map-poc zugreift. Das Nginx-Handbuch empfiehlt, einen Standardwert zu setzen, um solche Probleme zu vermeiden.

DNS-Spoofing-Schwachstelle

DNS-Spoofing gegen Nginx ist unter bestimmten Bedingungen möglich. Wenn ein Angreifer den von Nginx verwendeten DNS-Server kennt und dessen DNS-Abfragen abfangen kann, kann er DNS-Einträge fälschen. Diese Methode ist jedoch wirkungslos, wenn Nginx so konfiguriert ist, dass es localhost (127.0.0.1) für die DNS-Auflösung verwendet. Nginx erlaubt, einen DNS-Server wie folgt anzugeben:

resolver 8.8.8.8;

proxy_pass and internal Direktiven

Die proxy_pass Direktive wird verwendet, um Anfragen an andere Server weiterzuleiten, entweder intern oder extern. Die internal Direktive stellt sicher, dass bestimmte locations nur innerhalb von Nginx zugänglich sind. Obwohl diese Direktiven für sich genommen keine Schwachstellen darstellen, erfordert ihre Konfiguration eine sorgfältige Prüfung, um Sicherheitslücken zu vermeiden.

proxy_set_header Upgrade & Connection

Wenn der nginx-Server so konfiguriert ist, dass Upgrade- und Connection-Header weitergegeben werden, könnte eine h2c Smuggling attack durchgeführt werden, um auf geschützte/internal Endpunkte zuzugreifen.

Caution

Diese Schwachstelle würde einem Angreifer ermöglichen, eine direkte Verbindung zum proxy_pass-Endpunkt (http://backend:9999 in diesem Fall) herzustellen, deren Inhalt nicht von nginx überprüft wird.

Beispiel für eine verwundbare Konfiguration, um /flag von hier zu stehlen:

server {
listen       443 ssl;
server_name  localhost;

ssl_certificate       /usr/local/nginx/conf/cert.pem;
ssl_certificate_key   /usr/local/nginx/conf/privkey.pem;

location / {
proxy_pass http://backend:9999;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}

location /flag {
deny all;
}

Warning

Beachte, dass selbst wenn proxy_pass auf einen spezifischen Pfad wie http://backend:9999/socket.io zeigte, die Verbindung mit http://backend:9999 aufgebaut wird, sodass du jeden anderen Pfad innerhalb dieses internen Endpunkts erreichen kannst. Es spielt also keine Rolle, ob ein Pfad in der URL von proxy_pass angegeben ist.

HTTP/3 QUIC Modul remote DoS & leak (2024)

Im Jahr 2024 veröffentlichte Nginx CVE-2024-31079, CVE-2024-32760, CVE-2024-34161 und CVE-2024-35200, die zeigen, dass eine einzelne feindliche QUIC-Session Worker-Prozesse zum Absturz bringen oder memory leak verursachen kann, sobald das experimentelle ngx_http_v3_module kompiliert ist und ein listen ... quic-Socket exponiert wird. Betroffene Builds sind 1.25.0–1.25.5 und 1.26.0, während 1.27.0/1.26.1 die Fixes liefern; die memory disclosure (CVE-2024-34161) erfordert zusätzlich MTUs größer als 4096 Bytes, damit sensitive Daten offengelegt werden (Details in der unten referenzierten nginx-Advisory von 2024).

Recon & exploitation Hinweise

  • HTTP/3 ist opt-in, also scanne nach Alt-Svc: h3=":443"-Antworten oder brute-force UDP/443 QUIC handshakes; sobald bestätigt, fuzz die handshake- und STREAM-Frames mit custom quiche-client/nghttp3 payloads, um Worker-Abstürze zu provozieren und log leakage zu erzwingen.
  • Schnell fingerprint target support with:
nginx -V 2>&1 | grep -i http_v3
rg -n "listen .*quic" /etc/nginx/

Umgehung der Client-Zertifikat-Authentifizierung via TLS-Session-Resumption (CVE-2025-23419)

Eine Advisory vom Februar 2025 hat offenbart, dass nginx 1.11.4–1.27.3, gebaut mit OpenSSL, das Wiederverwenden einer TLS 1.3-Session von einem namensbasierten vhost in einem anderen erlaubt. Dadurch kann ein Client, der mit einem zertifikatsfreien Host verhandelt hat, das Ticket/PSK erneut abspielen, um in einen vhost mit ssl_verify_client on; zu wechseln und mTLS vollständig zu umgehen. Der Bug tritt auf, wenn mehrere virtual hosts denselben TLS 1.3-Session-Cache und dieselben Tickets teilen (siehe die 2025 nginx-Advisory weiter unten).

Angreifer-Playbook

# 1. Create a TLS session on the public vhost and save the session ticket
openssl s_client -connect public.example.com:443 -sess_out ticket.pem

# 2. Replay that session ticket against the mTLS vhost before it expires
openssl s_client -connect admin.example.com:443 -sess_in ticket.pem -ign_eof

Wenn das Ziel verwundbar ist, schließt der zweite Handshake ab, ohne ein Client-Zertifikat zu präsentieren, und offenbart geschützte Bereiche.

Was zu prüfen ist

  • Gemischte server_name-Blöcke, die ssl_session_cache shared:SSL sowie ssl_session_tickets on; teilen.
  • Admin/API-Blöcke, die mTLS erwarten, aber gemeinsame session cache-/ticket-Einstellungen von öffentlichen Hosts erben.
  • Automatisierung, die TLS 1.3 session resumption global aktiviert (z. B. Ansible roles), ohne die vhost-Isolation zu berücksichtigen.

HTTP/2 Rapid Reset-Resilienz (Verhalten von CVE-2023-44487)

Der HTTP/2 Rapid Reset attack (CVE-2023-44487) betrifft nginx weiterhin, wenn Betreiber keepalive_requests oder http2_max_concurrent_streams über die Defaults hinaus hochsetzen: Ein Angreifer öffnet eine HTTP/2-Verbindung, flutet sie mit tausenden Streams und sendet dann sofort RST_STREAM-Frames, sodass die Konkurrenzobergrenze nie erreicht wird, während die CPU durch die tear-down logic weiter belastet wird. Nginx-Defaults (128 concurrent streams, 1000 keepalive requests) halten den Schadensradius klein; das erhebliche Anheben dieser Limits macht es trivial, Worker bereits von einem einzigen Client zu verhungern (siehe das unten referenzierte F5 write-up).

Erkennungstipps

# Highlight risky knobs
rg -n "http2_max_concurrent_streams" /etc/nginx/
rg -n "keepalive_requests" /etc/nginx/

Hosts, die ungewöhnlich hohe Werte für diese Direktiven preisgeben, sind erstklassige Ziele: ein HTTP/2-Client kann in einer Schleife Streams erzeugen und sofort RST_STREAM-Frames senden, um die CPU auszulasten, ohne das Gleichzeitigkeitslimit zu überschreiten.

Selbst ausprobieren

Detectify hat ein GitHub-Repository erstellt, in dem Sie Docker verwenden können, um Ihren eigenen verwundbaren Nginx-Testserver mit einigen der in diesem Artikel besprochenen Fehlkonfigurationen aufzusetzen und diese selbst zu finden!

https://github.com/detectify/vulnerable-nginx

Statische Analyzer-Tools

gixy-ng & Gixy-Next & GIXY

  • Gixy-Next (ein aktualisierter Fork von GIXY) ist ein Tool zur Analyse von Nginx-Konfigurationen mit dem Ziel, Vulnerabilities, unsichere Direktiven und riskante Fehlkonfigurationen zu finden. Es erkennt auch Fehlkonfigurationen, die die Performance beeinträchtigen, und entdeckt verpasste Härtungsmaßnahmen, sodass eine automatisierte Erkennung von Schwachstellen möglich ist.
  • gixy-ng (der aktiv gepflegte Fork von GIXY) ist ein Tool zur Analyse von Nginx-Konfigurationen mit dem Ziel, Vulnerabilities, unsichere Direktiven und riskante Fehlkonfigurationen zu finden. Es erkennt auch Fehlkonfigurationen, die die Performance beeinträchtigen, und entdeckt verpasste Härtungsmaßnahmen, sodass eine automatisierte Erkennung von Schwachstellen möglich ist.

Nginxpwner

Nginxpwner ist ein einfaches Tool, um nach häufigen Nginx-Fehlkonfigurationen und Vulnerabilities zu suchen.

Referenzen

Tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks