Class: CMSScanner::Target

Inherits:
WebSite
  • Object
show all
Includes:
Server::Generic
Defined in:
lib/cms_scanner/target.rb,
lib/cms_scanner/target/scope.rb,
lib/cms_scanner/target/hashes.rb,
lib/cms_scanner/target/server/iis.rb,
lib/cms_scanner/target/platform/php.rb,
lib/cms_scanner/target/server/apache.rb,
lib/cms_scanner/target/server/generic.rb

Overview

Scope system logic

Defined Under Namespace

Modules: Platform, Server Classes: Scope

Instance Attribute Summary

Attributes inherited from WebSite

#opts, #uri

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Server::Generic

#headers, #server

Methods inherited from WebSite

#access_forbidden?, #http_auth?, #online?, #proxy_auth?, #redirection, #url, #url=

Constructor Details

#initialize(url, opts = {}) ⇒ Target

Returns a new instance of Target.

Parameters:

  • url (String)
  • opts (Hash) (defaults to: {})

Options Hash (opts):



15
16
17
18
19
20
# File 'lib/cms_scanner/target.rb', line 15

def initialize(url, opts = {})
  super(url, opts)

  scope << uri.host
  [*opts[:scope]].each { |s| scope << s }
end

Class Method Details

.page_hash(page) ⇒ String

Note:

Comments are deleted to avoid cache generation details

Returns The md5sum of the page.

Parameters:

Returns:

  • (String)

    The md5sum of the page



9
10
11
12
13
# File 'lib/cms_scanner/target/hashes.rb', line 9

def self.page_hash(page)
  page = NS::Browser.get(page, followlocation: true) unless page.is_a?(Typhoeus::Response)

  Digest::MD5.hexdigest(page.body.gsub(/<!--.*?-->/m, ''))
end

Instance Method Details

#comments_from_page(pattern, page = nil) {|MatchData, Nokogiri::XML::Comment| ... } ⇒ Array<Array<MatchData, Nokogiri::XML::Comment>>

Parameters:

Yields:

  • (MatchData, Nokogiri::XML::Comment)

Returns:

  • (Array<Array<MatchData, Nokogiri::XML::Comment>>)


34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/cms_scanner/target.rb', line 34

def comments_from_page(pattern, page = nil)
  page    = NS::Browser.get(url(page)) unless page.is_a?(Typhoeus::Response)
  matches = []

  page.html.xpath('//comment()').each do |node|
    next unless node.text.to_s.strip =~ pattern

    yield Regexp.last_match, node if block_given?

    matches << [Regexp.last_match, node]
  end

  matches
end

#error_404_hashString

Note:

This is used to detect potential custom 404 responding with a 200

Returns The hash of a 404.

Returns:

  • (String)

    The hash of a 404



22
23
24
# File 'lib/cms_scanner/target/hashes.rb', line 22

def error_404_hash
  @error_404_hash ||= self.class.page_hash(non_existant_page_url)
end

#homepage_hashString

Returns The hash of the homepage.

Returns:

  • (String)

    The hash of the homepage



16
17
18
# File 'lib/cms_scanner/target/hashes.rb', line 16

def homepage_hash
  @homepage_hash ||= self.class.page_hash(url)
end

#homepage_or_404?(page) ⇒ Boolean

Returns Wether or not the page is a the homepage or a 404 based on its md5sum.

Parameters:

Returns:

  • (Boolean)

    Wether or not the page is a the homepage or a 404 based on its md5sum



33
34
35
36
37
# File 'lib/cms_scanner/target/hashes.rb', line 33

def homepage_or_404?(page)
  md5sum = self.class.page_hash(page)

  md5sum == homepage_hash || md5sum == error_404_hash
end

#in_scope?(url) ⇒ Boolean

Returns true if the url given is in scope.

Parameters:

  • url (String)

    An absolute URL

Returns:

  • (Boolean)

    true if the url given is in scope



12
13
14
15
16
# File 'lib/cms_scanner/target/scope.rb', line 12

def in_scope?(url)
  scope.include?(Addressable::URI.parse(url.strip).host)
rescue
  false
end

#in_scope_urls(res, xpath = '//link|//script|//style|//img|//a', attributes = %w(href src)) {|String, Nokogiri::XML::Element| ... } ⇒ Array<String>

Returns The in scope absolute URLs detected in the response’s body.

Parameters:

  • res (Typhoeus::Response)
  • xpath (String) (defaults to: '//link|//script|//style|//img|//a')
  • attributes (Array<String>) (defaults to: %w(href src))

Yields:

  • (String, Nokogiri::XML::Element)

    The in scope url and its associated tag

Returns:

  • (Array<String>)

    The in scope absolute URLs detected in the response’s body



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/cms_scanner/target/scope.rb', line 25

def in_scope_urls(res, xpath = '//link|//script|//style|//img|//a', attributes = %w(href src))
  found = []

  res.html.xpath(xpath).each do |tag|
    attributes.each do |attribute|
      attr_value = tag[attribute]

      next unless attr_value && !attr_value.empty?

      url = uri.join(attr_value.strip).to_s

      next unless in_scope?(url)

      yield url, tag if block_given? && !found.include?(url)

      found << url
    end
  end

  found.uniq
end

#interesting_files(opts = {}) ⇒ Findings

Parameters:

  • opts (Hash) (defaults to: {})

Returns:

  • (Findings)


25
26
27
# File 'lib/cms_scanner/target.rb', line 25

def interesting_files(opts = {})
  @interesting_files ||= NS::Finders::InterestingFiles::Base.find(self, opts)
end

#non_existant_page_urlString

Returns The URL of an unlikely existant page.

Returns:

  • (String)

    The URL of an unlikely existant page



27
28
29
# File 'lib/cms_scanner/target/hashes.rb', line 27

def non_existant_page_url
  uri.join(Digest::MD5.hexdigest(rand(999_999_999).to_s) + '.html').to_s
end

#scopeArray<PublicSuffix::Domain, String>

Returns:



5
6
7
# File 'lib/cms_scanner/target/scope.rb', line 5

def scope
  @scope ||= Scope.new
end