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!.

Last updated