Nginx

Support HackTricks

Natychmiastowo dostępna konfiguracja do oceny podatności i testów penetracyjnych. Przeprowadź pełny pentest z dowolnego miejsca z ponad 20 narzędziami i funkcjami, które obejmują od rekonesansu po raportowanie. Nie zastępujemy pentesterów - rozwijamy niestandardowe narzędzia, moduły wykrywania i eksploatacji, aby dać im z powrotem trochę czasu na głębsze badania, przełamywanie zabezpieczeń i zabawę.

Brak lokalizacji 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 wyznaczone jako katalog główny. Ta konfiguracja umożliwia dostęp do plików w określonym katalogu głównym, takich jak /hello.txt. Jednak ważne jest, aby zauważyć, że zdefiniowana jest tylko konkretna lokalizacja (/hello.txt). Nie ma konfiguracji dla lokalizacji głównej (location / {...}). To pominięcie oznacza, że dyrektywa root ma zastosowanie globalnie, co umożliwia żądaniom do ścieżki głównej / dostęp do plików w /etc/nginx.

Krytyczne zagadnienie bezpieczeństwa wynika z tej konfiguracji. Proste żądanie GET, takie jak GET /nginx.conf, może ujawnić wrażliwe informacje, serwując plik konfiguracyjny Nginx znajdujący się w /etc/nginx/nginx.conf. Ustawienie katalogu głównego na mniej wrażliwy katalog, taki jak /etc, może złagodzić to ryzyko, jednak nadal może umożliwić niezamierzony dostęp do innych krytycznych plików, w tym innych plików konfiguracyjnych, dzienników dostępu, a nawet zaszyfrowanych poświadczeń używanych do podstawowej autoryzacji HTTP.

Alias LFI Misconfiguration

W plikach konfiguracyjnych Nginx należy dokładnie sprawdzić dyrektywy "location". Wrażliwość znana jako Local File Inclusion (LFI) może być niezamierzenie wprowadzona przez konfigurację, która przypomina następującą:

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

Ta konfiguracja jest podatna na ataki LFI, ponieważ serwer interpretuje żądania takie jak /imgs../flag.txt jako próbę uzyskania dostępu do plików poza zamierzonym katalogiem, co skutkuje efektywnym rozwiązaniem do /path/images/../flag.txt. Ta wada pozwala atakującym na pobieranie plików z systemu plików serwera, które nie powinny być dostępne przez sieć.

Aby złagodzić tę podatność, konfiguracja powinna zostać dostosowana do:

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

Unsafe path restriction

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 / Podział żądania HTTP

Wrażliwe zmienne $uri i $document_uri, które można naprawić, zastępując je $request_uri.

Wyrażenie regularne również może być wrażliwe, jak:

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

location ~ /docs/([^/\s])? { … $1 … } - Nie wrażliwe (sprawdza spacje)

location ~ /docs/(.*)? { … $1 … } - Nie wrażliwe

Wrażliwość w konfiguracji Nginx jest pokazana w poniższym przykładzie:

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

