This post details a walkthrough for level00 of the Fusion exploit exercise. This level contains a stack buffer overflow and no mitigations are enabled. This walkthrough will develop the exploit using the Metasploit framework.
This level contains a small web server that listens on an unknown port and calls the parse_http_request function for each connection. The parse_http_request will read 1024 bytes from the network connection and store this data into a buffer for processing.
The buffer must start with “GET path HTTP/1.1”, where path is an arbitrary string. The path data is passed to the fix_path function:
The result of realpath is stored in a 128 byte buffer. The realpath function resolves ./ or ../ paths and resolves symlinks. This function is the source of the buffer overflow because the path string is of arbitrary length. Sending a long path should cause a buffer overflow.
Building the proof of concept
Access the fusion machine over ssh using the credentials fusion/godmode, root access can be achieved using sudo -s with the password godmode. First determine of the PID of the level00 process and the port it is listening on.
The level00 process is using PID 1459 and listening on port 20000. This is confirmed using netcat to connect to port 20000:
Next attach gdb to this process and check which mitigations are enabled:
Just as the introduction suggested, the level00 binary is not compiled with any exploit mitigations. The following can be used as a skeleton remote TCP Metasploit module. I created the module at the following path: /opt/metasploit-framework/modules/exploits/fusion/level00.rb
Remember to replace the register_options array with the IP of your local fusion VM. In hopes of causing a crash lets modify the exploit method to send a payload with an overly long string of ‘A’ characters for the path.
Send the exploit and check gdb:
Huh, Gdb never caught an exception!?
This is because the process fork’d before calling parse_http_response and by default GDB does not attach to the child process. To change this behavior use the following command and send the exploit again: (gdb) set follow-fork-mode child
Success! The realpath function copied our string of ‘A’ characters into the resolved buffer causing a buffer overflow. This crashed on 0x41414141 because the the saved return pointer on the stack was overwritten with the string of ‘A’ characers.
Note: While developing the exploit we will be attaching the debugger many times. Rather than having to enable follow-fork-mode and source the commands each time, they can be placed in a file called .gdbinit. When gdb first starts it checks the local directory for this file and executes each command in it. While developing this exploit my .gdbinit file looks like:
Building the exploit
Using the Metasploit acyclic pattern we can determine exactly which four ‘A’ characters overwrote the saved return pointer. Modify the exploit method to use the Metasploit pattern:
Attach gdb to the level00 process again. Enter the reload command in msfconsole to reload the modules code and send the exploit.
Note: Thepattern_offset eipcommand will take the value out of the eip register and output the offset into the pattern that value was found
The value of eip is controlled by the 4 bytes at offset 127. Controlling the value eip allows us to execute code at an arbitrary address. To finish the exploit we need to get a payload somewhere in memory and put the location of the payload into eip. The level00 page gives a hint:
“Hint: Storing your shellcode inside of the fixpath ‘resolved’ buffer might be a bad idea due to character restrictions due to realpath(). Instead, there is plenty of room after the HTTP/1.1 that you can use that will be ideal (and much larger).”
Rather than trying to to put a payload into the path string replace the string of ‘B’s in the module with the payload. To find where the string of ‘B’s is located we can use the Metasploit pattern again. Modify the module to use a pattern length of 2000 in replace of the ‘B’s.
Attach gdb to the process, reload the module, and send the exploit:
Note: Thepattern_findcommand will find all occurances of the Metasploit pattern in memory and output its length and location.
Above we see two patterns were found. The first pattern is the path string, which was truncated to 200 bytes. The second pattern is payload which was truncated to 788 bytes. Luckily 788 bytes is just large enough for a meterpreter shell. In the module header options change the available space from 1400 to 788. The Metasploit checks this value when creating the payload.
Replace the data at offset 127 with the string address 0xbffff9e4 in little endian. This should execute the payload. For now make the payload a set of breakpoints to know we are attempting to execute it.
Attach gdb to the process again. Reload the module and send the exploit
Confirmed eip is executing the payloadi of breakpoints. The last step is changing the payload to a metsploit payload rather than breakpoints.
Finally a meterpreter shell! The puzzle is solved. Below is the full module: