{"id":5617,"date":"2023-01-12T11:57:39","date_gmt":"2023-01-12T10:57:39","guid":{"rendered":"https:\/\/www.vaadata.com\/blog\/?p=5617"},"modified":"2023-01-16T15:55:59","modified_gmt":"2023-01-16T14:55:59","slug":"deserialisation-vulnerabilites-exploitations-et-bonnes-pratiques-securite","status":"publish","type":"post","link":"https:\/\/www.vaadata.com\/blog\/fr\/deserialisation-vulnerabilites-exploitations-et-bonnes-pratiques-securite\/","title":{"rendered":"D\u00e9s\u00e9rialisation : vuln\u00e9rabilit\u00e9s, exploitations et bonnes pratiques s\u00e9curit\u00e9"},"content":{"rendered":"<div class=\"wp-block-image\">\n<figure class=\"alignright size-medium\"><img decoding=\"async\" width=\"300\" height=\"157\" src=\"https:\/\/www.vaadata.com\/blog\/wp-content\/uploads\/2023\/01\/Deserialisation_vulnerabilites_exploitation-300x157.png\" alt=\"Deserialisation_vulnerabilites_exploitation\" class=\"wp-image-5660\" srcset=\"https:\/\/www.vaadata.com\/blog\/wp-content\/uploads\/2023\/01\/Deserialisation_vulnerabilites_exploitation-300x157.png 300w, https:\/\/www.vaadata.com\/blog\/wp-content\/uploads\/2023\/01\/Deserialisation_vulnerabilites_exploitation-1024x535.png 1024w, https:\/\/www.vaadata.com\/blog\/wp-content\/uploads\/2023\/01\/Deserialisation_vulnerabilites_exploitation.png 1200w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/figure>\n<\/div>\n\n\n<p>Lorsqu&rsquo;on d\u00e9veloppe un jeu, on peut avoir besoin de sauvegarder la partie d&rsquo;un joueur dans un fichier pour ne pas perdre sa progression afin qu\u2019il puisse revenir l\u00e0 o\u00f9 il en \u00e9tait. De la m\u00eame mani\u00e8re, quand on d\u00e9veloppe un \u00e9diteur de texte en ligne, on peut vouloir pr\u00e9server le contenu que l&rsquo;utilisateur a \u00e9crit.<\/p>\n\n\n\n<p>En effet, il y a beaucoup de cas o\u00f9 l&rsquo;on souhaite sauvegarder l&rsquo;\u00e9tat de notre application pour le r\u00e9tablir dans le futur. Deux termes sont utilis\u00e9s pour d\u00e9finir ce processus : <strong>la s\u00e9rialisation et la d\u00e9s\u00e9rialisation<\/strong>.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Qu&rsquo;est-ce la d\u00e9s\u00e9rialisation (et la s\u00e9rialisation) ? <\/h2>\n\n\n\n<p>La s\u00e9rialisation est le processus qui consiste \u00e0 convertir l&rsquo;\u00e9tat d&rsquo;une application dans un format appropri\u00e9 pour un transfert ou du stockage. La d\u00e9s\u00e9rialisation est le processus inverse qui permet donc de restituer l&rsquo;\u00e9tat de l&rsquo;application. <\/p>\n\n\n\n<p>Par ailleurs, il se peut que l&rsquo;on souhaite s\u00e9rialiser des donn\u00e9es sp\u00e9cifiques comme des instances de classes par exemple. Il faut alors que le format dans lequel on s\u00e9rialise la donn\u00e9e le supporte. Cela se fait en sp\u00e9cifiant par exemple le nom de la classe en question \u00e0 c\u00f4t\u00e9 des donn\u00e9es. Cependant, une question peut se poser : qu&rsquo;est-ce qui arriverait lors de la d\u00e9s\u00e9rialisation si l&rsquo;utilisateur met un autre nom de classe que celui attendu ?<\/p>\n\n\n\n<p>Les classes peuvent avoir des m\u00e9thodes qui seront appel\u00e9es lors de leur d\u00e9s\u00e9rialisation, de la lecture ou \u00e9criture de leurs membres ou encore \u00e0 leur destruction. Par exemple, une classe pourrait mettre dans une liste tous les fichiers temporaires qu&rsquo;elle a cr\u00e9\u00e9 pour les supprimer quand elle sera d\u00e9truite. C&rsquo;est le cas par exemple de cette classe <a href=\"https:\/\/github.com\/mk-j\/PHP_XLSXWriter\/blob\/4da41e4f5df8333d17028aabf2a74e7ea71a1116\/xlsxwriter.class.php#L47-L54\" target=\"_blank\" rel=\"noopener\" title=\"\">XLSXWriter<\/a> en PHP.<\/p>\n\n\n\n<p>De fait, si un utilisateur est capable de contr\u00f4ler ce que le serveur d\u00e9s\u00e9rialisera, alors il pourrait utiliser des classes dangereuses pour s&rsquo;octroyer des droits, supprimer des fichiers ou encore <a href=\"https:\/\/www.vaadata.com\/blog\/fr\/vulnerabilite-rce-dans-un-nom-de-fichier\/\" target=\"_blank\" rel=\"noopener\" title=\"\">ex\u00e9cuter du code arbitraire<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">D\u00e9s\u00e9rialisation en PHP&nbsp;: fonctionnement et exploitations possibles<\/h2>\n\n\n\n<p>En PHP, la fonction <a href=\"https:\/\/www.php.net\/manual\/fr\/function.serialize.php\" target=\"_blank\" rel=\"noopener\" title=\"\">serialize<\/a> est utilis\u00e9e pour s\u00e9rialiser une structure de donn\u00e9es et son type. La fonction <a href=\"https:\/\/www.php.net\/manual\/fr\/function.unserialize\" target=\"_blank\" rel=\"noopener\" title=\"\">unserialize<\/a> permet de revenir en arri\u00e8re.<\/p>\n\n\n\n<p>Suite \u00e0 la s\u00e9rialisation des donn\u00e9es, elles sont repr\u00e9sent\u00e9es diff\u00e9remment en fonction de leur type.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Pour une cha\u00eene de caract\u00e8re <code>s:13:\"Hello, world!\";<\/code>, le nombre correspond \u00e0 sa longueur.<\/li><li>Pour un nombre entier, <code>i:42;<\/code>.<\/li><li>Pour un bool\u00e9en, <code>b:0; ou b:1;<\/code>.<\/li><li>Pour la valeur <code>null, N;<\/code>.<\/li><li>Pour une liste <code>a:1:{s:5:\"hello\";s:5:\"world\";}<\/code>, le premier nombre correspond au nombre d&rsquo;entr\u00e9es de la liste et, entre les accolades, une suite de cl\u00e9s\/valeurs.<\/li><li>Pour un objet <code>O:5:\"Hello\":1:{s:7:\"to_whom\";s:5:\"World\";}<\/code>, le premier nombre correspond \u00e0 la longueur du nom de la classe et, la suite c\u2019est la m\u00eame chose que pour une liste.<\/li><\/ul>\n\n\n\n<p>Un attaquant sera s\u00fbrement int\u00e9ress\u00e9 par la repr\u00e9sentation d&rsquo;un objet car il pourra contr\u00f4ler le nom de la classe et ainsi construire ce qu&rsquo;il souhaite. Prenons le code ci-dessous par exemple.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php\nclass TemporaryStorage {\n\tpublic $files = array();\n\n\tfunction __destruct() {\n\t\tforeach ($this-&gt;files as $temp_file) {\n\t\t\techo \"Deleting $temp_file...\\n\";\n\t\t\t@unlink($temp_file);\n\t\t}\n\t}\n};\n\nunserialize($_GET&#91;\"user_data\"]);\n\n<\/code><\/pre>\n\n\n\n<p>Si cette classe existe dans le code, alors un attaquant pourrait abuser de la d\u00e9construction de <code>TemporaryStorage<\/code> pour supprimer arbitrairement des fichiers sur le syst\u00e8me. Pour ce faire, il devra forger un objet ayant comme nom de classe <code>TemporaryStorage<\/code> avec un champ <code>files<\/code> et comme valeur une liste contenant les noms des fichiers \u00e0 supprimer. Puis de passer tout \u00e7a \u00e0 la fonction <code>unserialize<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nO:16:\"TemporaryStorage\":1:{s:5:\"files\";a:2:{i:0;s:20:\"\/app\/application.php\";i:1;s:16:\"\/data\/datbase.db\";}}\n\n<\/code><\/pre>\n\n\n\n<p>Si on transmet la cha\u00eene de caract\u00e8res ci-dessus, alors nous obtiendrons la r\u00e9ponse suivante du serveur.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nDeleting \/app\/application.php...\nDeleting \/data\/datbase.db...\n<\/code><\/pre>\n\n\n\n<p>Des classes faites maison qui permettraient \u00e0 un attaquant d&rsquo;augmenter l&rsquo;impact peuvent n\u00e9cessiter l&rsquo;acc\u00e8s au code source pour \u00eatre d\u00e9couvertes. Cependant, certaines biblioth\u00e8ques contenant des classes vuln\u00e9rables peuvent \u00eatre utilis\u00e9es, ce qui augmente les possibilit\u00e9s pour un attaquant. Sur ce point, le projet <a href=\"https:\/\/github.com\/ambionics\/phpggc\" target=\"_blank\" rel=\"noopener\" title=\"\">phpggc<\/a> regroupe une liste de classes pouvant \u00eatre exploit\u00e9es dans des biblioth\u00e8ques et Framework souvent utilis\u00e9s.<\/p>\n\n\n\n<p>Si une autre vuln\u00e9rabilit\u00e9 est pr\u00e9sente sur votre application qui permet d&rsquo;\u00e9diter arbitrairement des sessions PHP, alors un attaquant pourrait l&rsquo;utiliser pour faire de la d\u00e9s\u00e9rialisation dangereuse car les sessions ne sont rien d&rsquo;autre que des objets s\u00e9rialis\u00e9s.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">D\u00e9s\u00e9rialisation en C# avec Json.NET : fonctionnement et exploitations possibles<\/h2>\n\n\n\n<p>La biblioth\u00e8que <a href=\"https:\/\/www.newtonsoft.com\/json\" target=\"_blank\" rel=\"noopener\" title=\"\">Json.NET<\/a> permet de s\u00e9rialiser et d\u00e9s\u00e9rialiser des donn\u00e9es dans un format consid\u00e9r\u00e9 comme s\u00fbr, car simple : le JSON. Malheureusement, lors de la d\u00e9s\u00e9rialisation, la biblioth\u00e8que utilisera le champ <code>$type<\/code> dans un objet pour savoir quelle classe instancier. Si l&rsquo;option <code>TypeNameHandling.Objects<\/code> est utilis\u00e9e, alors lorsqu&rsquo;on essaiera de d\u00e9s\u00e9rialiser un \u00e9l\u00e9ment de type <code>object<\/code> on pourra sp\u00e9cifier n&rsquo;importe quel type.<\/p>\n\n\n\n<p>Prenons le cas suivant par exemple : <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>csharp\nusing System.Diagnostics;\nusing Newtonsoft.Json;\n\npublic class CommandManager {\n\tpublic string? output { get; set; }\n\n\tprivate string? _command;\n\n\tpublic string? command {\n\t\tget { return _command; }\n\n\t\tset {\n\t\t\t_command = value;\n\n\t\t\tProcess p = new Process();\n\t\t\tp.StartInfo.RedirectStandardOutput = true;\n\t\t\tp.StartInfo.FileName = \"\/usr\/bin\/env\";\n\t\t\tp.StartInfo.Arguments = _command;\n\t\t\tp.Start();\n\n\t\t\toutput = p.StandardOutput.ReadToEnd();\n\t\t\tp.WaitForExit();\n\n\t\t\tConsole.WriteLine(output);\n\t\t}\n\t}\n};\n<\/code><\/pre>\n\n\n\n<p>Cette classe poss\u00e8de un <em>setter<\/em> personnalis\u00e9 pour le champ <code>command<\/code>, il ex\u00e9cutera la commande pass\u00e9e et mettra la sortie dans le champ <code>output<\/code>. Comme expliqu\u00e9 plus haut, si nous utilisons la biblioth\u00e8que Json.NET pour d\u00e9s\u00e9rialiser, alors nous pourrons sp\u00e9cifier le nom de cette structure dans le champ <code>$type<\/code> et appeler le <em>setter<\/em> <code>command<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>csharp\nvar result = JsonConvert.DeserializeObject&lt;object&gt;(\n\tuser_input,\n\tnew JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects }\n);\n<\/code><\/pre>\n\n\n\n<p>Si nous utilisons le code ci-dessus pour d\u00e9s\u00e9rialiser la donn\u00e9e ci-dessous.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>json\n{\"$type\":\"CommandManager, myproject\",\"command\":\"id\"}\n\n<\/code><\/pre>\n\n\n\n<p>Alors le <em>setter<\/em> de <code>CommandManager<\/code> sera appel\u00e9 et notre commande <code>id<\/code> ex\u00e9cut\u00e9e. De la m\u00eame mani\u00e8re que pour l&rsquo;exploitation PHP, il existe des listes de classes vuln\u00e9rables sur des projets comme <a href=\"https:\/\/github.com\/pwntester\/ysoserial.net\" target=\"_blank\" rel=\"noopener\" title=\"\">ysoserial.net<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">D\u00e9s\u00e9rialisation dans d&rsquo;autres langages et bonnes pratiques s\u00e9curit\u00e9 <\/h2>\n\n\n\n<p>De mani\u00e8re g\u00e9n\u00e9rale, le proc\u00e9d\u00e9 est le m\u00eame dans les langages qui permettent de charger dynamiquement du code ou des classes. On cherche une fonction de d\u00e9s\u00e9rialisation puis des classes qui ont des m\u00e9thodes int\u00e9ressantes sans toujours tenir compte des consid\u00e9rations en termes de s\u00e9curit\u00e9.<\/p>\n\n\n\n<p>Nous proposons deux fa\u00e7ons de rem\u00e9dier \u00e0 ce probl\u00e8me. Si vous devez vraiment repr\u00e9senter des donn\u00e9es complexes venant du serveur et renvoy\u00e9es par le client, il est possible d&rsquo;utiliser une signature cryptographique avec la donn\u00e9e s\u00e9rialis\u00e9e par le serveur et de v\u00e9rifier la signature lorsque l&rsquo;utilisateur renvoie la donn\u00e9e. De cette fa\u00e7on, un attaquant ne pourra pas modifier la donn\u00e9e pour charger arbitrairement du code sans invalider la signature. <\/p>\n\n\n\n<p>L&rsquo;autre fa\u00e7on serait d&rsquo;utiliser un format plus basique comme le JSON tout en utilisant une biblioth\u00e8que qui ne permet pas (ou en tout cas par d\u00e9faut) de charger arbitrairement des classes.<\/p>\n\n\n\n<p><strong>Auteur : Arnaud PASCAL \u2013 Pentester @Vaadata<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lorsqu&rsquo;on d\u00e9veloppe un jeu, on peut avoir besoin de sauvegarder la partie d&rsquo;un joueur dans un fichier pour ne pas perdre sa progression afin qu\u2019il puisse revenir l\u00e0 o\u00f9 il en \u00e9tait. De la m\u00eame mani\u00e8re, quand on d\u00e9veloppe un \u00e9diteur de texte en ligne, on peut vouloir pr\u00e9server le contenu que l&rsquo;utilisateur a \u00e9crit.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,14],"tags":[],"class_list":{"0":"post-5617","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-solutions-fr","7":"category-technique"},"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/5617","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/comments?post=5617"}],"version-history":[{"count":18,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/5617\/revisions"}],"predecessor-version":[{"id":5663,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/5617\/revisions\/5663"}],"wp:attachment":[{"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/media?parent=5617"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/categories?post=5617"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.vaadata.com\/blog\/fr\/wp-json\/wp\/v2\/tags?post=5617"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}