class ViolentRuby::VulnerabilityScanner

Vulnerability Scanner provides a friendly interface to easily manage banner grabbing targets to match a list of +known vulnerable services+ that we want to identify. @author Kent 'picat' Gruber

Create a new Vulnerability Scanner

The Vulnerability Scanner scanner class can be setup in a few flexible ways.

@example Provide no targets, ip addresses or even a file.

scanner = ViolentRuby::VulnerabilityScanner.new

@example Provide targets.

ipaddrs = ['192.168.0.2', '192.168.0.3', '192.168.0.4']
scanner = ViolentRuby::VulnerabilityScanner.new(targets: ipaddrs)

@example Provide a file of known vulnerabilities.

scanner = ViolentRuby::VulnerabilityScanner.new(known_vulnerabilities: "vuln_banners.txt")

@example Just set targets and provide a file later.

scanner = ViolentRuby::VulnerabilityScanner.new
['192.168.0.2', '192.168.0.3'].each do |ip|
  scanner.targets << ip
end
scanner.targets
# => ['192.168.0.2', '192.168.0.3']
File.readlines("vuln_banners.txt").map(&:strip).each |banner|
  scanner.known_vulnerabilities << banner
end
# => ['MS-IIS WEB SERVER 4.0', 'MS-IIS WEB SERVER 5.0']
scanner.scan

Banner Grabbing

The Vulnerability Scanner provides a simple banner grabbing method which can be used.

@example Connect to 192.168.0.2 on port 8080

scanner = ViolentRuby::VulnerabilityScanner.new

# If no banner, or hit timeout.
scanner.retrieve_banner('192.168.0.2', 8080)
# => false

# If banner exists.
scanner.retrieve_banner('192.168.0.2', 80)
# => "MS-IIS WEB SERVER 5.0"

@example Connect to 192.168.0.2 on port 8080, trying for 10 seconds

scanner = ViolentRuby::VulnerabilityScanner.new
scanner.retrieve_banner('192.168.0.2', 8080, 10)

@example Connect to 192.168.0.2 on port 8080, with a given block

scanner = ViolentRuby::VulnerabilityScanner.new
scanner.retrieve_banner('192.168.0.2', 8080) do |banner|
  # do something with banner ( false if none found )
  if banner
    puts "Banner found: " + banner
  else
    puts "Banner not found."
  end
end

Example Usage

The VulnerabilityScanner is meant to be easy and flexible to use.

@example Basic

require 'violent_ruby'
config  = { targets: ['192.168.0.2', '192.168.0.3' ], known_vulnerabilities: 'vulns.txt' }
scanner = ViolentRuby::VulnerabilityScanner.new(config)
scanner.scan