Znaki \r (Carriage Return) i \n (Line Feed) oznaczają znaki nowej linii w żądaniach HTTP, a ich zakodowane w URL formy są reprezentowane jako %0d%0a. Włączenie tych znaków w żądaniu (np. http://localhost/%0d%0aDetectify:%20clrf) do źle skonfigurowanego serwera skutkuje tym, że serwer wydaje nowy nagłówek o nazwie Detectify. Dzieje się tak, ponieważ zmienna $uri dekoduje zakodowane w URL 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 związanych z wstrzykiwaniem CRLF i dzieleniem odpowiedzi na https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/.

Ta technika jest wyjaśniona w tej prezentacji z przykładami podatności i mechanizmami wykrywania. Na przykład, aby wykryć tę błędną konfigurację z perspektywy czarnej skrzynki, możesz użyć tych żądań:

  • https://example.com/%20X - Dowolny kod HTTP

  • https://example.com/%20H - 400 Bad Request

Jeśli jest podatny, pierwsze zwróci, ponieważ "X" jest dowolną metodą HTTP, a drugie zwróci błąd, ponieważ H nie jest prawidłową metodą. Serwer otrzyma coś takiego: GET / H HTTP/1.1 i to spowoduje błąd.

Inne przykłady wykrywania to:

  • http://company.tld/%20HTTP/1.1%0D%0AXXXX:%20x - Dowolny kod HTTP

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

Niektóre znalezione podatne konfiguracje przedstawione w tej prezentacji to:

  • Zauważ, jak $uri jest ustawione tak, jak jest w końcowym URL

location ^~ /lite/api/ {
proxy_pass http://lite-backend$uri$is_args$args;
}
  • Zauważ, że ponownie $uri znajduje się w URL (tym razem wewnątrz parametru)

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

Any variable

Odkryto, że dane dostarczone przez użytkownika mogą być traktowane jako zmienna Nginx w określonych okolicznościach. Przyczyna tego zachowania pozostaje nieco niejasna, jednak nie jest to rzadkie ani proste do weryfikacji. Ta anomalia została podkreślona w raporcie bezpieczeństwa na HackerOne, który można zobaczyć tutaj. Dalsze badania komunikatu o błędzie doprowadziły do zidentyfikowania jego wystąpienia w module filtra SSI w kodzie Nginx, wskazując na Server Side Includes (SSI) jako przyczynę.

Aby wykryć tę błędną konfigurację, można wykonać następujące polecenie, które polega na ustawieniu nagłówka referer w celu przetestowania drukowania zmiennej:

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

Skany tej niewłaściwej konfiguracji w różnych systemach ujawniły wiele przypadków, w których zmienne Nginx mogły być drukowane przez użytkownika. Jednak spadek liczby podatnych przypadków sugeruje, że wysiłki na rzecz naprawienia tego problemu były w pewnym stopniu skuteczne.

Odczyt surowej odpowiedzi backendu

Nginx oferuje funkcję poprzez proxy_pass, która umożliwia 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. Osiąga się to poprzez serwowanie przez Nginx niestandardowych stron błędów w odpowiedzi na błędy backendu. Jednak pojawiają się wyzwania, gdy Nginx napotyka nieprawidłowe żądanie HTTP. Takie żądanie jest przekazywane do backendu w takiej formie, w jakiej zostało odebrane, a surowa odpowiedź backendu jest następnie bezpośrednio wysyłana do klienta bez interwencji Nginx.

Rozważmy przykładowy scenariusz z aplikacją 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!"]

Aby to zarządzać, w konfiguracji Nginx używane są specyficzne dyrektywy:

http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
  • proxy_intercept_errors: Ta dyrektywa umożliwia Nginxowi serwowanie niestandardowej odpowiedzi dla odpowiedzi backendu z kodem statusu większym niż 300. Zapewnia, że w przypadku naszej aplikacji uWSGI odpowiedź 500 Error jest 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 wysłane ważne żądanie GET, Nginx przetwarza je normalnie, zwracając standardową odpowiedź błędu bez ujawniania jakichkolwiek 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 dyrektywa merge_slashes w Nginx jest ustawiona na on, co kompresuje wiele ukośników w URL w jeden ukośnik. Ta funkcja, choć upraszcza przetwarzanie URL, może nieumyślnie ukrywać luki w aplikacjach za Nginx, szczególnie tych podatnych na ataki lokalnego włączenia plików (LFI). Eksperci ds. bezpieczeństwa Danny Robinson i Rotem Bar podkreślili potencjalne ryzyko związane z tym domyślnym zachowaniem, szczególnie gdy Nginx działa jako reverse-proxy.

Aby złagodzić takie ryzyko, zaleca się wyłączenie dyrektywy merge_slashes dla aplikacji podatnych na te luki. Zapewnia to, że Nginx przekazuje żądania do aplikacji bez zmiany struktury URL, a tym samym nie maskuje żadnych ukrytych problemów z bezpieczeństwem.

Aby uzyskać więcej informacji, sprawdź Danny Robinson i Rotem Bar.

Maclicious Response Headers

Jak pokazano w tym artykule, istnieją pewne nagłówki, które, jeśli są obecne w odpowiedzi z serwera WWW, zmienią zachowanie proxy Nginx. Możesz je sprawdzić w dokumentacji:

  • 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 dla odpowiedzi przy użyciu X-Accel-Redirect.

  • X-Accel-Limit-Rate: Ogranicza szybkość transferu dla odpowiedzi przy użyciu X-Accel-Redirect.

Na przykład nagłówek X-Accel-Redirect spowoduje wewnętrzne przekierowanie w Nginx. Tak więc posiadanie konfiguracji Nginx z czymś takim jak root / i odpowiedzi z serwera WWW z X-Accel-Redirect: .env spowoduje, że Nginx wyśle zawartość /.env (Path Traversal).

Wartość domyślna w dyrektywie Map

W konfiguracji Nginx dyrektywa map często odgrywa rolę w kontroli autoryzacji. Powszechnym błędem jest nieokreślenie wartości domyślnej, 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 /map-poc. Podręcznik Nginx zaleca ustawienie wartości domyślnej, aby uniknąć takich problemów.

Luka w Spoofingu DNS

Spoofing DNS przeciwko Nginx jest możliwy w określonych warunkach. Jeśli atakujący zna serwer DNS używany przez Nginx i może przechwycić jego zapytania DNS, może sfałszować rekordy DNS. Ta metoda jest jednak nieskuteczna, jeśli Nginx jest skonfigurowany do używania localhost (127.0.0.1) do rozwiązywania DNS. Nginx pozwala na określenie serwera DNS w następujący sposób:

resolver 8.8.8.8;

proxy_pass i internal Dyrektywy

Dyrektywa proxy_pass jest wykorzystywana do przekierowywania żądań do innych serwerów, zarówno wewnętrznych, jak i zewnętrznych. Dyrektywa internal zapewnia, że niektóre lokalizacje są dostępne tylko wewnątrz Nginx. Chociaż te dyrektywy same w sobie nie są lukami, ich konfiguracja wymaga starannego zbadania, aby zapobiec lukom w zabezpieczeniach.

proxy_set_header Upgrade & Connection

Jeśli serwer nginx jest skonfigurowany do przekazywania nagłówków Upgrade i Connection, można przeprowadzić atak h2c Smuggling, aby uzyskać dostęp do chronionych/wewnętrznych punktów końcowych.

Ta luka pozwoliłaby atakującemu na nawiązanie bezpośredniego połączenia z punktem końcowym proxy_pass (http://backend:9999 w tym przypadku), którego zawartość nie będzie sprawdzana przez nginx.

Przykład podatnej konfiguracji do kradzieży /flag z tutaj:

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

Zauważ, że nawet jeśli proxy_pass wskazywał na konkretną ścieżkę taką jak http://backend:9999/socket.io, połączenie zostanie nawiązane z http://backend:9999, więc możesz skontaktować się z każdą inną ścieżką wewnątrz tego wewnętrznego punktu końcowego. Więc nie ma znaczenia, czy ścieżka jest określona w URL proxy_pass.

Spróbuj sam

Detectify stworzył repozytorium na GitHubie, w którym możesz użyć Dockera do skonfigurowania własnego podatnego serwera testowego Nginx z niektórymi z omówionych w tym artykule błędów konfiguracyjnych i spróbować je znaleźć samodzielnie!

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

Narzędzia analizy statycznej

Gixy to narzędzie do analizy konfiguracji Nginx. Głównym celem Gixy jest zapobieganie błędom konfiguracyjnym związanym z bezpieczeństwem oraz automatyzacja wykrywania wad.

Nginxpwner to proste narzędzie do wyszukiwania powszechnych błędów konfiguracyjnych Nginx i podatności.

Odniesienia

Natychmiast dostępna konfiguracja do oceny podatności i testów penetracyjnych. Przeprowadź pełny pentest z dowolnego miejsca z ponad 20 narzędziami i funkcjami, które obejmują od rekonesansu po raportowanie. Nie zastępujemy pentesterów - rozwijamy niestandardowe narzędzia, moduły wykrywania i eksploatacji, aby dać im z powrotem trochę czasu na głębsze badania, przełamywanie zabezpieczeń i zabawę.

Wsparcie dla HackTricks

Last updated