Module: WpItems::Detectable

Included in:
WpItems
Defined in:
lib/common/collections/wp_items/detectable.rb

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Instance Attribute Details

- (Object) item_xpath (readonly)

Returns the value of attribute item_xpath



6
7
8
# File 'lib/common/collections/wp_items/detectable.rb', line 6

def item_xpath
  @item_xpath
end

- (Object) vulns_file (readonly)

Returns the value of attribute vulns_file



6
7
8
# File 'lib/common/collections/wp_items/detectable.rb', line 6

def vulns_file
  @vulns_file
end

Instance Method Details

- (WpItems) aggressive_detection(wp_target, options = {})

Parameters:

  • wp_target (WpTarget)
  • options (Hash) (defaults to: {})

Options Hash (options):

  • :show_progression (Boolean)

    Whether or not output the progress bar

  • :only_vulnerable (Boolean)

    Only check for vulnerable items

  • :exclude_content (String)

Returns:



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/common/collections/wp_items/detectable.rb', line 15

def aggressive_detection(wp_target, options = {})
  browser          = Browser.instance
  hydra            = browser.hydra
  targets          = targets_items(wp_target, options)
  progress_bar     = progress_bar(targets.size, options)
  exist_options    = {
    error_404_hash:  wp_target.error_404_hash,
    homepage_hash:   wp_target.homepage_hash,
    exclude_content: options[:exclude_content] ? %r{#{options[:exclude_content]}} : nil
  }

  # If we only want the vulnerable ones, the passive detection is ignored
  # Otherwise, a passive detection is performed, and results will be merged
  results = options[:only_vulnerable] ? new : passive_detection(wp_target, options)

  targets.each do |target_item|
    request = browser.forge_request(target_item.url, request_params)

    request.on_complete do |response|
      progress_bar.progress += 1 if options[:show_progression]

      if target_item.exists?(exist_options, response)
        if !results.include?(target_item)
          results << target_item
        end
      end
    end

    hydra.queue(request)
  end

  hydra.run
  results.sort!
  results # can't just return results.sort because the #sort returns an array, and we want a WpItems
end

- (WpItem) create_item(klass, name, wp_target, vulns_file = nil) (protected)

Parameters:

  • klass (Class)
  • name (String)
  • wp_target (WpTarget)
  • [ (Hash)

    a customizable set of options

Returns:



154
155
156
157
158
159
160
161
162
# File 'lib/common/collections/wp_items/detectable.rb', line 154

def create_item(klass, name, wp_target, vulns_file = nil)
  klass.new(
    wp_target.uri,
    name:           name,
    vulns_file:     vulns_file,
    wp_content_dir: wp_target.wp_content_dir,
    wp_plugins_dir: wp_target.wp_plugins_dir
  )
end

- (Class) item_class (protected)

Returns:

  • (Class)


187
188
189
# File 'lib/common/collections/wp_items/detectable.rb', line 187

def item_class
  Object.const_get(self.to_s.gsub(/.$/, ''))
end

- (WpItems) passive_detection(wp_target, options = {})

Parameters:

  • wp_target (WpTarget)
  • options (Hash) (defaults to: {})

Returns:



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/common/collections/wp_items/detectable.rb', line 72

def passive_detection(wp_target, options = {})
  results      = new
  item_class   = self.item_class
  type         = self.to_s.gsub(/Wp/, '').downcase
  response     = Browser.get(wp_target.url)
  item_options = {
    wp_content_dir: wp_target.wp_content_dir,
    wp_plugins_dir: wp_target.wp_plugins_dir,
    vulns_file:     self.vulns_file
  }

  regex1 = %r{(?:[^=:]+)\s?(?:=|:)\s?(?:"|')[^"']+\\?/}
  regex2 = %r{\\?/}
  regex3 = %r{\\?/([^/\\"']+)\\?(?:/|"|')}

  names = response.body.scan(/#{regex1}#{Regexp.escape(wp_target.wp_content_dir)}#{regex2}#{Regexp.escape(type)}#{regex3}/i)

  names.flatten.uniq.each do |name|
    results << item_class.new(wp_target.uri, item_options.merge(name: name))
  end

  results.sort!
  results
end

- (ProgressBar) progress_bar(targets_size, options)

:nocov:

Parameters:

  • targets_size (Integer)
  • options (Hash)

Returns:

  • (ProgressBar)


56
57
58
59
60
61
62
63
64
65
# File 'lib/common/collections/wp_items/detectable.rb', line 56

def progress_bar(targets_size, options)
  if options[:show_progression]
    ProgressBar.create(
      format: '%t %a <%B> (%c / %C) %P%% %e',
      title: '  ', # Used to craete a left margin
      length: 120,
      total: targets_size
    )
  end
end

- (Hash) request_params (protected)

The default request parameters

Returns:

  • (Hash)


102
# File 'lib/common/collections/wp_items/detectable.rb', line 102

def request_params; { cache_ttl: 0, followlocation: true } end

- (Array<WpItem>) targets_items(wp_target, options = {}) (protected)

Parameters:

  • wp_target (WpTarget)
  • options (options) (defaults to: {})

Options Hash (options):

  • :only_vulnerable (Boolean)
  • :file (String)

    The path to the file containing the targets

Returns:



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/common/collections/wp_items/detectable.rb', line 110

def targets_items(wp_target, options = {})
  item_class = self.item_class
  vulns_file = self.vulns_file

  targets = vulnerable_targets_items(wp_target, item_class, vulns_file)

  unless options[:only_vulnerable]
    unless options[:file]
      raise 'A file must be supplied'
    end

    targets += targets_items_from_file(options[:file], wp_target, item_class, vulns_file)
  end

  targets.uniq! { |t| t.name }
  targets.sort_by { rand }
end

- (WpItem) targets_items_from_file(file, wp_target, item_class, vulns_file) (protected)

Parameters:

  • file (String)
  • wp_target (WpTarget)
  • item_class (Class)
  • vulns_file (String)

Returns:



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/common/collections/wp_items/detectable.rb', line 170

def targets_items_from_file(file, wp_target, item_class, vulns_file)
  targets = []

  File.open(file, 'r') do |f|
    f.readlines.collect do |item_name|
      targets << create_item(
        item_class,
        item_name.strip,
        wp_target,
        vulns_file
      )
    end
  end
  targets
end

- (Array<WpItem>) vulnerable_targets_items(wp_target, item_class, vulns_file) (protected)

Parameters:

  • wp_target (WpTarget)
  • item_class (Class)
  • vulns_file (String)

Returns:



133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/common/collections/wp_items/detectable.rb', line 133

def vulnerable_targets_items(wp_target, item_class, vulns_file)
  targets = []
  xml     = xml(vulns_file)

  xml.xpath(item_xpath).each do |node|
    targets << create_item(
      item_class,
      node.attribute('name').text,
      wp_target,
      vulns_file
    )
  end
  targets
end