PHP Tricks
Emplacement commun des cookies :
Ceci est également valable pour les cookies de phpMyAdmin.
Cookies:
Lieux :
Contournement des comparaisons PHP
Comparaisons lâches/Type Juggling ( == )
Si ==
est utilisé en PHP, il peut y avoir des cas inattendus où la comparaison ne se comporte pas comme prévu. Cela est dû au fait que "==" compare uniquement les valeurs transformées en le même type. Si vous souhaitez également comparer que le type des données comparées est le même, vous devez utiliser ===
.
Tableaux de comparaison PHP : https://www.php.net/manual/en/types.comparisons.php
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F2088318145-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Frq9WIQinJaxpWMvakjIQ%252Fuploads%252Fgit-blob-53dd523e3097738b14730e72b491c182672a1fc0%252Fimage%2520%2840%29%2520%281%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=441d805c&sv=1)
"string" == 0 -> True
Une chaîne qui ne commence pas par un nombre est égale à un nombre"0xAAAA" == "43690" -> True
Les chaînes composées de nombres au format décimal ou hexadécimal peuvent être comparées à d'autres nombres/chaînes avec True comme résultat si les nombres étaient les mêmes (les nombres dans une chaîne sont interprétés comme des nombres)"0e3264578" == 0 --> True
Une chaîne commençant par "0e" et suivie de n'importe quoi sera égale à 0"0X3264578" == 0X --> True
Une chaîne commençant par "0" et suivie de n'importe quelle lettre (X peut être n'importe quelle lettre) et suivie de n'importe quoi sera égale à 0"0e12334" == "0" --> True
C'est très intéressant car dans certains cas, vous pouvez contrôler l'entrée de chaîne de "0" et certains contenus qui sont hachés et comparés à cela. Par conséquent, si vous pouvez fournir une valeur qui créera un hachage commençant par "0e" et sans aucune lettre, vous pourriez contourner la comparaison. Vous pouvez trouver des chaînes déjà hachées avec ce format ici : https://github.com/spaze/hashes"X" == 0 --> True
Toute lettre dans une chaîne est égale à l'entier 0
Plus d'informations sur https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09
in_array()
Type Juggling affecte également la fonction in_array()
par défaut (vous devez définir sur true le troisième argument pour effectuer une comparaison stricte) :
strcmp()/strcasecmp()
Si cette fonction est utilisée pour toute vérification d'authentification (comme la vérification du mot de passe) et que l'utilisateur contrôle un côté de la comparaison, il peut envoyer un tableau vide au lieu d'une chaîne de caractères comme valeur du mot de passe (https://example.com/login.php/?username=admin&password[]=
) et contourner cette vérification:
Le même erreur se produit avec strcasecmp()
Conversion de type strict
Même si ===
est utilisé, il peut y avoir des erreurs qui rendent la comparaison vulnérable à la conversion de type. Par exemple, si la comparaison convertit les données en un type d'objet différent avant de les comparer:
preg_match(/^.*/)
preg_match()
pourrait être utilisé pour valider l'entrée de l'utilisateur (il vérifie si un mot/regex de la liste noire est présent dans l'entrée de l'utilisateur et si ce n'est pas le cas, le code peut continuer son exécution).
Contournement de saut de ligne
Cependant, en délimitant le début de l'expression régulière, preg_match()
ne vérifie que la première ligne de l'entrée de l'utilisateur, puis si d'une manière ou d'une autre vous pouvez envoyer l'entrée sur plusieurs lignes, vous pourriez contourner cette vérification. Exemple :
Pour contourner cette vérification, vous pourriez envoyer la valeur avec des sauts de ligne urlencodés (%0A
) ou si vous pouvez envoyer des données JSON, envoyez-les sur plusieurs lignes :
Trouvez un exemple ici : https://ramadistra.dev/fbctf-2019-rceservice
Contournement d'erreur de longueur
(Ce contournement a apparemment été testé sur PHP 5.2.5 et je n'ai pas réussi à le faire fonctionner sur PHP 7.3.15)
Si vous pouvez envoyer à preg_match()
une entrée très grande valide, il ne pourra pas la traiter et vous pourrez contourner la vérification. Par exemple, s'il met en liste noire un JSON, vous pourriez envoyer :
Contournement de ReDoS
Astuce de : https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F2088318145-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Frq9WIQinJaxpWMvakjIQ%252Fuploads%252Fgit-blob-746083bbabdbedd055c5dddac1d3ebcce0f1f726%252Fimage%2520%2810%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=f632a081&sv=1)
En bref, le problème se produit car les fonctions preg_*
en PHP s'appuient sur la bibliothèque PCRE. Dans PCRE, certaines expressions régulières sont appariées en utilisant beaucoup d'appels récursifs, ce qui utilise beaucoup d'espace de pile. Il est possible de définir une limite sur le nombre de récursions autorisées, mais en PHP cette limite est par défaut à 100 000 ce qui dépasse la taille de la pile.
Cette discussion sur Stackoverflow a également été liée dans l'article où il est discuté plus en profondeur de ce problème. Notre tâche était maintenant claire :
Envoyer une entrée qui ferait faire plus de 100 000 récursions à l'expression régulière, provoquant un SIGSEGV, faisant en sorte que la fonction preg_match()
renvoie false
, ce qui amène l'application à penser que notre entrée n'est pas malveillante, en lançant la surprise à la fin de la charge utile quelque chose comme {system(<verybadcommand>)}
pour obtenir SSTI --> RCE --> drapeau :).
Eh bien, en termes d'expressions régulières, nous ne faisons pas réellement 100k "récursions", mais nous comptons plutôt les "étapes de retour en arrière", comme le mentionne la documentation PHP qui indique que par défaut, cela correspond à 1 000 000 (1M) dans la variable pcre.backtrack_limit
.
Pour y parvenir, 'X'*500_001
donnera comme résultat 1 million d'étapes de retour en arrière (500k en avant et 500k en arrière) :
Type Juggling pour l'obscurcissement PHP
Exécution Après Redirection (EAR)
Si PHP redirige vers une autre page mais qu'aucune fonction die
ou exit
n'est appelée après que l'en-tête Location
soit défini, le PHP continue d'exécuter et d'ajouter des données au corps de la page :
Exploitation de la Traversal de Chemin et de l'Inclusion de Fichier
Vérifiez :
File Inclusion/Path traversalPlus de astuces
register_globals : Dans PHP < 4.1.1.1 ou s'il est mal configuré, register_globals peut être activé (ou leur comportement est imité). Cela implique que dans les variables globales comme $_GET s'ils ont une valeur par exemple $_GET["param"]="1234", vous pouvez y accéder via $param. Par conséquent, en envoyant des paramètres HTTP, vous pouvez écraser des variables qui sont utilisées dans le code.
Les cookies PHPSESSION du même domaine sont stockés au même endroit, donc si dans un domaine différents cookies sont utilisés dans différents chemins vous pouvez faire en sorte qu'un chemin accède au cookie du chemin en définissant la valeur du cookie de l'autre chemin. De cette manière, si les deux chemins accèdent à une variable portant le même nom vous pouvez faire en sorte que la valeur de cette variable dans le chemin 1 s'applique au chemin 2. Ensuite, le chemin 2 considérera comme valides les variables du chemin 1 (en donnant au cookie le nom qui lui correspond dans le chemin 2).
Lorsque vous avez les noms d'utilisateur des utilisateurs de la machine. Vérifiez l'adresse : /~<USERNAME> pour voir si les répertoires php sont activés.
password_hash/password_verify
Ces fonctions sont généralement utilisées en PHP pour générer des hachages à partir de mots de passe et pour vérifier si un mot de passe est correct par rapport à un hachage.
Les algorithmes pris en charge sont : PASSWORD_DEFAULT
et PASSWORD_BCRYPT
(commence par $2y$
). Notez que PASSWORD_DEFAULT est fréquemment identique à PASSWORD_BCRYPT. Et actuellement, PASSWORD_BCRYPT a une limite de taille en entrée de 72 octets. Par conséquent, lorsque vous essayez de hacher quelque chose de plus grand que 72 octets avec cet algorithme, seuls les 72 premiers octets seront utilisés :
Contournement des en-têtes HTTP en abusant des erreurs PHP
Si une page PHP imprime des erreurs et renvoie certaines entrées fournies par l'utilisateur, l'utilisateur peut faire en sorte que le serveur PHP renvoie un contenu suffisamment long pour que lorsqu'il essaie d'ajouter les en-têtes dans la réponse, le serveur génère une erreur. Dans le scénario suivant, l'attaquant a provoqué des erreurs importantes sur le serveur, et comme vous pouvez le voir à l'écran, lorsque PHP a tenté de modifier les informations d'en-tête, il n'a pas pu (par exemple, l'en-tête CSP n'a pas été envoyé à l'utilisateur) :
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F2088318145-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Frq9WIQinJaxpWMvakjIQ%252Fuploads%252Fgit-blob-14119d0754739cfdb01a8cdd752ea4a282899451%252Fimage%2520%28465%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=121d869f&sv=1)
Exécution de code
system("ls"); `ls`; shell_exec("ls");
Vérifiez ceci pour plus de fonctions PHP utiles
RCE via preg_replace()
Pour exécuter le code dans l'argument "replace", il est nécessaire d'avoir au moins une correspondance. Cette option de preg_replace a été dépréciée à partir de PHP 5.5.0.
RCE via Eval()
RCE via Assert()
Cette fonction en php vous permet d'exécuter du code qui est écrit dans une chaîne de caractères afin de retourner vrai ou faux (et en fonction de cela modifier l'exécution). Habituellement, la variable utilisateur sera insérée au milieu d'une chaîne de caractères. Par exemple :
assert("strpos($_GET['page']),'..') === false")
--> Dans ce cas, pour obtenir RCE, vous pourriez faire :
Vous devrez casser la syntaxe du code, ajouter votre charge utile, puis la réparer. Vous pouvez utiliser des opérations logiques telles que "and" ou "%26%26" ou "|". Notez que "or", "||" ne fonctionne pas car si la première condition est vraie, notre charge utile ne sera pas exécutée. De la même manière, ";" ne fonctionne pas car notre charge utile ne sera pas exécutée.
Une autre option est d'ajouter à la chaîne l'exécution de la commande : '.highlight_file('.passwd').'
Autre option (si vous avez le code interne) est de modifier une variable pour altérer l'exécution : $file = "hola"
RCE via usort()
Cette fonction est utilisée pour trier un tableau d'éléments en utilisant une fonction spécifique. Pour abuser de cette fonction :
RCE via .httaccess
Si vous pouvez uploader un .htaccess, alors vous pouvez configurer plusieurs choses et même exécuter du code (en configurant que les fichiers avec l'extension .htaccess peuvent être exécutés).
Différentes coquilles .htaccess peuvent être trouvées ici
RCE via Variables d'Environnement
Si vous trouvez une vulnérabilité qui vous permet de modifier les variables d'environnement en PHP (et une autre pour uploader des fichiers, bien qu'avec plus de recherche cela puisse être contourné), vous pourriez abuser de ce comportement pour obtenir RCE.
LD_PRELOAD
: Cette variable d'environnement vous permet de charger des bibliothèques arbitraires lors de l'exécution d'autres binaires (bien que dans ce cas cela pourrait ne pas fonctionner).PHPRC
: Indique à PHP où localiser son fichier de configuration, généralement appeléphp.ini
. Si vous pouvez uploader votre propre fichier de configuration, alors utilisezPHPRC
pour le pointer vers PHP. Ajoutez une entréeauto_prepend_file
spécifiant un deuxième fichier uploadé. Ce deuxième fichier contient du code PHP normal, qui est ensuite exécuté par le moteur PHP avant tout autre code.
Uploadez un fichier PHP contenant notre code de coquille
Uploadez un deuxième fichier, contenant une directive
auto_prepend_file
indiquant au préprocesseur PHP d'exécuter le fichier que nous avons uploadé à l'étape 1Définissez la variable
PHPRC
sur le fichier que nous avons uploadé à l'étape 2.
Obtenez plus d'informations sur la façon d'exécuter cette chaîne à partir du rapport original.
PHPRC - une autre option
Si vous ne pouvez pas uploader de fichiers, vous pourriez utiliser dans FreeBSD le "fichier"
/dev/fd/0
qui contient lestdin
, étant le corps de la requête envoyée austdin
:curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'
Ou pour obtenir RCE, activez
allow_url_include
et préfixez un fichier avec du code PHP en base64:curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'
Technique de ce rapport.
PHP Analyse Statique
Vérifiez si vous pouvez insérer du code dans les appels à ces fonctions (de ici):
Si vous déboguez une application PHP, vous pouvez activer l'affichage des erreurs globalement dans /etc/php5/apache2/php.ini
en ajoutant display_errors = On
et redémarrer Apache : sudo systemctl restart apache2
Déobfuscation de code PHP
Vous pouvez utiliser le site web www.unphp.net pour déobfusquer du code PHP.
Enveloppes et protocoles PHP
Les enveloppes et protocoles PHP pourraient vous permettre de contourner les protections en écriture et en lecture dans un système et le compromettre. Pour plus d'informations, consultez cette page.
RCE non authentifié Xdebug
Si vous constatez que Xdebug est activé dans la sortie de phpconfig()
, vous devriez essayer d'obtenir une RCE via https://github.com/nqxcode/xdebug-exploit
Variables variables
RCE abusant de new $_GET["a"]($_GET["b"])
Si dans une page vous pouvez créer un nouvel objet d'une classe arbitraire, vous pourriez être en mesure d'obtenir une RCE, consultez la page suivante pour apprendre comment :
PHP - RCE abusing object creation: new $_GET["a"]($_GET["b"])Exécuter du PHP sans lettres
https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/
Utilisation d'octal
XOR
Code shell XOR simple
Selon cette explication, il est possible de générer un code shell simple de cette manière :
Donc, si vous pouvez exécuter du PHP arbitraire sans chiffres et lettres, vous pouvez envoyer une requête comme celle-ci en abusant de cette charge utile pour exécuter du PHP arbitraire :
Pour une explication plus approfondie, consultez https://ctf-wiki.org/web/php/php/#preg_match
Code shell XOR (à l'intérieur de eval)
Perl like
Comme Perl
Last updated