hacktricks/network-services-pentesting/pentesting-web/nginx.md

19 KiB
Raw Blame History

Nginx

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Natychmiastowa konfiguracja do oceny podatności i testów penetracyjnych. Uruchom pełne testy penetracyjne z dowolnego miejsca za pomocą ponad 20 narzędzi i funkcji, które obejmują rozpoznanie, aż po raportowanie. Nie zastępujemy pentesterów - rozwijamy niestandardowe narzędzia, moduły wykrywania i eksploatacji, aby umożliwić im zagłębienie się głębiej, zdobycie powłok i dobrą zabawę.

{% embed url="https://pentest-tools.com/" %}

Brakujące miejsce root

Podczas konfigurowania serwera Nginx, dyrektywa root odgrywa kluczową rolę, definiując katalog podstawowy, z którego są serwowane 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 określony jako katalog główny. Ta konfiguracja umożliwia dostęp do plików w określonym katalogu głównym, takich jak /hello.txt. Jednakże ważne jest zauważenie, że zdefiniowana jest tylko określona lokalizacja (/hello.txt). Brak konfiguracji dla lokalizacji głównej (location / {...}). Ta omissja oznacza, że dyrektywa root jest stosowana globalnie, umożliwiając żądania do ścieżki głównej / w celu uzyskania dostępu do plików w /etc/nginx.

Z tej konfiguracji wynika istotne zagrożenie dla bezpieczeństwa. Proste żądanie GET, takie jak GET /nginx.conf, może ujawnić wrażliwe informacje poprzez udostępnienie pliku konfiguracyjnego Nginx znajdującego się w /etc/nginx/nginx.conf. Ustawienie roota na mniej wrażliwy katalog, np. /etc, może zmniejszyć to ryzyko, ale nadal może umożliwiać niezamierzony dostęp do innych istotnych plików, w tym innych plików konfiguracyjnych, logów dostępu, a nawet zaszyfrowanych poświadczeń używanych do autoryzacji podstawowej protokołu HTTP.

Konfiguracja Alias LFI

W plikach konfiguracyjnych Nginx konieczna jest dokładna inspekcja dyrektyw "location". Podatność znana jako Local File Inclusion (LFI) może zostać nieumyślnie wprowadzona poprzez konfigurację, która przypomina poniższe:

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

Ta konfiguracja jest podatna na ataki LFI ze względu na to, że serwer interpretuje żądania takie jak /imgs../flag.txt jako próbę dostępu do plików poza zamierzonym katalogiem, efektywnie rozwiązując się do /path/images/../flag.txt. Ta wada pozwala atakującym na pobieranie plików z systemu plików serwera, do których nie powinno być dostępu 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

Niebezpieczne ograniczenie ścieżki

Sprawdź następującą stronę, aby dowiedzieć się, jak ominąć dyrektywy takie jak:

location = /admin {
deny all;
}

location = /admin/ {
deny all;
}

Niewłaściwe użycie zmiennej / Podział żądania HTTP

{% hint style="danger" %} Narażone zmienne $uri i $document_uri mogą zostać naprawione poprzez ich zastąpienie przez $request_uri.

Regex może również być narażony, na przykład:

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

location ~ /docs/([^/\s])? { … $1 … } - Nie narażone (sprawdzanie spacji)

location ~ /docs/(.*)? { … $1 … } - Nie narażone {% endhint %}

Przykładem podatności w konfiguracji Nginx jest:

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

