mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/network-services-pentesting/pentesting-web/nginx.md'] t
This commit is contained in:
parent
ee2beef5fd
commit
32fecc4ada
BIN
src/images/nginx_try_files.png
Normal file
BIN
src/images/nginx_try_files.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 190 KiB |
@ -16,13 +16,13 @@ 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`.
|
||||
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 globalne, 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 <a href="#alias-lfi-misconfiguration" id="alias-lfi-misconfiguration"></a>
|
||||
|
||||
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ę przypominającą następującą:
|
||||
W plikach konfiguracyjnych Nginx należy dokładnie zbadać 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/;
|
||||
@ -64,7 +64,7 @@ deny all;
|
||||
|
||||
## Niebezpieczne użycie zmiennych / Podział żądania HTTP <a href="#unsafe-variable-use" id="unsafe-variable-use"></a>
|
||||
|
||||
> [!CAUTION]
|
||||
> [!OSTRZEŻENIE]
|
||||
> 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:
|
||||
@ -81,7 +81,7 @@ 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:
|
||||
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 wydaniem przez serwer nowego nagłówka 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
|
||||
@ -93,12 +93,12 @@ 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/](https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/).
|
||||
|
||||
Ta technika jest również [**wyjaśniona w tym wykładzie**](https://www.youtube.com/watch?v=gWQyWdZbdoY&list=PL0xCSYnG_iTtJe2V6PQqamBF73n7-f1Nr&index=77) z przykładami podatnymi i mechanizmami wykrywania. Na przykład, aby wykryć tę niewłaściwą konfigurację z perspektywy czarnej skrzynki, możesz użyć tych żądań:
|
||||
Ta technika jest [**wyjaśniona w tym wykładzie**](https://www.youtube.com/watch?v=gWQyWdZbdoY&list=PL0xCSYnG_iTtJe2V6PQqamBF73n7-f1Nr&index=77) z przykładami podatnymi i mechanizmami wykrywania. Na przykład, aby wykryć tę niewłaściwą 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 jako "X", ponieważ jest to dowolna metoda 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.
|
||||
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 wywoła błąd.
|
||||
|
||||
Inne przykłady wykrywania to:
|
||||
|
||||
@ -127,17 +127,67 @@ 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 łatwe do zweryfikowania. Ta anomalia została podkreślona w raporcie bezpieczeństwa na HackerOne, który można zobaczyć [tutaj](https://hackerone.com/reports/370094). Dalsze badania komunikatu o błędzie doprowadziły do zidentyfikowania jego wystąpienia w [module filtra SSI w kodzie Nginx](https://github.com/nginx/nginx/blob/2187586207e1465d289ae64cedc829719a048a39/src/http/modules/ngx_http_ssi_filter_module.c#L365), wskazując na Server Side Includes (SSI) jako przyczynę.
|
||||
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 łatwe do zweryfikowania. Ta anomalia została podkreślona w raporcie bezpieczeństwa na HackerOne, który można zobaczyć [tutaj](https://hackerone.com/reports/370094). Dalsze badania nad komunikatem o błędzie doprowadziły do zidentyfikowania jego wystąpienia w [module filtra SSI w kodzie Nginx](https://github.com/nginx/nginx/blob/2187586207e1465d289ae64cedc829719a048a39/src/http/modules/ngx_http_ssi_filter_module.c#L365), 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:
|
||||
```bash
|
||||
$ 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ć wyświetlane przez użytkownika. Jednak spadek liczby podatnych przypadków sugeruje, że wysiłki na rzecz naprawienia tego problemu były w pewnym stopniu skuteczne.
|
||||
Skanowanie tej błędnej konfiguracji w różnych systemach ujawniło wiele przypadków, w których zmienne Nginx mogły być wyświetlane przez użytkownika. Jednak spadek liczby podatnych przypadków sugeruje, że wysiłki na rzecz naprawy tego problemu były w pewnym stopniu skuteczne.
|
||||
|
||||
### Używanie try_files z zmiennymi $URI$ARGS
|
||||
|
||||
Następująca błędna konfiguracja 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 jest używana do sprawdzania istnienia plików w określonej kolejności. Nginx dostarczy pierwszy, który znajdzie. Podstawowa składnia dyrektywy `try_files` jest następująca:
|
||||
```
|
||||
try_files file1 file2 ... fileN fallback;
|
||||
```
|
||||
Nginx sprawdzi istnienie każdego pliku w określonej kolejności. Jeśli plik istnieje, zostanie natychmiast udostępniony. 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, gdy używane są zmienne `$uri$args` w tej dyrektywie, Nginx spróbuje znaleźć plik, który pasuje do URI żądania połączonego z dowolnymi argumentami ciągu zapytania. Dlatego 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 ładunkiem:
|
||||
```
|
||||
GET /?../../../../../../../../etc/passwd HTTP/1.1
|
||||
Host: example.com
|
||||
```
|
||||
Używając naszego ładunku, wyjdziemy poza katalog główny (zdefiniowany w konfiguracji Nginx) i załadujemy plik `/etc/passwd`. W logach debugowania możemy zaobserwować, jak Nginx próbuje plików:
|
||||
```
|
||||
...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 przy użyciu powyższej konfiguracji:
|
||||

|
||||
|
||||
## 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.
|
||||
Nginx oferuje funkcję przez `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że, 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:
|
||||
```python
|
||||
@ -153,7 +203,7 @@ proxy_intercept_errors on;
|
||||
proxy_hide_header Secret-Header;
|
||||
}
|
||||
```
|
||||
- [**proxy_intercept_errors**](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors): Ta dyrektywa umożliwia Nginxowi serwowanie niestandardowej odpowiedzi dla odpowiedzi backendu z kodem statusu większym niż 300. Zapewnia to, że w naszym przykładzie aplikacji uWSGI odpowiedź `500 Error` jest przechwytywana i obsługiwana przez Nginx.
|
||||
- [**proxy_intercept_errors**](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors): Ta dyrektywa umożliwia Nginxowi serwowanie niestandardowej odpowiedzi dla odpowiedzi backendu z kodem statusu większym niż 300. Zapewnia to, że w przypadku naszej aplikacji uWSGI odpowiedź `500 Error` jest przechwytywana i obsługiwana przez Nginx.
|
||||
- [**proxy_hide_header**](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#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.
|
||||
@ -172,8 +222,8 @@ Jak pokazano w [**tym artykule**](https://mizu.re/post/cors-playground), istniej
|
||||
|
||||
- `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`: Ustala zestaw znaków dla odpowiedzi przy użyciu X-Accel-Redirect.
|
||||
- `X-Accel-Expires`: Ustala czas wygaśnięcia odpowiedzi przy użyciu X-Accel-Redirect.
|
||||
- `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).
|
||||
|
Loading…
x
Reference in New Issue
Block a user