🧠Brainpan
Exploiting a buffer overflow and abusing sudo privileges for escalation.
Last updated
Exploiting a buffer overflow and abusing sudo privileges for escalation.
Last updated
Room
Brainpan
OS
Level
Hard
Link
This box is a little different than the others. The description reveals that the target is meant as a practice for the OSCP buffer overflow so that's what we'll be focusing on.
We begin with the typical port scan to see what's open on the target brainpan.thm
:
We get two uncommon ports so let's run an nmap
scan to get a better idea of what's running.
Apparently, port 9999 features a custom application that nmap
can't identify. Port 10000 on the other hand appears to be a SimpleHTTP python server. Being curious of course, we connect to port 9999 with nc
and see what's coming back:
For obvious reasons we wouldn't have done something like this in production (we've just executed a successful DoS attack) but since we expect a buffer overflow we can now assume that this might be it.
If we wait for a minute we'll be able to connect again. It's possible that a cronjob
is restarting the service from time to time so we don't have to reset the target every time.
But enough breaking stuff, we still got a webserver to investigate.
Visiting http://brainpan.thm:10000/
in a browser we are greeted by a single image that contains several statistics about "safe coding". There's no interactive content, no links, no robots.txt
. After starting a gobuster
scan we do find something interesting though.
There's a /bin
directory. Navigating to it leads to a directory listing with a single item in it: brainpan.exe
, which we can download.
Judging from the output of the service on port 9999 and the name of the executable, we just found the binary of that seemingly vulnerable service.
To determine the file type of the executable we use file
:
That's interesting, it turns out to be a windows executable. However, the nmap
scan was 95% sure that the target is running on linux. Using ping
we can further support that assumption:
TTL values of 64 are usually the default on linux machines, whereas on windows we'd rather expect a value of 32 or 128. (We see 63 because of the intermediary VPN hop.)
See this blog post for a more detailled list of default TTL values.
We should keep this in mind when it comes to exploiting a buffer overflow in order to select the right payload.
Most write-ups will show how to use Immunity Debugger. However, there's an easier way to exploit this buffer overflow without using a debugger or a windows VM.
Alright, we got the windows executable - let's analyse it. Usually we'd use something like checksec
to extract protection mechanisms from the binary but that's for ELF only. For PE we use pesec
instead (install this and other tools for PE analysis via sudo apt install pev
).
No stack canaries, no data execution prevention and no address space layout randomization - how fortunate for us. Let's see what that code is actually doing by analyzing it with Ghidra
.
The main
function works pretty straight forward. It follows the default socket programming procedure of creating a socket (lines <40), binding the socket to port 9999 (line 46-47) and waiting for connections with accept
in an endless loop (line 56).
Following a successful connection of a client the banner that we saw earlier (stored in local_400
) is send to the client (line 60). Subsequently, the server waits to receive up to 1000 bytes from the client (line 61). In line 62 the input is then passed to a function called _get_reply
.
The rest of the code is sending either ACCESS DENIED
or ACCESS GRANTED
to the client, depending on the return value of _get_reply
, before closing the connection.
Knowing that our input will be processed in _get_reply
we decompile this function.
The input (remember it could be up to 1000 bytes long) is copied to local_20c
which is a 520 bytes long char
array without any safety checks.
At this point, we have confirmed the buffer overflow vulnerability and can continue to exploit it with a special crafted payload.
I have explained all following steps in detail in this article: Buffer Overflow - Explained.
Step one - finding the offset.
The call to strcpy
happens with the address EBP-520
(signed hex represention in the screenshot) as destination address. Meaning after 520 bytes of input we'll overwrite the base pointer. Hence, after 524 bytes we overwrite the return pointer.
Offset = 524
bytes
Step two - finding a return address. We'll search for a JMP ESP
instruction (hex: FF E4
). Any hexeditor with a search function will work:
There's only one occurance at the file offset 0x6f3
. To get the virtual address we'll also need the image base and the data offset which we can read from the section headers with readpe
.
With the image base address at 0x31170000
and the address of the .text
section at 0x1000
we got the virtual base address for the program code. Together with the raw offset of the code in the file (0x400
) and the raw offset of our target address (0x6f3
) we calculate the final address:
We can confirm that we got the correct address by simply using the Ghidra
search function.
Return address = 0x311712f3
Step three - creating the shellcode.
Keep in mind that we got a linux target that's probably just emulating a windows binary. If this payload doesn't work we might try using different payloads instead.
Step four - the final exploit. Now we combine all the gathered information in a single exploit script.
We successfully exploited the buffer overflow and gained access to the target as user puck
.
Looking through our home folder we notice a checksrv.sh
script. This script is responsible for starting the brainpan.exe
and we can see that it's indeed being emulated using wine
. Note that a windows reverse shell would also have worked in this case.
The final part of this box, escalating privileges to root
, is pretty straight forward. Checking our current permissions with sudo -l
we discover an application that we're allowed to run as root
without a password. When executed without an argument we're shown the usage.
One command stands out: manual
, as it takes an input called command
. It shows the man page for the specified command. A quick search on GTFOBins leads to a shell (man
allows executing commands in the interactive view).
We finished the box and got root
access.
Although rated hard, this box focused only on a single very basic buffer overflow without any protection mechanisms. Mitigations for the buffer overflow alone include:
Enabling / enforcing ASLR
Enabling DEP
Enabling stack canaries
However, the root cause was a single unsafe string copy operation which failed to compare the length of source and destination first. Mitigation: apply safe coding practices (or use memory safe programming languages).
For the privilege escalation:
Avoid giving sudo
permissions to any user other than root
(in this case the SUID bit might have been a better choice)
Linux