Translated ['src/network-services-pentesting/pentesting-web/nginx.md'] t

This commit is contained in:
Translator 2025-07-12 09:40:00 +00:00
parent ee2beef5fd
commit 32fecc4ada
2 changed files with 62 additions and 12 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

View File

@ -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:
![Example burp request](../../images/nginx_try_files.png)
## 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).