Znaki \r (powrót karetki) i \n (nowa linia) oznaczają nowe znaki w żądaniach HTTP, a ich zapis w postaci URL-encoded to %0d%0a. Umieszczenie tych znaków w żądaniu (np. http://localhost/%0d%0aDetectify:%20clrf) do źle skonfigurowanego serwera skutkuje wydaniem przez serwer nowego nagłówka o nazwie Detectify. Dzieje się tak, ponieważ zmienna $uri dekoduje URL-encoded nowe znaki, 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 ryzyku wstrzykiwania CRLF i podziału odpowiedzi na https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/.

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

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

Jeśli jest podatny, pierwsze żądanie zwróci "X" jako dowolną metodę HTTP, a drugie spowoduje błąd, ponieważ H nie jest prawidłową metodą. Serwer otrzyma coś w rodzaju: GET / H HTTP/1.1, co 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 adresie URL.
location ^~ /lite/api/ {
proxy_pass http://lite-backend$uri$is_args$args;
}
  • Zauważ, jak ponownie $uri znajduje się w adresie 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;
}

Dowolna zmienna

Odkryto, że dane dostarczone przez użytkownika mogą być traktowane jako zmienna Nginx w określonych okolicznościach. Przyczyna tego zachowania pozostaje w pewnym sensie niejasna, ale nie jest to rzadkie ani proste do zweryfikowania. To nietypowe zjawisko zostało podkreślone w raporcie bezpieczeństwa na HackerOne, który można zobaczyć tutaj. Dalsze dochodzenie w sprawie komunikatu o błędzie doprowadziło do zidentyfikowania jego wystąpienia w module filtru SSI kodu źródłowego Nginx-a, wskazując na Server Side Includes (SSI) jako główną przyczynę.

Aby wykryć tę błędną konfigurację, można wykonać poniższą komendę, która polega na ustawieniu nagłówka referer w celu przetestowania drukowania zmiennej:

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

Skanowania dla tej konfiguracji na różnych systemach ujawniły wiele przypadków, gdzie zmienne Nginx mogły być wydrukowane przez użytkownika. Jednakże spadek liczby podatnych przypadków sugeruje, że wysiłki mające na celu załatanie tego problemu były w pewnym stopniu skuteczne.

Odczyt surowej odpowiedzi z backendu

Nginx oferuje funkcję poprzez 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. Jest to osiągane poprzez serwowanie Nginx stron błędów niestandardowych w odpowiedzi na błędy backendu. Jednakże pojawiają się wyzwania, gdy Nginx napotyka nieprawidłowe żądanie HTTP. Takie żądanie jest przekazywane do backendu w otrzymanej postaci, a surowa odpowiedź backendu jest następnie bezpośrednio wysyłana do klienta bez interwencji 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!"]

Aby zarządzać tym, używane są konkretne dyrektywy w konfiguracji Nginx:

http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
  • proxy_intercept_errors: Ta dyrektywa umożliwia Nginxowi obsługę niestandardowej odpowiedzi dla odpowiedzi z backendu z kodem stanu większym niż 300. Zapewnia, że dla naszej przykładowej aplikacji uWSGI odpowiedź 500 Error jest przechwytywana i obsługiwana przez Nginx.
  • proxy_hide_header: Jak sugeruje nazwa, ta dyrektywa ukrywa określone nagłówki HTTP przed klientem, zwiększając prywatność i bezpieczeństwo.

Gdy zostanie wysłane poprawne żądanie GET, Nginx przetwarza je normalnie, zwracając standardową odpowiedź błędu, nie ujawniając żadnych tajnych nagłówków. Jednak nieprawidłowe żądanie HTTP omija ten mechanizm, co skutkuje ujawnieniem surowych odpowiedzi z backendu, w tym tajnych nagłówków i komunikatów błędów.

merge_slashes ustawione na off

Domyślnie dyrektywa merge_slashes Nginxa jest ustawiona na on, co spowoduje skompresowanie wielokrotnych ukośników w adresie URL do pojedynczego ukośnika. Ta funkcja, podczas upraszczania przetwarzania adresów URL, może niechcący ukrywać podatności w aplikacjach za Nginx, zwłaszcza tych podatnych na ataki lokalnego dołączania plików (LFI). Eksperci ds. bezpieczeństwa Danny Robinson i Rotem Bar zwrócili uwagę na potencjalne ryzyko związane z tym domyślnym zachowaniem, zwłaszcza gdy Nginx działa jako odwrotny proxy.

