Brainpan 1 VM

for the Brainpan: 1 VM hosted on Vulnhub from superkojiman.

I’ve been learning buffer overflow exploits for Windows and Linux for the past week in preparation for eventually starting the OSCP, so I decided to look for a VM that needs me to do this to progress with it. I really enjoyed this one, although I did learn quite a bit (Especially using a local binary for privilege escalation through an overflow attack, as opposed to opening a remote shell)

I’ve tried to make this as comprehensive as I could, but despite it being screenshot-heavy I’m sure I’ve left some out, but hopefully it’s explanatory enough to help.

Ok, so first off nmap:

We can see two ports that don’t really look standard and can’t tell us much, but with a banner-grabbing script in nmap we find out that port 10000 is a http port, so let’s run it through nikto:

When we view the page through a browser the front page is pretty much useless to us:

Nikto did find a ‘bin’ directory, so let’s check if there’s anything else by brute-forcing potential paths through dirb:

Still just ‘bin’, so we’ll focus on that. It turns out to be a directory listing containing a windows executable, which I’m assuming is the abyss service on port 9999:

So I used a Window 7 VM (Which I got from ModernIE, a site from MS which provides VMs for testing). I was able to crash the application with a large input of characters, So the next step is to locate the EIP memory address by sending in a known pattern of characters and seeing what populates the EIP when the application crashes again:

import socket

host = ""

buffer = crash  
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
print "[*]Sending evil buffer..."  
s.connect((host, 9999))
print data
print "[*]Payload Sent !"

And then we use pattern_offset, using the contents of the EIP as input, to see at what offset it’s located:

So we refine our overflow python script with ‘A’ * 524 then ‘B’ * 4, and if we’re correct the EIP will be populated with the letter ‘B’ 4 times (the hex code for ‘B’ being \x42):

So now that that is confirmed, we use the mona script within immunity debugger to locate a module with bad-enough memory protection to help us, and find one:

When looking through these modules, the best candidate will have Rebase and ASLR disable, while also being present on the victim’s machine as well as our own environment; the executable under exploit is always the best candidate for this as we know for a fact the victim will be running it, so this works out for us.

So now the next step is to find an instruction for JMP ESP (\xff\xe4, which value can be found through nasm on kali):

Because it’s little-endian, when we use this address we will send the characters right-to-left.

and then the next step is to create a payload using msfvenom, targeted to windows 32-bit and encoded to remove the null byte bad character. This payload will open a reverse tcp shell; in other words it will call our machine as defined in the LHOST and LPORT which we can listen for with netcat.

So this gives us our exploit script as you can see below; some padding to the EIP offset, the instruction to JMP ESP and then the buffer preceded with a few NOP sleds:

and now let’s check that this works by opening a netcat listener and seeing if it picks up a request:

Great! Now even though this is a Windows executable, the victim machine is running Linux and probably executing the application through WINE, so now that our concept works we’ll just replace our payload with one targetting linux:

We also change the host from our Windows VM to the target VM and the script is ready to go:

Now when we execute it we see that it works there too:

So we can see we’re on a limited shell as a user called “puck”. Now let’s firstly get a bash shell, then look for any good SUID binaries that this user can execute:

This one stands out, as it resides in local/bin:

so we move this to /home/puck/web and from our kali machine we can see the binary in the same place where we downloaded brainpan.exe from. We can see above it takes one parameter as an argument and that means that hopefully we can overflow that and abuse the SUID against it.

first of all, let’s try to crash it:

The segmentation fault tells us the memory is banjaxed and that means our overflow is possible.

It’s difficult to test this as easily as our windows one because within linux I prefer the edb debugger (Just what I learned with), but the executable dies straight away, success or fail, leaving edb nothing to really work with. I did find an option though to provide arguments to the process that edb is attached to before it is unpaused:

So above is our repeated string pattern that we use to locate the EIP register.

And here we can see which portion of the string overwrote that register:

Which is how we get our offset:

and test it again by populating with ‘B’ * 4:

I couldn’t find a JMP ESP instruction within this binary which is unfortunate, but I did find a CALL EAX instruction, which as far as I can tell (And I may be wrong here) means that the payload goes before the EIP portion of our attack string instead of after, which means a limited amount of space to work with, but luckily our offset to EIP was quite high. So here’s our instruction, found through edb:

and again we create our payload, this LOOKS fine, but as I figure out later there was a gap in my knowledge when crafting it:

and the final script:

to put this onto the victim machine, I just went back to my reverse shell as ‘puck’ and did a wget from my kali’s apache folder.

Now the gap in my knowledge was that even though that SUID was set bash would pretty much ignore it, enter SHELLSHOCK which gets around this. The exploit would work but I would still be puck, though with the shellsock inserted as the payload instead I would gain the permissions of the owner of the binary:

The payload for this was the shellshock exploit found here:

Now let us see what this ‘anansi’ user can do, using sudo -l:

so they can execute a binary called anansi_util as root. The binary itself doesn’t seem to do much but that doesn’t matter. We just have to run bash or something while still satisfying the sudoers entry. We do this by creating a symlink to bash and calling it anansi_util from within that directory:

And then execute to get root:

Written on May 12, 2017