Smartcat

scoreboard

Description: Smartcat was one of the cheapest point challenges available during the Insomnihack Teaser in January 2016. When solving the challenge the team is awarded 50 points. The challenge focused on being able to identify code injection opportunities and required the challenger to know linux bash tricks.


Introduction

When logging into the scoreboard we were presented with an interface where when clicking around on icons a challenge would be presented. When clicking on the litter box the we were presented with the smartcat1 challenge description and provided a link to reach the challenge site. Inside the description it describes that only the debug interface is available for the smart cat litter and that it only allows pings. It also tells u the “contract number” is stored somewhere on the page. Last, the challenge description tells us that there is no need to brute-force anything.

Problem

After clicking on the link (http://smartcat.insomnihack.cg/cgi-bin/index.cgi), we were provided with the Smart Cat debugging interface - which allowed us to input text into a form box labeled dest. So my first check was to see what happened when I inserted the word test

test case

This let me know that not only does the website accept IP addresses to test against ping, but also other inputs. In order to enable the ability to send other input though, we had to terminate the ping command with a carriage return. So we included a %0a argument in our web url request. This allowed us to execute arbitrary commands on the web server. For example, we could also put index.cgi?dest=%0als and index.cgi?dest=%0apwd and receive the directory contents and the present working directory of the web server script.1

However, when we tried to chain multiple commands together we ran into problems. We couldn’t do things like cat index.cgi, which would provide us the source code we were dealing with. We also tried hex encoding, url encoding, uniencoding, and then it hit us. Why aren’t we using redirection?

Before a command is executed, its input and output may be redirected using a special notation interpreted by the shell. Redirection may also be used to open and close files for the current shell execution environment. The following redirection operators may precede or appear anywhere within a simple command or may follow a command. Redirections are processed in the order they appear, from left to right.

So with that we redirected a file to cat, index.cgi?dest=%0acat<index.cgi. Just like that we were given the source code for the server script running the diagnostic terminal. After getting ahold of the source code we were able to quickly identify the blacklisted characters. Which were plentiful … $;&|({ `\t. This limited us to using =%0a%00"'\/><-. We did try to cat<there, but received an error. So we were able to see that it was probably a directory. Which leads us to our solution …

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/usr/bin/env python

import cgi, subprocess, os

headers = ["mod_cassette_is_back/0.1","format-me-i-im-famous","dirbuster.will.not.help.you","solve_me_already"]

print "X-Powered-By: %s" % headers[os.getpid()%4]
print "Content-type: text/html"
print

print """
<html>

<head><title>Can I haz Smart Cat ???</title></head>

<body>

<h3> Smart Cat debugging interface </h3>
"""

blacklist = " $;&|({`\t"
results = ""
form = cgi.FieldStorage()
dest = form.getvalue("dest", "127.0.0.1")
for badchar in blacklist:
if badchar in dest:
results = "Bad character %s in dest" % badchar
break

if "%n" in dest:
results = "Segmentation fault"

if not results:
try:
results = subprocess.check_output("ping -c 1 "+dest, shell=True)
except:
results = "Error running " + "ping -c 1 "+dest


print """

<form method="post" action="index.cgi">
<p>Ping destination: <input type="text" name="dest"/></p>
</form>

<p>Ping results:</p><br/>
<pre>%s</pre>

<img src="../img/cat.jpg"/>

</body>

</html>
""" % cgi.escape(results)

Solution

While we were researching how to enumerate the directory we remembered about the find command.2 After, that it was easy to solve the problem, based on our progress so far. We executed a get request using, index.cgi?dest=%0afind and then used cat to retrieve the flag.

solution


Endnotes

  1. Notice we did not include the entire url here. This is only for ease of creating the write-up. When crafting the HTTP get request it is required to send our input to the actual host address. I.e. http://smartcat.insomnihack.cg/cgi-bin/index.cgi

  2. The find utility recursively descends the directory tree for each path listed, evaluating an expression (composed of the primaries'' andoperands’’ listed below) in terms of each file in the tree.