hacktricks/network-services-pentesting/pentesting-web/nginx.md
2024-02-11 01:46:25 +00:00

16 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 dostępność konfiguracji do oceny podatności i testowania penetracyjnego. Uruchom pełne testowanie penetracyjne z dowolnego miejsca za pomocą ponad 20 narzędzi i funkcji, które obejmują rozpoznanie i raportowanie. Nie zastępujemy pentesterów - opracowujemy niestandardowe narzędzia, moduły wykrywania i eksploatacji, aby dać im więcej czasu na głębsze drążenie, otwieranie powłok i dobrą zabawę.

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

Brak lokalizacji root

Podstawy konfiguracji katalogu głównego Nginx

Podczas konfigurowania serwera Nginx, kluczową rolę odgrywa dyrektywa root, która definiuje podstawowy katalog, z którego są serwowane pliki. Przyjrzyj się poniższemu przykładowi:

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 ważne jest zauważenie, że zdefiniowana jest tylko określona lokalizacja (/hello.txt). Nie ma konfiguracji dla lokalizacji głównej (location / {...}). Ta pominięta część oznacza, że dyrektywa root ma zastosowanie globalne, umożliwiając żądania do ścieżki głównej / w celu uzyskania dostępu do plików znajdujących się w /etc/nginx.

Z tej konfiguracji wynika istotne zagrożenie dla bezpieczeństwa. Proste żądanie GET, takie jak GET /nginx.conf, może ujawnić poufne informacje, udostępniając plik konfiguracyjny Nginx znajdujący się w /etc/nginx/nginx.conf. Ustawienie root na mniej poufnym katalogu, takim jak /etc, może zmniejszyć to ryzyko, ale nadal może umożliwiać niezamierzony dostęp do innych ważnych plików, w tym innych plików konfiguracyjnych, dzienników dostępu, a nawet zaszyfrowanych poświadczeń używanych do uwierzytelniania podstawowego protokołu HTTP.

Błędna konfiguracja Alias LFI

W plikach konfiguracyjnych Nginx warto dokładnie sprawdzić dyrektywy "location". Może zostać nieumyślnie wprowadzona podatność związana z lokalnym uwzględnianiem plików (LFI) poprzez konfigurację podobną do poniższej:

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

Ta konfiguracja jest podatna na ataki LFI z powodu interpretowania przez serwer żądań takich jak /imgs../flag.txt jako próby dostępu do plików spoza zamierzonego katalogu, co efektywnie prowadzi do rozwiązania /path/images/../flag.txt. Ta luka umożliwia atakującym 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

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

{% content-ref url="../../pentesting-web/proxy-waf-protections-bypass.md" %} proxy-waf-protections-bypass.md {% endcontent-ref %}

Niebezpieczne użycie zmiennych

Podatność w konfiguracji Nginx jest przedstawiona na poniższym przykładzie:

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

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

Dowolna zmienna

Odkryto, że dane dostarczone przez użytkownika mogą być traktowane jako zmienna Nginx w określonych okolicznościach. Przyczyna tego zachowania pozostaje nieco niejasna, ale nie jest to rzadkie ani łatwe do zweryfikowania. To odstępstwo zostało podkreślone w raporcie o bezpieczeństwie na HackerOne, który można zobaczyć tutaj. Dalsze badania nad komunikatem o błędzie doprowadziły do zidentyfikowania jego występowania w module filtru SSI kodu źródłowego Nginx, wskazując na Server Side Includes (SSI) jako główną przyczynę.

Aby wykryć tę nieprawidłową 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

Skanowanie tej konfiguracji na różnych systemach ujawniło wiele przypadków, w których zmienne Nginx mogły być wydrukowane przez użytkownika. Jednak spadek liczby podatnych instancji sugeruje, że wysiłki mające na celu naprawienie tego problemu odniosły pewien sukces.

Odczytywanie surowych odpowiedzi z backendu

Nginx oferuje funkcję za pomocą 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. Jest to osiągane 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 niezmienionej postaci, a surowa odpowiedź backendu jest bezpośrednio wysyłana do klienta bez ingerencji Nginx.

