{"id":364,"date":"2012-11-07T10:39:59","date_gmt":"2012-11-07T18:39:59","guid":{"rendered":"http:\/\/seanmurphree.com\/blog\/?p=364"},"modified":"2012-11-20T16:21:01","modified_gmt":"2012-11-21T00:21:01","slug":"natas-level-16-semi-blind-shell-injection","status":"publish","type":"post","link":"https:\/\/seanmurphree.com\/blog\/?p=364","title":{"rendered":"Natas Level 16 &#8211; Semi-Blind Shell Injection"},"content":{"rendered":"<p>In this post, we&#8217;re going to be looking at Level 16 of the Natas wargame, hosted by Over The Wire.<\/p>\n<h2>What&#8217;s Going On?<\/h2>\n<p>Upon logging in, we are presented with a text field, submit button and the usual link to the PHP source code of the level. \u00a0Additionally, we&#8217;re given a bit of text that says this level now filters even more characters. \u00a0Seeing this screen, we should be reminded of Level 10 which took a value from us, and used grep to find it in a dictionary.txt file. \u00a0However, to verify, it&#8217;s look at the PHP source code.<\/p>\n<p>Once we look at the code, we can see this is basically the same level except for a few small differences. \u00a0The main difference is that now more characters are filtered from the user input. \u00a0This includes single quotes, double quotes, back ticks, ampersand, pipe and semi-colon. \u00a0This is all in an attempt to prevent shell-injection, as our user supplied value is passed to the grep command. \u00a0However, this filtering doesn&#8217;t filter all necessary shell characters! Specifically, shell allows for commands to be executed in the following fashion:<\/p>\n<blockquote><p>$(command) will execute command<\/p><\/blockquote>\n<p>So, let&#8217;s look at how we can use the above execution format to beat this level.<\/p>\n<h2>Exploit<\/h2>\n<h3>Part 1<\/h3>\n<p>Since we cannot put double quotes in our input, we can&#8217;t simply close the search quotes and specify another file to list as well, like we did in level 10. \u00a0Instead, we must supply some value within the grep search quotes, and get some result. \u00a0So, let&#8217;s think. \u00a0If we could get one character at a time from the password file and grep it against dictionary.txt, we could discern, based on the grep results, what character was searched for. \u00a0If we could do this for every character of the password, we could discern the password. \u00a0So, how can we do this? \u00a0Well, luckily linux provides us with the cut command. \u00a0We can use cut to select a specific character position from a string as follows:<\/p>\n<blockquote><p>cut -c1-1 &lt; \/etc\/natas_webpass\/natas17<\/p><\/blockquote>\n<p>The above command would return the 1st character from the natas17 password file. \u00a0Now, let&#8217;s remember we need to get that above command executed, not simply used as a search string itself, so we must wrap it in $() like:<\/p>\n<blockquote><p>$(cut -c1-1 &lt; \/etc\/natas_webpass\/natas17)<\/p><\/blockquote>\n<p>Submitting the above as our query returns a blank page. \u00a0This is possibly good or possibly bad. \u00a0Remember, passwords sometimes have numbers and the dictionary file doesn&#8217;t have any numbers. \u00a0So to make sure it&#8217;s working correctly, let&#8217;s submit the same command but for the 2nd character:<\/p>\n<blockquote><p>$(cut -c2-2 &lt; \/etc\/natas_webpass\/natas17)<\/p><\/blockquote>\n<p>Now we get a list result. \u00a0This tells us two things. \u00a0First, it tells us our submission is working as planned. \u00a0Second it tells us a list of words all sharing one same character. \u00a0In this instance it&#8217;s the letter &#8220;h&#8221;.<\/p>\n<p>Great! \u00a0Now we can repeat this for every character position and get an idea of the password. \u00a0We will know where numbers reside, and we will figure out the letter of every other character! \u00a0However, we aren&#8217;t done yet. \u00a0We still need to figure out which number is in which numeric positions, as well as if characters are upper or lower case (since grep uses the -i flag for case-insensitive search).<\/p>\n<h3>Part 2<\/h3>\n<p>Now that we have a good idea on most of the password, let&#8217;s take a finer approach to nailing down the specifics (numbers and capitalization).<\/p>\n<p>The linux shell provides many tools, including conditional logic through if\/then\/else statements. \u00a0If we can make use of this, we could compare the characters of the password to a specific value, and if they are equal return one value, if they&#8217;re not, return a different value. \u00a0We can use this logic to verify which characters are uppercase or lowercase as well as check what numbers are in the numeric positions of the password. \u00a0First, let&#8217;s look at the if\/then\/else structure:<\/p>\n<blockquote><p>$(if [ $(cut -c32-32 &lt; \/etc\/natas_webpass\/natas17) = x ]<br \/>\nthen<br \/>\necho x<br \/>\nelse<br \/>\necho 0<br \/>\nfi)<\/p><\/blockquote>\n<p>The above compares the 32nd character to lowercase x, and if it&#8217;s equal returns x, otherwise returns 0. \u00a0This is a good submission to this level as we will see a list of words containing x if the 32nd character is equal to little x, otherwise we will get no list (since there are no numbers in dictionary.txt). \u00a0One thing to note about the statement above is that when placed on new lines, there is no delimiter needed between the if condition, then, and else (If placed on the same line however, the required delimiter would be the semi-colon, which is filtered in this level). \u00a0But, how can we place new lines in a single line text field? \u00a0Well, we can&#8217;t. \u00a0Though, what we can do is specify the new line character through URL encoding. \u00a0Just like how the space character is encoded as %20, the new line character has ASCII hex value &#8220;0a&#8221; and can be encoded in the URL as %0a. \u00a0So, let&#8217;s look at the URL request for the above query:<\/p>\n<blockquote><p>http:\/\/natas16.natas.labs.overthewire.org\/index.php?needle=$(if+%5B+%24%28cut+-c32-32+%3C+%2Fetc%2Fnatas_webpass%2Fnatas17%29+%3D+x+%5D%0athen%0aecho+x%0aelse%0aecho+0%0afi)&amp;submit=Search<\/p><\/blockquote>\n<p>The above returns the list of words with x in them. \u00a0Thus, we can discern that the 32nd character of the password is in fact lowercase x. \u00a0To verify that this is case sensitive, change the lowercase x to uppercase and see that nothing is returned by grep. \u00a0Now, we simply need to test all characters in this same fashion for case, as well as the numeric spots for what number they contain. \u00a0Done by hand, this is easily finished within 15 minutes, or a script could be written using the above query only to brute force the password without even requiring step 1.<\/p>\n<h2>So What?<\/h2>\n<p>Input sanitization or filtering works great, when it checks for all possible attacks. \u00a0However, when even the smallest vector is left open, it will be found and it will be exploited. \u00a0This level goes to show that injection isn&#8217;t limited to SQL, or databases, or even the shell which was used here. \u00a0Injection is the result of control channels being mixed with data channels. \u00a0When user data can contain control characters and they are allowed to do their controlling work, there will always be problems!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post, we&#8217;re going to be looking at Level 16 of the Natas wargame, hosted by Over The Wire. What&#8217;s Going On? Upon logging in, we are presented with a text field, submit button and the usual link to &hellip; <a href=\"https:\/\/seanmurphree.com\/blog\/?p=364\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[36,35,4],"tags":[39,37,13,38],"_links":{"self":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/364"}],"collection":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=364"}],"version-history":[{"count":6,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/364\/revisions"}],"predecessor-version":[{"id":373,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/364\/revisions\/373"}],"wp:attachment":[{"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=364"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=364"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/seanmurphree.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=364"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}