Class: WPScan::WpItem

Inherits:
Object
  • Object
show all
Includes:
CMSScanner::Target::Platform::PHP, CMSScanner::Target::Server::Generic, Finders::Finding, Vulnerable
Defined in:
app/models/wp_item.rb

Overview

WpItem (superclass of Plugin & Theme)

Direct Known Subclasses

DB::Plugin, DB::Theme, Plugin, Theme

Constant Summary collapse

READMES =
%w[readme.txt README.txt Readme.txt ReadMe.txt README.TXT readme.TXT].freeze
CHANGELOGS =
%w[changelog.txt Changelog.txt ChangeLog.txt CHANGELOG.txt].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Vulnerable

#vulnerable?

Constructor Details

#initialize(name, target, opts = {}) ⇒ WpItem

Returns a new instance of WpItem.

Parameters:

  • name (String)

    The plugin/theme name

  • target (Target)

    The targeted blog

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

Options Hash (opts):

  • :mode (Symbol)

    The detection mode to use

  • :version_detection (Hash)

    The options to use when looking for the version

  • :url (String)

    The URL of the item



20
21
22
23
24
25
26
27
28
29
# File 'app/models/wp_item.rb', line 20

def initialize(name, target, opts = {})
  @name           = URI.decode(name)
  @target         = target
  @uri            = Addressable::URI.parse(opts[:url]) if opts[:url]

  @detection_opts = { mode: opts[:mode] }
  @version_detection_opts = opts[:version_detection] || {}

  parse_finding_options(opts)
end

Instance Attribute Details

#db_dataObject (readonly)

Returns the value of attribute db_data.



12
13
14
# File 'app/models/wp_item.rb', line 12

def db_data
  @db_data
end

#detection_optsObject (readonly)

Returns the value of attribute detection_opts.



12
13
14
# File 'app/models/wp_item.rb', line 12

def detection_opts
  @detection_opts
end

#nameObject (readonly)

Returns the value of attribute name.



12
13
14
# File 'app/models/wp_item.rb', line 12

def name
  @name
end

#targetObject (readonly)

Returns the value of attribute target.



12
13
14
# File 'app/models/wp_item.rb', line 12

def target
  @target
end

#uriObject (readonly)

Returns the value of attribute uri.



12
13
14
# File 'app/models/wp_item.rb', line 12

def uri
  @uri
end

#version_detection_optsObject (readonly)

Returns the value of attribute version_detection_opts.



12
13
14
# File 'app/models/wp_item.rb', line 12

def version_detection_opts
  @version_detection_opts
end

Instance Method Details

#==(other) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
100
101
# File 'app/models/wp_item.rb', line 97

def ==(other)
  return false unless self.class == other.class

  name == other.name
end

#changelog_urlString, false

Returns The changelog urr if found.

Returns:

  • (String, false)

    The changelog urr if found



126
127
128
129
130
131
132
133
134
135
136
# File 'app/models/wp_item.rb', line 126

def changelog_url
  return if detection_opts[:mode] == :passive

  if @changelog_url.nil?
    CHANGELOGS.each do |path|
      return @changelog_url = url(path) if Browser.get(url(path)).code == 200
    end
  end

  @changelog_url
end

#classify_nameSymbol

Returns The Class name associated to the item name.

Returns:

  • (Symbol)

    The Class name associated to the item name



108
109
110
# File 'app/models/wp_item.rb', line 108

def classify_name
  name.to_s.tr('-', '_').camelize.to_s.to_sym
end

#directory_listing?(path = nil, params = {}) ⇒ Boolean

Parameters:

  • path (String) (defaults to: nil)
  • params (Hash) (defaults to: {})

    The request params

Returns:

  • (Boolean)


142
143
144
145
# File 'app/models/wp_item.rb', line 142

def directory_listing?(path = nil, params = {})
  return if detection_opts[:mode] == :passive
  super(path, params)
end

#error_log?(path = 'error_log', params = {}) ⇒ Boolean

Parameters:

  • path (String) (defaults to: 'error_log')
  • params (Hash) (defaults to: {})

    The request params

Returns:

  • (Boolean)


151
152
153
154
# File 'app/models/wp_item.rb', line 151

def error_log?(path = 'error_log', params = {})
  return if detection_opts[:mode] == :passive
  super(path, params)
end

#last_updatedString

Returns:

  • (String)


68
69
70
# File 'app/models/wp_item.rb', line 68

def last_updated
  @last_updated ||= db_data['last_updated']
end

#latest_versionString

Returns:

  • (String)


57
58
59
# File 'app/models/wp_item.rb', line 57

def latest_version
  @latest_version ||= db_data['latest_version'] ? WPScan::Version.new(db_data['latest_version']) : nil
end

#outdated?Boolean

Returns:

  • (Boolean)


73
74
75
76
77
78
79
# File 'app/models/wp_item.rb', line 73

def outdated?
  @outdated ||= if version && latest_version
                  version < latest_version
                else
                  false
                end
end

#popular?Boolean

Not used anywhere ATM

Returns:

  • (Boolean)


63
64
65
# File 'app/models/wp_item.rb', line 63

def popular?
  @popular ||= db_data['popular']
end

#readme_urlString

Returns The readme url if found.

Returns:

  • (String)

    The readme url if found



113
114
115
116
117
118
119
120
121
122
123
# File 'app/models/wp_item.rb', line 113

def readme_url
  return if detection_opts[:mode] == :passive

  if @readme_url.nil?
    READMES.each do |path|
      return @readme_url = url(path) if Browser.get(url(path)).code == 200
    end
  end

  @readme_url
end

#to_sObject



103
104
105
# File 'app/models/wp_item.rb', line 103

def to_s
  name
end

#url(path = nil) ⇒ String

URI.encode is preferered over Addressable::URI.encode as it will encode leading # character: URI.encode(‘#t#’) => %23t%23 Addressable::URI.encode(‘#t#’) => #t%23

Parameters:

  • path (String) (defaults to: nil)

    Optional path to merge with the uri

Returns:

  • (String)


89
90
91
92
93
94
# File 'app/models/wp_item.rb', line 89

def url(path = nil)
  return unless @uri
  return @uri.to_s unless path

  @uri.join(URI.encode(path)).to_s
end

#vulnerabilitiesArray<Vulnerabily>

Returns:

  • (Array<Vulnerabily>)


32
33
34
35
36
37
38
39
40
41
42
43
# File 'app/models/wp_item.rb', line 32

def vulnerabilities
  return @vulnerabilities if @vulnerabilities

  @vulnerabilities = []

  [*db_data['vulnerabilities']].each do |json_vuln|
    vulnerability = Vulnerability.load_from_json(json_vuln)
    @vulnerabilities << vulnerability if vulnerable_to?(vulnerability)
  end

  @vulnerabilities
end

#vulnerable_to?(vuln) ⇒ Boolean

Checks if the wp_item is vulnerable to a specific vulnerability

Parameters:

  • vuln (Vulnerability)

    Vulnerability to check the item against

Returns:

  • (Boolean)


50
51
52
53
54
# File 'app/models/wp_item.rb', line 50

def vulnerable_to?(vuln)
  return true unless version && vuln && vuln.fixed_in && !vuln.fixed_in.empty?

  version < vuln.fixed_in
end