@example Advanced (sort'a)

require 'violent_ruby'
scanner = ViolentRuby::VulnerabilityScanner.new
scanner.targets = ['192.168.0.2', '192.168.0.3' ]
scanner.known_vulnerabilities = 'vulns.txt'
scanner.scan(port: 8080)

Attributes

known_vulnerabilities[RW]

@attr [Array<String>] known_vulnerabilities List of known vulnerabilities.

targets[RW]

@attr [Array<String>] targets List of target ip addresses.

Public Class Methods

new(args = {}) click to toggle source

Create a new instance of the vulnerability scanner.

@param [Hash] args The options to create a new Vulnerability Scanner. Very optional. @param args [Array<String>] :targets The targets to work with. @param args [Array<String>] :known_vulnerabilities A file containing known vulnerabilities. @return [VulnerabilityScanner]

# File lib/violent_ruby/vulnerability_scanner/vulnerability_scanner.rb, line 93
def initialize(args = {})
  @targets                   = []
  @known_vulnerabilities     = [] 
  self.targets               = args[:targets] if args[:targets]
  self.known_vulnerabilities = args[:known_vulnerabilities] if args[:known_vulnerabilities]
end

Public Instance Methods

check_vulnerabilities(banner, file = false) click to toggle source

Check if a given banner is included in a given file which should contain a list of vulnerable banners to match against in order to determine vulnerabilities.

@param [String] banner Target banner to check. @param optional [String] file A file containing vulnerable banners. @return [Boolean]

# File lib/violent_ruby/vulnerability_scanner/vulnerability_scanner.rb, line 129
def check_vulnerabilities(banner, file = false)
  if file
    File.readlines(file).map(&:strip).each do |line|
      return true if line.match?(banner)
    end
  else
    @known_vulnerabilities.each do |vulnerability|
      return true if vulnerability.match?(banner)
    end
  end
  false
end
Also aliased as: vulnerable?
known_vulnerabilities=(args) click to toggle source

@param [String,Array<String>] args Either a banner string or an array of banner strings. @return [void]

# File lib/violent_ruby/vulnerability_scanner/vulnerability_scanner.rb, line 183
def known_vulnerabilities=(args)
  if File.readable?(args)
    File.readlines(args[:known_vulnerabilities]).map(&:strip).each do |line|
      @known_vulnerabilities << line
    end 
  elsif args.is_a? String
    @known_vulnerabilities << args
  elsif args.is_a? Array
    args.each { |vulnerability| @known_vulnerabilities << vulnerability }
  end
end
retrieve_banner(ip, port, seconds = 2) { |banner| ... } click to toggle source

Retrieve a banner from a given ip and port for a given ammount of seconds, or default for two seconds.

@param [String] ip Target ip address. @param [Integer] port Target port number. @param [Integer] seconds Timeout value. @return [String,Boolean]

# File lib/violent_ruby/vulnerability_scanner/vulnerability_scanner.rb, line 107
def retrieve_banner(ip, port, seconds = 2)
  banner = false
  Timeout.timeout(seconds) do 
    socket = TCPSocket.new(ip, port)
    banner = socket.recv(1024)
    socket.close
  end
  return false unless banner
  banner.strip!
  yield banner if block_given?
  banner
rescue
  false
end
scan(args = {}) click to toggle source

Do the scanning!

@param [Hash] args Scan arguments. @param args [String] :ip @see handle_ip @param args [Array<String>] :ips @see handle_ip @param args [Integer] :port @see handle_port @param args [Array<Integer>] :ports @see handle_port @param args [String] :file @see handle_file @param args [Integer] :timeout @see handle_timeout @return [void]

# File lib/violent_ruby/vulnerability_scanner/vulnerability_scanner.rb, line 155
def scan(args = {})
  ip_addrs = handle_ip(args)
  ports    = handle_port(args)
  timeout  = handle_timeout(args)
  file     = handle_file(args)
  results  = []
  ip_addrs.each do |ip|
    ports.each do |port|
      retrieve_banner(ip, port, timeout) do |banner|
        results << result(ip, port, banner) if vulnerable?(banner, file)
      end
    end
  end
  results
end
targets=(args) click to toggle source

@param [String,Array<String>] args Either a IP address or an array of IP addresses. @return [void]

# File lib/violent_ruby/vulnerability_scanner/vulnerability_scanner.rb, line 173
def targets=(args)
  if args.is_a? String
    @targets << args
  else args.is_a? Array
    args.each { |target| @targets << target }
  end 
end
vulnerable?(banner, file = false)

Human readable alias.

Private Instance Methods

handle_file(args = {}) click to toggle source

@api private This method manages dealing with handling the file argument for the scan method in a clean manner.

@param [Hash] args @param args [Integer] :file File containing vulnerable banners. @return [String, Boolean]

# File lib/violent_ruby/vulnerability_scanner/vulnerability_scanner.rb, line 267
def handle_file(args = {})
  if args[:file]
    args[:file]
  else
    false
  end
end
handle_ip(args = {}) click to toggle source

@api private This method manages dealing with handling the ip arguments for the scan method in a clean manner.

@param [Hash] args @param args [String] :ip Single ip address. @param args [Array<String>] :ips Multiple ip addresses. @return [Array<String>]

# File lib/violent_ruby/vulnerability_scanner/vulnerability_scanner.rb, line 217
def handle_ip(args = {})
  if args[:ip]
    [args[:ip]]
  elsif args[:ips]
    args[:ips]
  else
    @targets
  end
end
handle_port(args = {}) click to toggle source

@api private This method manages dealing with handling the port arguments for the scan method in a clean manner.

@param [Hash] args @param args [String] :port Single port. @param args [Array<String>] :ips Multiple ports. @return [Array<Integer>]

# File lib/violent_ruby/vulnerability_scanner/vulnerability_scanner.rb, line 235
def handle_port(args = {})
  if args[:port]
    [args[:port]]
  elsif args[:ports]
    args[:ports]
  else
    [21, 22, 25, 80, 110, 443]
  end
end
handle_timeout(args = {}) click to toggle source

@api private This method manages dealing with handling the timeout argument for the scan method in a clean manner.

@param [Hash] args @param args [Integer] :timeout Timeout in seconds. @return [Integer]

# File lib/violent_ruby/vulnerability_scanner/vulnerability_scanner.rb, line 252
def handle_timeout(args = {})
  if args[:timeout]
    args[:timeout]
  else
    2
  end
end
result(ip, port, banner) click to toggle source

@api private This method manages what is done with the result once we know a vulnerable banner is found.

@param [String] ip @param [Integer] port @param [String] banner @return [Hash]

# File lib/violent_ruby/vulnerability_scanner/vulnerability_scanner.rb, line 205
def result(ip, port, banner)
  {ip: ip, port: port, banner: banner}
end