Aby zmniejszyć takie ryzyko, zaleca się wyłączenie dyrektywy merge_slashes dla aplikacji podatnych na te podatności. Zapewnia to, że Nginx przekazuje żądania do aplikacji bez zmiany struktury adresu URL, nie maskując żadnych istniejących problemów związanych z bezpieczeństwem.

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

Złośliwe nagłówki odpowiedzi

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

  • X-Accel-Redirect: Wskazuje Nginxowi wewnętrzne przekierowanie żądania 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. Dlatego posiadanie konfiguracji Nginx z czymś takim jak root / i odpowiedź z serwera WWW z X-Accel-Redirect: .env spowoduje, że Nginx wyśle zawartość /.env (Przechodzenie ścieżką).

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 ominąć zabezpieczenia, uzyskując dostęp do niezdefiniowanego URI wewnątrz /map-poc. Podręcznik Nginx zaleca ustawienie wartości domyślnej, aby uniknąć takich problemów.

Podatność na podszywanie DNS

Podszywanie DNS wobec Nginx jest możliwe w określonych warunkach. Jeśli atakujący zna serwer DNS używany przez Nginx i może przechwycić jego zapytania DNS, może podszyć się pod rekordy DNS. Ta metoda jednak nie działa, jeśli Nginx jest skonfigurowany do korzystania z localhost (127.0.0.1) do rozwiązywania nazw DNS. Nginx pozwala określić serwer DNS w następujący sposób:

resolver 8.8.8.8;

Dyrektywy proxy_pass i internal

Dyrektywa proxy_pass jest wykorzystywana do przekierowywania żądań do innych serwerów, zarówno wewnętrznie, jak i zewnętrznie. Dyrektywa internal zapewnia, że określone lokalizacje są dostępne tylko w obrębie Nginx. Chociaż te dyrektywy same w sobie nie stanowią podatności, ich konfiguracja wymaga dokładnego 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, atak h2c Smuggling może zostać przeprowadzony w celu uzyskania dostępu do chronionych/wewnętrznych punktów końcowych.

{% hint style="danger" %} Ta podatność pozwoliłaby atakującemu ustanowić bezpośrednie połączenie z punktem końcowym proxy_pass (http://backend:9999 w tym przypadku), którego zawartość nie będzie sprawdzana przez nginx. {% endhint %}

Przykład podatnej konfiguracji do kradzieży /flag znajdziesz 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;
}

{% hint style="warning" %} Zauważ, że nawet jeśli proxy_pass wskazywał na określoną ś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 dowolną inną ścieżką wewnątrz tego wewnętrznego punktu końcowego. Dlatego nie ma znaczenia, czy ścieżka jest określona w adresie URL proxy_pass. {% endhint %}

Wypróbuj to samodzielnie

Detectify utworzył repozytorium na GitHubie, gdzie możesz użyć Dockera do skonfigurowania własnego podatnego serwera testowego Nginx z niektórymi błędami konfiguracji omówionymi w tym artykule i spróbować je znaleźć samodzielnie!

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

Narzędzia analizy statycznej

GIXY

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

Nginxpwner

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

Odnośniki

Natychmiastowa dostępność konfiguracji do oceny podatności i testów penetracyjnych. Uruchom pełny test penetracyjny z dowolnego miejsca za pomocą ponad 20 narzędzi i funkcji, które obejmują rozpoznanie, raportowanie. Nie zastępujemy testerów penetracyjnych - rozwijamy niestandardowe narzędzia, moduły wykrywania i eksploatacji, aby umożliwić im zagłębienie się głębiej, zdobycie dostępu i dobrą zabawę.

{% embed url="https://pentest-tools.com/" %}

Zacznij od zera i zostań ekspertem AWS hackingu z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks: