Thursday, August 13, 2009

Statefull/Authenticated/Deep Protocol Fuzzing with Sulley

Okay so Sulley works, but creating a basic HTTP fuzzer was nothing so cool. It just scratched the protocol surface. How about statefull or in-state protocol with authentication? How but fuzzing the methods/functions and it's arguments deep within?

Here is a proof-of-concept dig at leveraging Sulley to do just that for FTP. Same would be possible to achieve for various other protocols like SMTP, POP3.

from sulley import *

import socket
import ftplib


s_initialize("ftp-cmds")

if s_block_start("site"):
s_string("status")
s_static("\r\n")
s_block_end()


def ftpcon(target):

ftp = ftplib.FTP('localhost','cloner','cloner')

def do_fuzz():
sess = sessions.session(session_filename="ftptest.log")
target = sessions.target('localhost', 21)
sess.add_target(target)
sess.pre_send=ftpcon
sess.connect(s_get("ftp-cmds"))
sess.fuzz()

if 1:
do_fuzz()

Firing this generates 1076 test cases for fuzzing (ofcourse you could add to the existing Sulley attack library to generate more test cases) one ftp command post authentication.


This code can be extended to fuzz all the ftp commands/methods and its arguments that are available post authentication in a statefull manner.

Let's see what it really took to get this done. It was FTPLIB that made it possible for us to take establish an authenticated session with the target Pure-FTPd server. The default python installation comes with libraries for several other protocols like SMTP, HTTP and POP3 as well.

For encrypted protocols SSL python library is available in case you do not wish to use proto=ssl option from Sulley.

How difficult is it to write something like FTPLIB or the authentication/statefull piece for your target protocol? The short answer is - it depends - on protocol specifications (if at all you have) and your mileage. Good skill set at Python socket programming can boost your mileage considerably!

Let's look at a snippet of FTPLIB and see what does it take.

def connect(self, host='', port=0, timeout=-999):
self.sock = socket.create_connection((self.host, self.port), self.timeout)
self.af = self.sock.family
self.file = self.sock.makefile('rb')
self.welcome = self.getresp()
return self.welcome

No wonder why hackers love Python!

2 comments: