module WpVersion::Findable

Public Instance Methods

find(target_uri, wp_content_dir, wp_plugins_dir, versions_xml) click to toggle source

Find the version of the blog designated from target_uri

@param [ URI ] target_uri @param [ String ] wp_content_dir @param [ String ] wp_plugins_dir

@return [ WpVersion ]

# File lib/common/models/wp_version/findable.rb, line 13
def find(target_uri, wp_content_dir, wp_plugins_dir, versions_xml)
  methods.grep(/find_from_/).each do |method|

    if method === :find_from_advanced_fingerprinting
      version = send(method, target_uri, wp_content_dir, wp_plugins_dir, versions_xml)
    else
      version = send(method, target_uri)
    end

    if version
      return new(target_uri, number: version, found_from: method)
    end
  end
  nil
end
version_pattern() click to toggle source

Used to check if the version is correct: must contain at least one dot.

@return [ String ]

# File lib/common/models/wp_version/findable.rb, line 32
def version_pattern
  '([^\r\n"\]+\.[^\r\n"\]+)'
end

Protected Instance Methods

find_from_advanced_fingerprinting(target_uri, wp_content_dir, wp_plugins_dir, versions_xml) click to toggle source

Uses data/wp_versions.xml to try to identify a wordpress version.

It does this by using client side file hashing

/!\ Warning : this method might return false positive if the file used for fingerprinting is part of a theme (they can be updated)

@param [ URI ] target_uri @param [ String ] wp_content_dir @param [ String ] wp_plugins_dir @param [ String ] versions_xml The path to the xml containing all versions

@return [ String ] The version number

# File lib/common/models/wp_version/findable.rb, line 153
def find_from_advanced_fingerprinting(target_uri, wp_content_dir, wp_plugins_dir, versions_xml)
  xml     = xml(versions_xml)

  # This wp_item will take care of encoding the path

  # and replace variables like $wp-content$ & $wp-plugins$

  wp_item = WpItem.new(target_uri,
                       wp_content_dir: wp_content_dir,
                       wp_plugins_dir: wp_plugins_dir)

  xml.xpath('//file').each do |node|
    wp_item.path = node.attribute('src').text

    response = Browser.get(wp_item.url)
    md5sum = Digest::MD5.hexdigest(response.body)

    node.search('hash').each do |hash|
      if hash.attribute('md5').text == md5sum
        return hash.search('version').text
      end
    end
  end
  nil
end
find_from_atom_generator(target_uri) click to toggle source

Attempts to find the WordPress version from, the generator tag in the Atom source.

@param [ URI ] target_uri

@return [ String ] The version number

# File lib/common/models/wp_version/findable.rb, line 120
def find_from_atom_generator(target_uri)
  scan_url(
    target_uri,
    %r{<generator uri="http://wordpress.org/" version="#{version_pattern}">WordPress</generator>},
    'feed/atom/'
  )
end
find_from_meta_generator(target_uri) click to toggle source

Attempts to find the wordpress version from, the generator meta tag in the html source.

The meta tag can be removed however it seems, that it is reinstated on upgrade.

@param [ URI ] target_uri

@return [ String ] The version number

# File lib/common/models/wp_version/findable.rb, line 67
def find_from_meta_generator(target_uri)
  scan_url(
    target_uri,
    %r{name="generator" content="wordpress #{version_pattern}"}
  )
end
find_from_rdf_generator(target_uri) click to toggle source

Attempts to find WordPress version from, the generator tag in the RDF feed source.

@param [ URI ] target_uri

@return [ String ] The version number

# File lib/common/models/wp_version/findable.rb, line 94
def find_from_rdf_generator(target_uri)
  scan_url(
    target_uri,
    %r{<admin:generatorAgent rdf:resource="http://wordpress.org/\?v=#{version_pattern}" />},
    'feed/rdf/'
  )
end
find_from_readme(target_uri) click to toggle source

Attempts to find the WordPress version from the readme.html file.

@param [ URI ] target_uri

@return [ String ] The version number

# File lib/common/models/wp_version/findable.rb, line 182
def find_from_readme(target_uri)
  scan_url(
    target_uri,
    %r{<br />\sversion #{version_pattern}},
    'readme.html'
  )
end
find_from_rss_generator(target_uri) click to toggle source

Attempts to find the WordPress version from, the generator tag in the RSS feed source.

@param [ URI ] target_uri

@return [ String ] The version number

# File lib/common/models/wp_version/findable.rb, line 80
def find_from_rss_generator(target_uri)
  scan_url(
    target_uri,
    %r{<generator>http://wordpress.org/\?v=#{version_pattern}</generator>},
    'feed/'
  )
end
find_from_sitemap_generator(target_uri) click to toggle source

Attempts to find the WordPress version from the sitemap.xml file.

See: code.google.com/p/wpscan/issues/detail?id=109

@param [ URI ] target_uri

@return [ String ] The version number

# File lib/common/models/wp_version/findable.rb, line 197
def find_from_sitemap_generator(target_uri)
  scan_url(
    target_uri,
    %r{generator="wordpress/#{version_pattern}"},
    'sitemap.xml'
  )
end
scan_url(target_uri, pattern, path = nil) click to toggle source

Returns the first match of <pattern> in the body of the url

@param [ URI ] target_uri @param [ Regex ] pattern @param [ String ] path

@return [ String ]

# File lib/common/models/wp_version/findable.rb, line 45
def scan_url(target_uri, pattern, path = nil)
  url = path ? target_uri.merge(path).to_s : target_uri.to_s
  response = Browser.get_and_follow_location(url)

  response.body[pattern, 1]
end