Parent

Files

WpEnumerator

Enumerate over a given set of items and check if they exist

Public Class Methods

enumerate(options = {}, items = nil) click to toggle source

Enumerate the given Targets

Attributes

  • targets - targets to enumerate

    • :url - Base URL

    • :wp_content - wp-content directory

    • :path - Path to plugin

  • type - "plugins" or "themes", item to enumerate

  • filename - filename in the data directory with paths

  • show_progress_bar - Show a progress bar during enumeration

# File lib/wpscan/wp_enumerator.rb, line 33
def self.enumerate(options = {}, items = nil)

  WpOptions.check_options(options)

  targets = self.generate_items(options)

  unless items == nil
    items.each do |i|
      targets << i
    end
  end

  found = []
  queue_count = 0
  request_count = 0
  enum_browser = Browser.instance
  enum_hydra = enum_browser.hydra
  enumerate_size = targets.size

  targets.each do |target|
    # Timthumb files have no /timthumbs/ directory
    unless options[:type] =~ /timthumbs/
      target[:path] = "#{options[:type]}/#{target[:path]}"
    end
    url = "#{target[:url]}#{target[:wp_content_dir]}/#{target[:path]}"

    request = enum_browser.forge_request(url, { :cache_timeout => 0, :follow_location => true })
    request_count += 1

    request.on_complete do |response|
      if options[:show_progress_bar]
        print "\rChecking for #{enumerate_size} total #{options[:type]}... #{(request_count * 100) / enumerate_size}% complete."
      end
      if WpTarget.valid_response_codes.include?(response.code)
        if Digest::MD5.hexdigest(response.body) != options[:error_404_hash]
          found << target
        end
      end
    end

    enum_hydra.queue(request)
    queue_count += 1

    if queue_count == enum_browser.max_threads
      enum_hydra.run
      queue_count = 0
    end
  end

  enum_hydra.run
  found
end

Protected Class Methods

generate_items(options = {}) click to toggle source
# File lib/wpscan/wp_enumerator.rb, line 88
def self.generate_items(options = {})
  only_vulnerable   = options[:only_vulnerable_ones]
  file              = options[:file]
  vulns_file        = options[:vulns_file]
  wp_content_dir    = options[:wp_content_dir]
  url               = options[:url]
  type              = options[:type]
  targets_url       = []

  if only_vulnerable == false
    # Open and parse the 'most popular' plugin list...
    File.open(file, 'r') do |f|
      f.readlines.collect do |line|
        targets_url << {
            :url            => url,
            :path           => line.strip,
            :wp_content_dir => wp_content_dir,
            :name           => File.dirname(line.strip)
        }
      end
    end
  end

  # Timthumbs have no XML file
  unless type =~ /timthumbs/
    xml = Nokogiri::XML(File.open(vulns_file)) do |config|
      config.noblanks
    end

    # We check if the plugin name from the plugin_vulns_file is already in targets, otherwise we add it
    xml.xpath(options[:vulns_xpath_2]).each do |node|
      name = node.attribute("name").text
      targets_url << {
          :url            => url,
          :path           => name,
          :wp_content_dir => wp_content_dir,
          :name           => name
      }
      end
  end

  targets_url.flatten!
  targets_url.uniq!
  # randomize the plugins array to *maybe* help in some crappy IDS/IPS/WAF detection
  targets_url.sort_by! { rand }
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.