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.

  1. #!/bin/ruby
  2. # KING SABRI | @KINGSABRI
  3. # Simple FTP COMMNDS Fuzzer
  4. #
  5. require 'socket'
  6. class String
  7. def red; colorize(self, "\e[31m"); end
  8. def green; colorize(self, "\e[32m"); end
  9. def colorize(text, color_code); "#{color_code}#{text}\e[0m" end
  10. end
  11. mark_Red = "[+]".red
  12. mark_Green = "[+]".green
  13. host = ARGV[0] || "127.0.0.1"
  14. port = ARGV[1] || 21
  15. # List of FTP protocol commands
  16. cmds = ["MKD","ACCL","TOP","CWD","STOR","STAT","LIST","RETR","NLST","LS","DELE","RSET","NOOP","UIDL","USER","APPE"]
  17. buffer = ["A"]
  18. counter = 1
  19. cmds.each do |cmd|
  20. buffer.each do |buf|
  21. while buffer.length <= 40
  22. buffer << "A" * counter
  23. counter += 100
  24. end
  25. s = TCPSocket.open(host, port)
  26. s.recv(1024)
  27. s.send("USER ftp\r\n", 0)
  28. s.recv(1024)
  29. s.send("PASS ftp\r\n", 0)
  30. s.recv(1024)
  31. puts mark_Red + " Sending " + "#{cmd} ".green + "Command with " + "#{buf.size} bytes ".green + "Evil buffer" + ".".green
  32. s.send(cmd + " " + buf + "\r\n", 0)
  33. s.recv(1024)
  34. s.send("QUIT\r\n", 0)
  35. s.close
  36. end
  37. puts "~~~~~~~~~~~~~~~~~~~~".red
  38. sleep 0.5
  39. end

I was thinking of making it a bit more elegant to give myself a chance to inspect and configure each command separately.

  1. #!/usr/bin/evn ruby
  2. #
  3. # KING SABRI | @KINGSABRI
  4. # Simple FTP COMMNDS Fuzzer
  5. #
  6. require 'socket'
  7. if ARGV.size < 1
  8. puts "#{__FILE__} <host> [port]"
  9. exit 0
  10. else
  11. @host = ARGV[0]
  12. @port = ARGV[1] || 21
  13. end
  14. def fuzz(payload)
  15. begin
  16. s = TCPSocket.open(@host, @port)
  17. s.recv(2048)
  18. s.send payload, 0
  19. s.recv(2048)
  20. s.close
  21. rescue
  22. puts "Crash detected after #{payload.size} bytes"
  23. exit 0
  24. end
  25. end
  26. def insertion(point="", buffer=0)
  27. buffer = buffer * 10
  28. points =
  29. {
  30. core: "A" * buffer, # Comment this line is it hangs the fuzzer
  31. user: "USER " + "B" * buffer + "\r\n",
  32. pass: "PASS " + "C" * buffer + "\r\n",
  33. accl: "ACCL " + "D" * buffer + "\r\n",
  34. appe: "APPE " + "E" * buffer + "\r\n",
  35. cmd: "CWD " + "F" * buffer + "\r\n",
  36. dele: "DELE " + "G" * buffer + "\r\n",
  37. list: "LIST " + "H" * buffer + "\r\n",
  38. ls: "LS " + "I" * buffer + "\r\n",
  39. mkd: "MKD " + "J" * buffer + "\r\n",
  40. nlst: "NLST " + "K" * buffer + "\r\n",
  41. noop: "NOOP " + "L" * buffer + "\r\n",
  42. retr: "RETR " + "M" * buffer + "\r\n",
  43. rest: "RSET " + "N" * buffer + "\r\n",
  44. stat: "STAT " + "O" * buffer + "\r\n",
  45. stor: "STOR " + "P" * buffer + "\r\n",
  46. top: "TOP " + "Q" * buffer + "\r\n",
  47. uidl: "UIDL " + "R" * buffer + "\r\n"
  48. }
  49. return points[point] unless point.empty?
  50. points
  51. end
  52. puts "[+] Fuzzing #{@host} on port #{@port}..."
  53. insertion.keys.each do |point|
  54. (1..500).each do |buffer|
  55. puts "[+] Fuzzing #{point.to_s}: #{insertion(point, buffer).size} bytes"
  56. fuzz insertion(point, buffer)
  57. end
  58. end

Note that, this script can be used for other protocols (IMAP, POP3, etc) since it deals with socket!.