Fuzzer
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
Mutation
FTP Fuzzer
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 String
def red; colorize(self, "\e[31m"); end
def green; colorize(self, "\e[32m"); end
def colorize(text, color_code); "#{color_code}#{text}\e[0m" end
end
mark_Red = "[+]".red
mark_Green = "[+]".green
host = ARGV[0] || "127.0.0.1"
port = ARGV[1] || 21
# List of FTP protocol commands
cmds = ["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 <= 40
buffer << "A" * counter
counter += 100
end
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" + ".".green
s.send(cmd + " " + buf + "\r\n", 0)
s.recv(1024)
s.send("QUIT\r\n", 0)
s.close
end
puts "~~~~~~~~~~~~~~~~~~~~".red
sleep 0.5
end
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 < 1
puts "#{__FILE__} <host> [port]"
exit 0
else
@host = ARGV[0]
@port = ARGV[1] || 21
end
def fuzz(payload)
begin
s = TCPSocket.open(@host, @port)
s.recv(2048)
s.send payload, 0
s.recv(2048)
s.close
rescue
puts "Crash detected after #{payload.size} bytes"
exit 0
end
end
def insertion(point="", buffer=0)
buffer = buffer * 10
points =
{
core: "A" * buffer, # Comment this line is it hangs the fuzzer
user: "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?
points
end
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)
end
end
Note that, this script can be used for other protocols (IMAP, POP3, etc) since it deals with socket!.