Fuzzers usually used for general or precisely applications functions. In this part we'll show how to fuzz most known services using ruby. Remember, Fuzzing is an Art of Hitting Things, it's not about the tools.
Fuzzer Types
Mutation
Metadata/File format
The general idea of fuzzing FTP service is to test all commands buffer sizes. However, not the case isn't the same all the time, for example, testing username and password buffers. In addition, the same technique could be applied for many services even customized services.
#!/bin/ruby# KING SABRI | @KINGSABRI# Simple FTP COMMNDS Fuzzer#require 'socket'​class Stringdef red; colorize(self, "\e[31m"); enddef green; colorize(self, "\e[32m"); enddef colorize(text, color_code); "#{color_code}#{text}\e[0m" endend​mark_Red = "[+]".redmark_Green = "[+]".green​​host = ARGV[0] || "127.0.0.1"port = ARGV[1] || 21​# List of FTP protocol commandscmds = ["MKD","ACCL","TOP","CWD","STOR","STAT","LIST","RETR","NLST","LS","DELE","RSET","NOOP","UIDL","USER","APPE"]​buffer = ["A"]counter = 1​cmds.each do |cmd|buffer.each do |buf|​while buffer.length <= 40buffer << "A" * countercounter += 100end​s = TCPSocket.open(host, port)s.recv(1024)s.send("USER ftp\r\n", 0)s.recv(1024)s.send("PASS ftp\r\n", 0)s.recv(1024)puts mark_Red + " Sending " + "#{cmd} ".green + "Command with " + "#{buf.size} bytes ".green + "Evil buffer" + ".".greens.send(cmd + " " + buf + "\r\n", 0)s.recv(1024)s.send("QUIT\r\n", 0)s.closeendputs "~~~~~~~~~~~~~~~~~~~~".redsleep 0.5end
I was thinking of making it a bit more elegant to give myself a chance to inspect and configure each command separately.
#!/usr/bin/evn ruby## KING SABRI | @KINGSABRI# Simple FTP COMMNDS Fuzzer#require 'socket'​if ARGV.size < 1puts "#{__FILE__} <host> [port]"exit 0else@host = ARGV[0]@port = ARGV[1] || 21end​def fuzz(payload)begins = TCPSocket.open(@host, @port)s.recv(2048)s.send payload, 0s.recv(2048)s.closerescueputs "Crash detected after #{payload.size} bytes"exit 0endend​def insertion(point="", buffer=0)buffer = buffer * 10points ={core: "A" * buffer, # Comment this line is it hangs the fuzzeruser: "USER " + "B" * buffer + "\r\n",pass: "PASS " + "C" * buffer + "\r\n",accl: "ACCL " + "D" * buffer + "\r\n",appe: "APPE " + "E" * buffer + "\r\n",cmd: "CWD " + "F" * buffer + "\r\n",dele: "DELE " + "G" * buffer + "\r\n",list: "LIST " + "H" * buffer + "\r\n",ls: "LS " + "I" * buffer + "\r\n",mkd: "MKD " + "J" * buffer + "\r\n",nlst: "NLST " + "K" * buffer + "\r\n",noop: "NOOP " + "L" * buffer + "\r\n",retr: "RETR " + "M" * buffer + "\r\n",rest: "RSET " + "N" * buffer + "\r\n",stat: "STAT " + "O" * buffer + "\r\n",stor: "STOR " + "P" * buffer + "\r\n",top: "TOP " + "Q" * buffer + "\r\n",uidl: "UIDL " + "R" * buffer + "\r\n"}return points[point] unless point.empty?pointsend​puts "[+] Fuzzing #{@host} on port #{@port}..."insertion.keys.each do |point|(1..500).each do |buffer|​puts "[+] Fuzzing #{point.to_s}: #{insertion(point, buffer).size} bytes"fuzz insertion(point, buffer)​endend
Note that, this script can be used for other protocols (IMAP, POP3, etc) since it deals with socket!.