Exploit Development Part 1 - the Basics of Fuzzing

When searching for vulnerabilities (bugs) in applications fuzzing has been proven to be a very effective method to identify input validation bugs. In this post we will have a look at a very simple fuzzer. At the end we will have a fuzzer that will fuzz the IMAP protocol. Lets get started.

During this exercise we will fuzz “Eudora Qualcomm WorldMail 3.0” The installation file for this mail server can be downloaded from: http://www.exploit-db.com/wp-content/themes/exploit/applications/7b4ab5fe7aed0d10fd23bfa3f5555045-WorldMail3_installer.exe

After installation you will see the mail server is running multiple services on different ports either via the WorldMail management console or/and via a nmap scan. We will focus on port 143 which is running IMAP.

So what is fuzzing? Fuzzing in short is a technique where you send all sorts of data to the application to see if it crashes. You’ll use the application logic to reach different parts of the code. The best way to understand fuzzing is by building a very simple fuzzer yourself.

The first thing that is important is that we create a simple program that connects to the server and is able to send and receive data.

import argv from sys

print "[*] Building connection"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((argv[0], 143))
data=s.recv(1024)
print "[*] Successfully connected. Recieved banner: " + data.strip()
print "[*] Sending data..."
s.send(data + "rn")
print "[*] Data send, closing connection"
s.close()
print "[*] Done"

Easy, now we can connect, receive the IMAP worldmail banner and send data.

Lets write the fuzzing part: We will keep this fuzzer extremely simple. We will create a string with a specific character, then we will in create the size with every loop. We’ll repeat this process for every IMAP command till the string we are sending is equal or larger then a length of 5000

Lets see what this looks like:

#!/usr/bin/python
import time
import socket
from sys import argv

def imap_connect(junk):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((argv[1], 143))
            data=s.recv(1024)
            print "[*] Sending junk (\\x%s * %i)" % (junk[0].encode("hex"), len(junk))
            s.send(junk + "\r\n")
            s.close()
        except:
            print "[!] An error has occured, this is probably good news ;)"
            quit()

#Lot of IMAP commands are missing but you get the concept ;)
commands = ["LIST", "AUTHENTICATE", ""]

if argv[1]:
    #Getting our char
    for char in range(256):
        junk = chr(char) 
        counter = 1
        while len(junk) < 1000:
            junk += str(chr(char) * 50) #Adding 50 chars to our current junk str
            for command in commands:
                imap_connect("A01 " + command + str(junk)) 

Now this is nice but you can probably see that this fuzzer is dead simple. Also, there is no other implementation of the IMAP protocol except for the IMAP commands. We are not even logging in. I would be great if we had those opportunities to. Luckily, other people already wrote fuzzers that do this for you. A good example is Spike (comes with backtrack). Spike is great for this scenario because it already has a IMAP protocol implementation.

You should be able to get the same type of crash (the previous simple fuzzer script will cause a crash, more about application crashes in part 2) with Spike by running the following commands:

cd /pentest/fuzzers/spike/src/
./generic_send_tcp <server-ip> 143 audits/IMAP/imap1.spk 0 0

Well thats it for now. We have a crash. Next post we’ll have a look to see if we can exploit this crash.

Happy crashing, Ruben.

Comments