|
Page 3 of 6 Writing the SEH Exploit
Now that we know conceptually how a SEH exploit operates, we need to apply this to a buffer overflow bug in some software. One of the hardest parts of writing an exploit for software is to first find a vulnerability in it. In this case, we are going to leverage a documented vulnerability instead of taking time to attempt to find our own. While searching with Google, we are able to find this link from Juniper which describes a vulnerability in EasyChat Server 2.2. Refer to this link for more details:
http://www.juniper.net/security/auto/vulnerabilities/vuln25328.html
Severity: CRITICAL
Description: Easy Chat Server is a web-based chat server for Microsoft Windows.
The server is prone to a remote buffer-overflow vulnerability because it fails to validate user-supplied data.
This issue arises when an attacker supplies excessive data as part of the authentication credentials. Specifically, this issue affects the 'username' and 'password' parameters of the 'chat.ghp' CGI application.
Attackers may leverage this issue to execute arbitrary code in the context of the application. Failed attacks will cause denial-of-service conditions.
Easy Chat Server 2.2 is reported vulnerable; other versions may also be affected.
Affected Products:
EFS Software Easy Chat Server 2.2
This tells us that we may be able to send an overly long username and/or password to the chat.ghp CGI application and cause it to generate an exception that we can take advantage of. After researching the EasyChat software more, we are able to see that it is a web based application and that the login page itself limits us to 30 characters for a username. If we use an application like wget to send a request with a large username, we may be able to get EasyChat to crash with a DOS condition. If so, we can then begin working to try and control the crash using an SEH attack vector exploit.
The http request to chat.ghp will need to look something like this:
http://10.82.80.201/chat.ghp?username=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&password=test&room=1&sex=2
While wget may work well in this case to test for a crash, it is usually better to write a perl or python script to allow for greater flexibility in writing the exploit. For our attack, we are going to use python. Based on the general design for the exploit discussed earlier, we know that the A's section representing the username will actually need to look more like the following:
Buffer Padding + short jump to stage 2 + pop/pop/ret address + stage 2 payload
The first task we need to do is select the operating system that EasyChat Server will be running on. In our case, we will tailor this exploit to function on Windows XP SP1 English edition to start with. This is important to note because supporting DLL libraries change between main operating systems such as Windows XP and Window NT as well as between service pack editions of the same primary operating system like Windows XP SP1 and SP2. Even the language such as English vs. French can make a difference. Based on the specific flavor of Windows, we will need to determine a valid pop/pop/ret that can be used.
Since we will be running EasyChat Server on a Windows platform, we will use the free debugger OllyDBG version 1.10 to help us see how EasyChat operates in conjunction with our exploit. In most cases it is much easier to write a functional exploit if you can create a sandbox for the target software. By having EasyChat Server running in a controlled environment, we can continue to crash and restart the server while observing the behavior with OllyDBG which makes creating the exploit much simpler. If you attack an application in the wild, you may only get one attempt at a successful exploit.
Let's begin by trying to determine exactly how long the buffer padding needs to be so that we properly overwrite the Next Exception_Registration_Record pointer and Exception Handler pointer in the stack. After starting the EasyChat Server, we start OllyDBG on the target server. Within Olly, select File -> Attach to see a list of running processes to attach to. We will need to select the one for "Easy Chat Server". If for some reason you do not see the process, close Olly and restart it. Once Olly is attached to the EasyChat process, you will see the process was paused in the lower right-hand corner. It is critical to remember to click the play button in Olly to allow the system to continue processing. If you do not click play, the listener for EasyChat will not respond to the attacker and we will not ever see anything occur.
We are now ready to try our first attempt. We will use Windows XP SP2 as the attacker platform using Python 2.6 for Windows, but you can use any platform you choose. Our initial Windows Python code will look like this:
#!c:/Data/Apps/python/python.exe -u
import string, sys
import socket, httplib
#buffer offest for SP1
buffer = 'A'*200
# add DEADBEEF to buffer to help align on SEH pointer in memory
buffer += '\xEF\xBE\xAD\xDE'
# Add a bunch of hex 42 (B's) to help over flow buffer and see results.
# This is where the primary exploit (stage 2) code will go.
buffer += 'B'*500
url = '/chat.ghp?username=' + buffer + '&password=' + buffer + '&room=1&sex=2'
print 'Running exploit...\r\n'
print url
conn = httplib.HTTPConnection('192.168.1.205', 80)
conn.request("GET", url)
r1 = conn.getresponse()
print r1.status, r1.reason
conn.close()
We'll look at all the pieces to this code before looking at the results in Olly. The first line of code tells the python interpreter where the python executable is located. In my case, Python was installed in the C:\Data\Apps\Python directory where the python.exe file sits. The "-u" flag tells python to operate with unbuffered binary stdout and stderr. This will help keep our script from hanging when executed. The next few lines are used to import function libraries. While all of the ones include in our script are not required, it does not hurt anything to include extra libraries. The most critical import is httplib which is used to create the http connection to the chat server.
We then begin by building a string variable called buffer. This will be the variable that we pass as username when complete. Buffer is first created with 200 letter A's. We then append hex EFBEADDE to the buffer using the "+=" operator. This brings us to the issue of "Little Endian" vs. "Big Endian". In computing, endianness is the byte (and sometimes bit) ordering used to represent some kind of data. In our case, it is relevant to how memory addresses are stored and read. In big endian, the most significant bit comes first. The address 0xABCDEF12 is written in shellcode as "\xAB\xCD\xEF\x12". However, in little endian, you have the opposite where the least significant bit comes first. In this case, our shellcode address would be written as "\x12\xEF\xCD\xAB". Therefore when we are looking at the stack dump in OllyDBG, the shellcode string "\xEF\xBE\xAD\xDE" will appear as DEADBEEF which is easy to spot in the stack.
To finish the buffer, we append 500 letter B's (hex 42) to ensure that we will overflow the buffer. I use B's after DEADBEEF just to make it easier to spot where hex 41 stops and hex 42 begins. Now that the buffer is complete, we construct the url string that we intend to send to the chat server. Notice that the parameters room= and sex= are also required in the GET message we send. In my case, I use the buffer for both the username and password fields since both are vulnerable, but this is not required. One or the other should also work fine.
The final task is to connect to the http server and send the GET message. Function httplib.HTTPConnection establishes the connection to the HTTP server on port 80 and returns a handle for the connection assigned to variable conn. The line conn.request("GET", url) then sends the url we made with an HTTP GET request. The next line attempts to retrieve the http return code such as 200 OK. The status and reason of the response is printed followed by a command to close the connection to the server.
There is one other important item to note. The script itself ends with the .py extension which tells windows to use the Python interpreter for this file. When we open a command prompt at where the script is located we can now simply type the name of the script file such as attack.py to launch our attack. Let's go ahead and do this to see how our exploit code behaves so far.
|