Przyjrzyjmy się przykładowemu scenariuszowi z wykorzystaniem 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 to zarządzać, 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 serwera backendowego o kodzie statusu większym niż 300. Zapewnia to, że w przypadku naszej aplikacji uWSGI, odpowiedź 500 Error zostanie przechwycona i obsłużona przez Nginx.
  • proxy_hide_header: Jak wskazuje nazwa, ta dyrektywa ukrywa określone nagłówki HTTP przed klientem, poprawiając prywatność i bezpieczeństwo.

Gdy zostanie wysłane prawidłowe żą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 serwera backendowego, w tym tajnych nagłówków i komunikatów o błędach.

merge_slashes ustawione na off

Domyślnie dyrektywa merge_slashes w Nginxie jest ustawiona na on, co powoduje kompresję wielu ukośników w adresie URL do pojedynczego ukośnika. Ta funkcja, choć usprawnia przetwarzanie adresów URL, może niechcący ukrywać podatności w aplikacjach działających za Nginxem, zwłaszcza tych podatnych na ataki lokalnego włączenia 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 serwer proxy odwracający.

Aby zminimalizować 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 adresu URL, nie maskując żadnych istniejących problemów zabezpieczeń.

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

Domyślna wartość w dyrektywie Map

W konfiguracji Nginx, dyrektywa map często odgrywa rolę w kontroli autoryzacji. Częstym błędem jest nieokreślenie domyślnej wartości, 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 ustawienia default, złośliwy użytkownik może ominąć 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.

Podatność na DNS Spoofing

Podatność na DNS spoofing w przypadku Nginx jest możliwa w określonych warunkach. Jeśli atakujący zna serwer DNS używany przez Nginx i może przechwycić jego zapytania DNS, może podrobić rekordy DNS. Jednak ta metoda jest nieskuteczna, jeśli Nginx jest skonfigurowany do korzystania z localhost (127.0.0.1) dla rozwiązywania DNS. Nginx umożliwia określenie serwera DNS w następujący sposób:

resolver 8.8.8.8;

Dyrektywy proxy_pass i internal

Dyrektywa proxy_pass jest używana do przekierowywania żądań do innych serwerów, zarówno wewnętrznych, jak i zewnętrznych. Dyrektywa internal zapewnia, że określone lokalizacje są dostępne tylko w obrębie Nginx. Chociaż same w sobie te dyrektywy nie są podatnościami, konieczne jest dokładne zbadanie ich konfiguracji, 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że zostać przeprowadzony atak h2c Smuggling, aby uzyskać dostęp do chronionych/wewnętrznych punktów końcowych.

{% hint style="danger" %} Ta podatność umożliwiłaby atakującemu ustanowienie bezpośredniego połączenia z punktem końcowym proxy_pass (http://backend:9999 w tym przypadku), którego zawartość nie zostanie sprawdzona przez nginx. {% endhint %}

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

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ślony ś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. Nie ma znaczenia, czy ścieżka jest określona w adresie URL proxy_pass. {% endhint %}

Spróbuj sam

Detectify utworzył repozytorium GitHub, w którym możesz użyć Dockera, aby skonfigurować własny serwer testowy Nginx z niektórymi omówionymi w tym artykule błędami konfiguracji i spróbować je znaleźć samodzielnie!

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

Narzędzia do statycznej analizy

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 konfiguracji i podatności Nginx.

Odwołania

Natychmiastowa dostępność konfiguracji do oceny podatności i testowania penetracyjnego. Uruchom pełny test penetracyjny z dowolnego miejsca za pomocą ponad 20 narzędzi i funkcji, które obejmują rozpoznanie i raportowanie. Nie zastępujemy testerów penetracyjnych - opracowujemy niestandardowe narzędzia, moduły wykrywania i eksploatacji, aby dać im więcej czasu na dogłębne badania, zdobywanie powłok i dobrą zabawę.

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

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

Inne sposoby wsparcia HackTricks: