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
1cde5dbcb0
commit
eadede6b2e
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 |
@ -3,7 +3,7 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## Відсутня коренева локація <a href="#missing-root-location" id="missing-root-location"></a>
|
||||
## Відсутнє кореневе місцезнаходження <a href="#missing-root-location" id="missing-root-location"></a>
|
||||
|
||||
При налаштуванні сервера Nginx, **директива root** відіграє критичну роль, визначаючи базовий каталог, з якого подаються файли. Розгляньте наведену нижче приклад:
|
||||
```bash
|
||||
@ -16,13 +16,13 @@ proxy_pass http://127.0.0.1:8080/;
|
||||
}
|
||||
}
|
||||
```
|
||||
У цій конфігурації `/etc/nginx` призначено як кореневий каталог. Ця налаштування дозволяє доступ до файлів у вказаному кореневому каталозі, таких як `/hello.txt`. Однак важливо зазначити, що визначено лише конкретне місце (`/hello.txt`). Немає конфігурації для кореневого місця (`location / {...}`). Це упущення означає, що директива root застосовується глобально, що дозволяє запитам до кореневого шляху `/` отримувати доступ до файлів під `/etc/nginx`.
|
||||
У цій конфігурації `/etc/nginx` призначено як кореневий каталог. Ця налаштування дозволяє доступ до файлів у вказаному кореневому каталозі, таких як `/hello.txt`. Однак важливо зазначити, що визначено лише конкретне місце (`/hello.txt`). Немає конфігурації для кореневого місця (`location / {...}`). Це упущення означає, що директива root застосовується глобально, дозволяючи запитам до кореневого шляху `/` отримувати доступ до файлів під `/etc/nginx`.
|
||||
|
||||
Критичне питання безпеки виникає з цієї конфігурації. Простий запит `GET`, наприклад `GET /nginx.conf`, може розкрити чутливу інформацію, надаючи доступ до файлу конфігурації Nginx, розташованого за адресою `/etc/nginx/nginx.conf`. Встановлення кореня на менш чутливий каталог, наприклад `/etc`, може зменшити цей ризик, але все ще може дозволити ненавмисний доступ до інших критичних файлів, включаючи інші файли конфігурації, журнали доступу та навіть зашифровані облікові дані, що використовуються для базової аутентифікації HTTP.
|
||||
Критичне питання безпеки виникає з цієї конфігурації. Простий запит `GET`, наприклад `GET /nginx.conf`, може розкрити чутливу інформацію, надаючи файл конфігурації Nginx, розташований за адресою `/etc/nginx/nginx.conf`. Встановлення кореня на менш чутливий каталог, наприклад `/etc`, може зменшити цей ризик, але все ще може дозволити ненавмисний доступ до інших критичних файлів, включаючи інші файли конфігурації, журнали доступу та навіть зашифровані облікові дані, що використовуються для базової аутентифікації HTTP.
|
||||
|
||||
## Alias LFI Misconfiguration <a href="#alias-lfi-misconfiguration" id="alias-lfi-misconfiguration"></a>
|
||||
|
||||
У конфігураційних файлах Nginx необхідно ретельно перевірити директиви "location". Уразливість, відома як Local File Inclusion (LFI), може бути ненавмисно введена через конфігурацію, яка нагадує наступну:
|
||||
У конфігураційних файлах Nginx необхідно уважно перевірити директиви "location". Уразливість, відома як Local File Inclusion (LFI), може бути ненавмисно введена через конфігурацію, яка нагадує наступну:
|
||||
```
|
||||
location /imgs {
|
||||
alias /path/images/;
|
||||
@ -67,7 +67,7 @@ deny all;
|
||||
> [!CAUTION]
|
||||
> Уразливі змінні `$uri` та `$document_uri`, і це можна виправити, замінивши їх на `$request_uri`.
|
||||
>
|
||||
> Регулярний вираз також може бути уразливим, наприклад:
|
||||
> Регулярний вираз також може бути уразливим, як:
|
||||
>
|
||||
> `location ~ /docs/([^/])? { … $1 … }` - Уразливий
|
||||
>
|
||||
@ -81,7 +81,7 @@ location / {
|
||||
return 302 https://example.com$uri;
|
||||
}
|
||||
```
|
||||
Символи \r (Carriage Return) та \n (Line Feed) позначають символи нового рядка в HTTP-запитах, а їх URL-кодовані форми представлені як `%0d%0a`. Включення цих символів у запит (наприклад, `http://localhost/%0d%0aDetectify:%20clrf`) до неправильно налаштованого сервера призводить до того, що сервер видає новий заголовок з назвою `Detectify`. Це відбувається тому, що змінна $uri декодує URL-кодовані символи нового рядка, що призводить до несподіваного заголовка у відповіді:
|
||||
Символи \r (Carriage Return) та \n (Line Feed) позначають символи нового рядка в HTTP запитах, а їх URL-кодовані форми представлені як `%0d%0a`. Включення цих символів у запит (наприклад, `http://localhost/%0d%0aDetectify:%20clrf`) до неправильно налаштованого сервера призводить до того, що сервер видає новий заголовок з назвою `Detectify`. Це відбувається тому, що змінна $uri декодує URL-кодовані символи нового рядка, що призводить до несподіваного заголовка у відповіді:
|
||||
```
|
||||
HTTP/1.1 302 Moved Temporarily
|
||||
Server: nginx/1.19.3
|
||||
@ -91,9 +91,9 @@ Connection: keep-alive
|
||||
Location: https://example.com/
|
||||
Detectify: clrf
|
||||
```
|
||||
Дізнайтеся більше про ризики CRLF-ін'єкцій та розділення відповідей на [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/).
|
||||
Дізнайтеся більше про ризики CRLF-ін'єкції та розділення відповідей на [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/).
|
||||
|
||||
Цю техніку також [**пояснено в цій доповіді**](https://www.youtube.com/watch?v=gWQyWdZbdoY&list=PL0xCSYnG_iTtJe2V6PQqamBF73n7-f1Nr&index=77) з деякими вразливими прикладами та механізмами виявлення. Наприклад, щоб виявити цю неправильну конфігурацію з точки зору чорного ящика, ви можете використовувати ці запити:
|
||||
Ця техніка також [**пояснена в цій доповіді**](https://www.youtube.com/watch?v=gWQyWdZbdoY&list=PL0xCSYnG_iTtJe2V6PQqamBF73n7-f1Nr&index=77) з деякими вразливими прикладами та механізмами виявлення. Наприклад, щоб виявити цю неправильну конфігурацію з точки зору чорного ящика, ви можете використовувати ці запити:
|
||||
|
||||
- `https://example.com/%20X` - Будь-який HTTP код
|
||||
- `https://example.com/%20H` - 400 Bad Request
|
||||
@ -105,7 +105,7 @@ Detectify: clrf
|
||||
- `http://company.tld/%20HTTP/1.1%0D%0AXXXX:%20x` - Будь-який HTTP код
|
||||
- `http://company.tld/%20HTTP/1.1%0D%0AHost:%20x` - 400 Bad Request
|
||||
|
||||
Деякі вразливі конфігурації, виявлені в цій доповіді, були:
|
||||
Деякі виявлені вразливі конфігурації, представлені в цій доповіді, були:
|
||||
|
||||
- Зверніть увагу, як **`$uri`** встановлено як є в кінцевому URL
|
||||
```
|
||||
@ -135,9 +135,59 @@ $ curl -H ‘Referer: bar’ http://localhost/foo$http_referer | grep ‘foobar
|
||||
```
|
||||
Сканування на наявність цієї неконфігурації в системах виявило кілька випадків, коли змінні Nginx могли бути виведені користувачем. Однак зменшення кількості вразливих випадків свідчить про те, що зусилля щодо виправлення цієї проблеми були дещо успішними.
|
||||
|
||||
## Читання сирцевої відповіді бекенду
|
||||
### Використання try_files з змінними $URI$ARGS
|
||||
|
||||
Nginx пропонує функцію через `proxy_pass`, яка дозволяє перехоплювати помилки та HTTP-заголовки, що генеруються бекендом, з метою приховування внутрішніх повідомлень про помилки та заголовків. Це досягається шляхом надання Nginx користувацьких сторінок помилок у відповідь на помилки бекенду. Однак виникають труднощі, коли Nginx стикається з недійсним HTTP-запитом. Такий запит пересилається до бекенду в отриманому вигляді, а сирцева відповідь бекенду потім безпосередньо надсилається клієнту без втручання Nginx.
|
||||
Наступна неконфігурація Nginx може призвести до вразливості LFI:
|
||||
```
|
||||
location / {
|
||||
try_files $uri$args $uri$args/ /index.html;
|
||||
}
|
||||
```
|
||||
У нашій конфігурації є директива `try_files`, яка використовується для перевірки наявності файлів у вказаному порядку. Nginx надасть перший, який він знайде. Основний синтаксис директиви `try_files` виглядає наступним чином:
|
||||
```
|
||||
try_files file1 file2 ... fileN fallback;
|
||||
```
|
||||
Nginx перевірить наявність кожного файлу в зазначеному порядку. Якщо файл існує, він буде негайно наданий. Якщо жоден з вказаних файлів не існує, запит буде передано до резервного варіанту, яким може бути інший URI або конкретна сторінка помилки.
|
||||
|
||||
Однак, коли використовуються змінні `$uri$args` в цій директиві, Nginx спробує знайти файл, який відповідає URI запиту в поєднанні з будь-якими аргументами рядка запиту. Тому ми можемо експлуатувати цю конфігурацію:
|
||||
```
|
||||
http {
|
||||
server {
|
||||
root /var/www/html/public;
|
||||
|
||||
location / {
|
||||
try_files $uri$args $uri$args/ /index.html;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
З наступним payload:
|
||||
```
|
||||
GET /?../../../../../../../../etc/passwd HTTP/1.1
|
||||
Host: example.com
|
||||
```
|
||||
Використовуючи наш payload, ми вийдемо за межі кореневої директорії (визначеної в конфігурації Nginx) і завантажимо файл `/etc/passwd`. У журналах налагодження ми можемо спостерігати, як Nginx намагається отримати доступ до файлів:
|
||||
```
|
||||
...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 проти Nginx, використовуючи вказану вище конфігурацію:
|
||||

|
||||
|
||||
## Читання сирцевої відповіді з бекенду
|
||||
|
||||
Nginx пропонує функцію через `proxy_pass`, яка дозволяє перехоплювати помилки та HTTP заголовки, що генеруються бекендом, з метою приховування внутрішніх повідомлень про помилки та заголовків. Це досягається шляхом того, що Nginx обслуговує користувацькі сторінки помилок у відповідь на помилки бекенду. Однак виникають труднощі, коли Nginx стикається з недійсним HTTP запитом. Такий запит пересилається до бекенду в отриманому вигляді, а сирцева відповідь бекенду безпосередньо надсилається клієнту без втручання Nginx.
|
||||
|
||||
Розгляньте приклад сценарію, що стосується програми uWSGI:
|
||||
```python
|
||||
@ -145,7 +195,7 @@ 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!"]
|
||||
```
|
||||
Щоб керувати цим, у конфігурації Nginx використовуються специфічні директиви:
|
||||
Для управління цим використовуються специфічні директиви в конфігурації Nginx:
|
||||
```
|
||||
http {
|
||||
error_page 500 /html/error.html;
|
||||
@ -153,16 +203,16 @@ 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): Ця директива дозволяє Nginx надавати користувацьку відповідь для відповідей з бекенду зі статус-кодом більшим за 300. Це забезпечує, що для нашого прикладу програми uWSGI відповідь `500 Error` перехоплюється і обробляється Nginx.
|
||||
- [**proxy_intercept_errors**](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors): Ця директива дозволяє Nginx надавати користувацьку відповідь для відповідей бекенду з кодом статусу більше 300. Це забезпечує, що для нашого прикладу програми uWSGI відповідь `500 Error` перехоплюється і обробляється Nginx.
|
||||
- [**proxy_hide_header**](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_hide_header): Як випливає з назви, ця директива приховує вказані HTTP заголовки від клієнта, підвищуючи конфіденційність і безпеку.
|
||||
|
||||
Коли надсилається дійсний запит `GET`, Nginx обробляє його звичайним чином, повертаючи стандартну відповідь про помилку без розкриття будь-яких секретних заголовків. Однак недійсний HTTP запит обходить цей механізм, що призводить до розкриття сирих відповідей з бекенду, включаючи секретні заголовки та повідомлення про помилки.
|
||||
Коли надсилається дійсний `GET` запит, Nginx обробляє його звичайним чином, повертаючи стандартну відповідь про помилку без розкриття будь-яких секретних заголовків. Однак недійсний HTTP запит обходить цей механізм, що призводить до розкриття сирих відповідей бекенду, включаючи секретні заголовки та повідомлення про помилки.
|
||||
|
||||
## merge_slashes встановлено на off
|
||||
|
||||
За замовчуванням директива Nginx **`merge_slashes`** встановлена на **`on`**, що стискає кілька прямолінійних слешів у URL в один слеш. Ця функція, хоча і спрощує обробку URL, може ненавмисно приховувати вразливості в програмах за Nginx, особливо ті, що піддаються атакам локального включення файлів (LFI). Експерти з безпеки **Денні Робінсон і Ротем Бар** підкреслили потенційні ризики, пов'язані з цією поведінкою за замовчуванням, особливо коли Nginx діє як реверс-проксі.
|
||||
За замовчуванням директива Nginx **`merge_slashes`** встановлена на **`on`**, що стискає кілька прямолінійних слешів у URL в один слеш. Ця функція, хоча і спрощує обробку URL, може ненавмисно приховувати вразливості в програмах за Nginx, особливо ті, що схильні до атак локального включення файлів (LFI). Експерти з безпеки **Денні Робінсон і Ротем Бар** підкреслили потенційні ризики, пов'язані з цією поведінкою за замовчуванням, особливо коли Nginx діє як реверс-проксі.
|
||||
|
||||
Щоб зменшити такі ризики, рекомендується **вимкнути директиву `merge_slashes`** для програм, які піддаються цим вразливостям. Це забезпечить, що Nginx пересилає запити до програми без зміни структури URL, тим самим не маскуючи жодних основних проблем безпеки.
|
||||
Щоб зменшити такі ризики, рекомендується **вимкнути директиву `merge_slashes`** для програм, схильних до цих вразливостей. Це забезпечить, що Nginx пересилає запити до програми без зміни структури URL, тим самим не маскуючи жодних основних проблем безпеки.
|
||||
|
||||
Для отримання додаткової інформації перегляньте [Денні Робінсон і Ротем Бар](https://medium.com/appsflyer/nginx-may-be-protecting-your-applications-from-traversal-attacks-without-you-even-knowing-b08f882fd43d).
|
||||
|
||||
@ -173,14 +223,14 @@ proxy_hide_header Secret-Header;
|
||||
- `X-Accel-Redirect`: Вказує Nginx на внутрішнє перенаправлення запиту на вказане місце.
|
||||
- `X-Accel-Buffering`: Контролює, чи повинен Nginx буферизувати відповідь.
|
||||
- `X-Accel-Charset`: Встановлює набір символів для відповіді при використанні X-Accel-Redirect.
|
||||
- `X-Accel-Expires`: Встановлює час закінчення для відповіді при використанні X-Accel-Redirect.
|
||||
- `X-Accel-Expires`: Встановлює час закінчення терміну дії для відповіді при використанні X-Accel-Redirect.
|
||||
- `X-Accel-Limit-Rate`: Обмежує швидкість передачі для відповідей при використанні X-Accel-Redirect.
|
||||
|
||||
Наприклад, заголовок **`X-Accel-Redirect`** викличе внутрішнє **перенаправлення** в nginx. Тож наявність конфігурації nginx з чимось на кшталт **`root /`** і відповіді від веб-сервера з **`X-Accel-Redirect: .env`** змусить nginx надіслати вміст **`/.env`** (Path Traversal).
|
||||
|
||||
### **Значення за замовчуванням у директиві Map**
|
||||
### **Default Value in Map Directive**
|
||||
|
||||
У **конфігурації Nginx** директива `map` часто відіграє роль у **контролі авторизації**. Загальною помилкою є невказування **значення за замовчуванням**, що може призвести до несанкціонованого доступу. Наприклад:
|
||||
У **конфігурації Nginx** директива `map` часто відіграє роль у **контролі авторизації**. Загальною помилкою є невказання **значення за замовчуванням**, що може призвести до несанкціонованого доступу. Наприклад:
|
||||
```yaml
|
||||
http {
|
||||
map $uri $mappocallow {
|
||||
@ -199,9 +249,9 @@ return 200 "Hello. It is private area: $mappocallow";
|
||||
}
|
||||
}
|
||||
```
|
||||
Без `default` **зловмисний користувач** може обійти безпеку, отримавши доступ до **невизначеного URI** в `/map-poc`. [Посібник Nginx](https://nginx.org/en/docs/http/ngx_http_map_module.html) радить встановити **значення за замовчуванням**, щоб уникнути таких проблем.
|
||||
Без `default` **зловмисний користувач** може обійти безпеку, отримавши доступ до **недефінованого URI** в `/map-poc`. [Посібник Nginx](https://nginx.org/en/docs/http/ngx_http_map_module.html) радить встановити **значення за замовчуванням**, щоб уникнути таких проблем.
|
||||
|
||||
### **Вразливість до DNS-спуфінгу**
|
||||
### **Уразливість до DNS-спуфінгу**
|
||||
|
||||
DNS-спуфінг проти Nginx можливий за певних умов. Якщо зловмисник знає **DNS-сервер**, який використовує Nginx, і може перехопити його DNS-запити, він може підробити DNS-записи. Однак цей метод є неефективним, якщо Nginx налаштований на використання **localhost (127.0.0.1)** для розв'язання DNS. Nginx дозволяє вказувати DNS-сервер наступним чином:
|
||||
```yaml
|
||||
@ -209,11 +259,11 @@ resolver 8.8.8.8;
|
||||
```
|
||||
### **`proxy_pass` та `internal` директиви**
|
||||
|
||||
Директива **`proxy_pass`** використовується для перенаправлення запитів на інші сервери, як внутрішні, так і зовнішні. Директива **`internal`** забезпечує доступ до певних місць лише всередині Nginx. Хоча ці директиви самі по собі не є вразливостями, їх конфігурація вимагає ретельного аналізу, щоб запобігти безпековим прогалинам.
|
||||
Директива **`proxy_pass`** використовується для перенаправлення запитів на інші сервери, як внутрішні, так і зовнішні. Директива **`internal`** забезпечує, що певні місця доступні лише всередині Nginx. Хоча ці директиви самі по собі не є вразливостями, їх конфігурація вимагає ретельного аналізу, щоб запобігти безпековим прогалинам.
|
||||
|
||||
## proxy_set_header Upgrade & Connection
|
||||
|
||||
Якщо сервер nginx налаштований на передачу заголовків Upgrade та Connection, може бути виконана [**атака h2c Smuggling**](../../pentesting-web/h2c-smuggling.md) для доступу до захищених/внутрішніх кінцевих точок.
|
||||
Якщо сервер nginx налаштований на передачу заголовків Upgrade та Connection, може бути виконано [**атака h2c Smuggling**](../../pentesting-web/h2c-smuggling.md) для доступу до захищених/внутрішніх кінцевих точок.
|
||||
|
||||
> [!CAUTION]
|
||||
> Ця вразливість дозволила б зловмиснику **встановити пряме з'єднання з кінцевою точкою `proxy_pass`** (`http://backend:9999` у цьому випадку), вміст якої не буде перевірятися nginx.
|
||||
|
Loading…
x
Reference in New Issue
Block a user