# 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_links_opml(target_uri) click to toggle source

Attempts to find the WordPress version from the p-links-opml.php file.

@param [ URI ] target_uri

@return [ String ] The version number

    # File lib/common/models/wp_version/findable.rb, line 210
    def find_from_links_opml(target_uri)
      scan_url(
        target_uri,
        %r{generator="wordpress/#{version_pattern}"},
        'wp-links-opml.php'
      )
    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