/dev/random: Sleepy

Looks like I’ve got time to write up another recent VM challenge before the memory fades. This time, it’s boot2root challenge Sleepy by Sagi-.

I really like this one because it took me back to my University days of Java development. Then I hated it because it took me back to doing acrobatics with I/O readers, buffers, streams, etc. the Java way. Then when I completed it I loved it.

On with it then!

Initial scanning

Starting off with a full TCP SYN scan produce three open ports.

TCP 21 is FTP, and it allows anonymous login:

Anonymous is rightly jailed and there’s only an image to download:

sleepy

I thought that the image might hold some essential information or clues, but I wasn’t able to find any. Not sure if it’s a motif or a red herring.

Assuming FTP’s a red herring, attention turns to the other two open ports. Running a service scan on the ports might confirm what protocols they’re offering:

So with ajp13 confirmed as Apache Jserv, I guess we’re looking at something Tomcat. Probably my first thing to start work on.

At this stage I had never heard about Java Debug Wire Protocol, but a quick search tells me it’s a remote Java debugger.  This should be great. I still like working with Java, so if I get to play around with a debugger I’ve never seen that’s cool.

Dealing strictly with Apache Jserv first, however…

AJP

As AJP has accidentally been left open to the world, it might be possible to exploit the system, for example by injecting malicious code to the server. In order to control it, though, I need access to some Tomcat management interface to test it.

Exploiting an open AJP is pretty well documented by others so I’ll not go into to much commentary on it. I needed to set up Apache on my machine, and add the Apahce jk modules. Then configuring jk to forward requests – not to my local server, but to the victim – it should be possible to try and get management access.

libapache2-mod-jk provides the following files:

The default Apache website needs to forward all requests to JK, and JK needs to be configured to forward requests to the victim.

After restarting Apache, it’s possible to connect to http://localhost/ and see all of the Tomcat goodies including /manager/ and /host-manager/ on the victim. However, the passwords are not the defaults and attempting a few passwords didn’t prove successful.

Tomcat

Getting access is going to require viewing the administrative passwords – often stored in plaintext – from the server.

The Java debugger

The JDWP port appears to be controlled by the jdb command which provides a remote shell for control. It’s not a shell with the breadth of control that a terminal would provide – everything has to be done via Java execution – but hopefully with enough libraries exposed something can be conjured up.

The help is pretty good for jdb. Command classes outputs a list of all classes that are available to the running program, and classpath shows that we seem to be running Java 7…

Above we’ve got a hell of a lot of Java standard library classes available, plus a class which is named without a long package name – luciddream. This is presumably the author’s work, and given the Sleepy theme, that’s a fair guess.

It’s unfortunately not possible to just execute arbitrary Java from the prompt:

Instead control of execution needs to be seized by the debugger. The main class has only one function other than main and the constructor:

Setting a breakpoint on snore() and waiting eventually gives us control and at that point we can execute any arbitrary Java code we want, using the available classes:

Great! So, with all of the java.io classes we can potentially exfiltrate file data from the victim, or possibly even inject data. Also with java.lang.Runtime we’ve got access to the current thread and can execute arbitrary commands.

The thing is, merely executing a command will merely return the object representing the new process, not the response to the command. For example, running whoami:

To actually get output from the command, some I/O acrobatics is required. Working with what we’ve got (and I probably am not doing it in the most efficient manner), we’ve got the following return values and methods to link up.

  • exec() returns an object of type Process, let’s call it p.
  • p.getInputStream() returns an object of type InputStream, i
  • Ultimately we’re looking to get a String, s, which can be output to the console
  • Out of the many readers available, BufferedReader, r, offers method readLine() which returns a String, s
  • A BufferedReader, r, can be instantiated with an InputStreamReader, ir
  • An InputSteamReader, ir, can be instantiated with an InputStream, i, which we got earlier

Got that? Good.

  • exec() gives us Process p
  • p.getInputStream() gives us InputStream i
  • new InputStreamReader(i) gives us InputStreamReader ir
  • new BufferedReader(ir) gives us BufferedReader r
  • r.readLine() gives us String s

Putting this into practice, we can attempt to run whoami again:

Unfortunately things get a bit more complicated when the result of the command is multiple lines. We only get one call to readLine() on the BufferedReader, so only the first line of output can be retrieved. e.g. ls -la produces a weak result:

To get full output, line feeds need to be replaced with another string – e.g. by using awk ORS=’something’ – and in order to build more complicated commands with pipes and so on, we need a command processor, e.g. bash.

Voila:

Using this methos I did a search for files with tomcat in the name and got the following (edited) list:

Dumping this file gives us the passwords we require (again, edited for reading):

Credentials

TomcatManager

Exploiting Tomcat

Exploiting isn’t the right word here, as we own Tomcat now. We can easily get control as the Tomcat user with Metasploit and the credentials. (Remember that the rhost/target is our own machine as we’re attacking the victim through our Apache server:

We’ve not got a reasonable user shell on the system.

Privilege escalation

It’s getting quite late and I don’t want to make an already verbose walkthrough too much longer. In summary the following items were found in further investigation and are able to lead to privilege escalation.

First of all the machine is vulnerable to shellshock:

This may seem counter intuitive when we already have a shell, but it will come in essential later.

Furthermore there is an executable /usr/bin/nightmare that has SUID bit set and is owned by root. Since this runs as root, if we can get something arbitrary to run from this, then we can gain access as root.

I found the Meterpreter session to be extremely unstable for what happens next – I kept getting disconnected – so I uploaded nc to the victim and opened a reverse shell back to my machine:

And locally on my machine we can get a decent interactive shell:

nightmare needs some better terminal emulation configured, so this can be set up by setting environment variable TERM to ‘linux’ and using Python to spawn a proper tty. (FYI, to enter Ctrl-C in the terminal enter Ctrl-V first; this allows the Ctrl-C to be sent through to the remote host’s control instead of killing the Meterpreter session.)

Here’s what happens when /usr/bin/nightmare is executed normally:

Decompiling nightmare with Hopper, it’s easy to see what it’s doing. main() runs a loop (sub_4008d0()) which repeatedly calls fire(), which executes the command /usr/bin/aafire which is what’s responsible for animating the ASCII-art fire. The option to quit the program at the y/n prompt is ‘broken’ but by pressing Ctrl-C we enter sigHandler() which calls train(), which executes /usr/bin/sl – the executable responsible for the ASCII-art train. However, crucially this call sets the real/effective/saved UIDs and GIDs to root preventing a reduction in privileges if we can explioit Shellshock.

After finding a method to exploit that I hadn’t seen before, it was possible to get a root shell and get the flag.

Done!

SpyderSec: Challenge

I can’t believe it’s been nine months since my last post. I must have been busy. Or lazy.

Just as well I recently completed SpyderSec‘s nice little X-Files themed encryption challenge to get me out of my blog funk.

This was a really fun one, and totally worth a look if you’re interested in video steganography. This is a walkthrough to how I completed the challenge, so if you fancy trying yourself look away now.

Flag #1

The challenge spec already makes clear that this is a web application challenge and a full nmap TCP scan confirmed that only port 80 was open. The web page served doesn’t reveal too much:

Website front page

Just in case an administrator left some content or administration pages open, I scanned the host with dirb.

Search turns up a /v/ directory, but this is Forbidden.

Looking at the html source of the page reveals some packed JavaScript:

You can dump this packed program into one of a few public JavaScript unpackers, but I wanted to see if it would evaluate fine in nodejs, which it did:

The hex values appeared to be ASCII characters, so I tried converting to a string and got some interesting output:

I wasn’t sure what to make of “muder.fbi” at this point. Plugging it into the dirb search didn’t turn up any hidden content.

Plugging away at the page for a while, I turned to look at the logs of the requests I had made in BurpSuite. I noticed that the page was including a cookie and that it mentioned a URI:

I already knew of the /v/ directory, so it stood that there was a good chance I would find something interesting if I accessed this location directly. However, I found disappointment in the fact that the URI was also a forbidden location:

The challenge was beginning to feel very much like a hidden data exercise. I tried plugging various strings I had captured into the web server to see if I could find something. I can’t remember how long it took, but eventually putting the URI together with ‘mulder.fbi’ caused the web server to offer me a 13MB file:

A cursory examination of the file showed it as a video file.

Flag #2: Kill Switch

The video turned out to be a song with lyrics slides. (The song incidentally is a reference to an episode of The X-Files – I had to look that up.)

At this point I figured that there was something hidden in the video file. Hidden data – particularly where video is concerned – is really not my strong suit. I searched the file for strings (which didn’t help) and for container metadata (didn’t find any). On a hunch I decided to run the file through a video processor. I asked the program to make a direct stream copy of the audio and video, meaning that the whole content would be copied without recompression into a new file. If there was any hidden data in the file, it might reveal a difference in file size.

Several megabytes of data were missing from the stream copy, but the file played exactly the same; a strong indication that there was data to be found in the file. Since the data was not part of the video and audio streams, I felt I had a chance with this. (If the data had been hidden as data in the streams themselves then my chances of success would have been much lower.)

Still, I don’t really know much about video container formats, so I took the least resistance path and did some web searches first of all. Actually, doing a search for “hide data in mp4 video” turns up some pretty interesting stuff immediately. (That link is seriously worth a read if you’re interested.)

Working on the hunch that the video file contains a TrueCrypt encrypted volume, the challenge essentially becomes “find the correct password”. And the thing about TrueCrypt volumes is that they’re practically indiscernible from random data. All you can do is keep trying passwords until one works and even if you never find one that works, you will never know whether the data is actually random or you’ve just not found the correct password.

Anyway, you probably know where this is going. Eventually (too long) I found the password. I can’t remember exactly when I turned my attention to the website images (I had already gone over the BurpSuite logs several times to no avail, and was considering writing or searching for a tool to automate TrueCrypt password attempts) when I dumped the webpage content and started looking for strings.

The password was hidden in the metadata in the following file:

SpyderSec Challenge.png

And there we have it. The TrueCrypt password is A!Vu~jtH#729sLA;h4%. After that, getting to the final flag is a breeze…

SpyderSec TyueCrypt password

SpyderSec TrueCrypt volume mounted successfully

SpyderSec challenge completed