wpscan 3.7.8 → 3.7.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 419360bc6185b4a079466de1af1a4fd7d0a3ceca0c53b80d31c1f75febf30f0b
4
- data.tar.gz: 5ae9c3860d72442cf5ed6dc28b49370dafcd1895ea7ca09e6510890ffebdc583
3
+ metadata.gz: a8351294d3eedeff4b00824a523541cac828c5d43a1852900e606dc22c7676f5
4
+ data.tar.gz: d589d01854ee40dd87e073ab636745607434d7fdd1f3e48c269276c68a3fe918
5
5
  SHA512:
6
- metadata.gz: e59110ef74710b0d6c51865855f83b2581a9e0387b70b4503f1da78fac0deca5768f11212717c5800a40c38ae7b76a86e66e72d63e0af58d8b5b726000ef742e
7
- data.tar.gz: 631b185df19662aabe35a97dd326f5a84fa0db16372f60b71a19e59b64c614631dfea22e5630266bd7b129f33f4593820d3d9a6d79f4e10a8cefafbb8bb71493
6
+ metadata.gz: 6845cdd64b1f715a80b3c932da5e072b465dea4d1af6ec5db67de2585ce8f3366c19ba40071a0de7a6887c79b5db87631630fbad5df4e9de174e29d84afdb5f5
7
+ data.tar.gz: 3bb25f129cb00c8a0087d32f88c1423de1bc2d014268d45956e7052134242c3fadeba08cdb183596ce556c76036a08534efc8ef7395a2023d0d614d49185af7c
data/README.md CHANGED
@@ -15,7 +15,7 @@
15
15
 
16
16
  <p align="center">
17
17
  <a href="https://badge.fury.io/rb/wpscan" target="_blank"><img src="https://badge.fury.io/rb/wpscan.svg"></a>
18
- <a href="https://travis-ci.org/wpscanteam/wpscan" target="_blank"><img src="https://travis-ci.org/wpscanteam/wpscan.svg?branch=master"></a>
18
+ <a href="https://github.com/wpscanteam/wpscan/actions?query=workflow%3ABuild" target="_blank"><img src="https://github.com/wpscanteam/wpscan/workflows/Build/badge.svg"></a>
19
19
  <a href="https://codeclimate.com/github/wpscanteam/wpscan" target="_blank"><img src="https://codeclimate.com/github/wpscanteam/wpscan/badges/gpa.svg"></a>
20
20
  </p>
21
21
 
@@ -18,9 +18,7 @@ module WPScan
18
18
  target.content_dir = ParsedCli.wp_content_dir if ParsedCli.wp_content_dir
19
19
  target.plugins_dir = ParsedCli.wp_plugins_dir if ParsedCli.wp_plugins_dir
20
20
 
21
- return if target.content_dir
22
-
23
- raise Error::WpContentDirNotDetected
21
+ raise Error::WpContentDirNotDetected unless target.content_dir
24
22
  end
25
23
  end
26
24
  end
@@ -9,7 +9,7 @@ module WPScan
9
9
  def passive(_opts = {})
10
10
  pattern = %r{#{target.content_dir}/mu\-plugins/}i
11
11
 
12
- target.in_scope_uris(target.homepage_res) do |uri|
12
+ target.in_scope_uris(target.homepage_res, '(//@href|//@src)[contains(., "mu-plugins")]') do |uri|
13
13
  next unless uri.path&.match?(pattern)
14
14
 
15
15
  url = target.url('wp-content/mu-plugins/')
@@ -20,7 +20,7 @@ module WPScan
20
20
  end
21
21
 
22
22
  def passive_from_css_href(res, opts)
23
- target.in_scope_uris(res, '//style/@src|//link/@href') do |uri|
23
+ target.in_scope_uris(res, '//link/@href[contains(., "style.css")]') do |uri|
24
24
  next unless uri.path =~ %r{/themes/([^\/]+)/style.css\z}i
25
25
 
26
26
  return create_theme(Regexp.last_match[1], uri.to_s, opts)
@@ -71,11 +71,13 @@ module WPScan
71
71
  return username, 'Display Name', 50 if username
72
72
  end
73
73
 
74
- # @param [ String ] url
74
+ # @param [ String, Addressable::URI ] uri
75
75
  #
76
76
  # @return [ String, nil ]
77
- def username_from_author_url(url)
78
- url[%r{/author/([^/\b]+)/?}i, 1]
77
+ def username_from_author_url(uri)
78
+ uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI)
79
+
80
+ uri.path[%r{/author/([^/\b]+)/?}i, 1]
79
81
  end
80
82
 
81
83
  # @param [ Typhoeus::Response ] res
@@ -83,12 +85,12 @@ module WPScan
83
85
  # @return [ String, nil ] The username found
84
86
  def username_from_response(res)
85
87
  # Permalink enabled
86
- target.in_scope_uris(res, '//link/@href|//a/@href') do |uri|
87
- username = username_from_author_url(uri.to_s)
88
+ target.in_scope_uris(res, '//@href[contains(., "author/")]') do |uri|
89
+ username = username_from_author_url(uri)
88
90
  return username if username
89
91
  end
90
92
 
91
- # No permalink
93
+ # No permalink, TODO Maybe use xpath to extract the classes ?
92
94
  res.body[/<body class="archive author author-([^\s]+)[ "]/i, 1]
93
95
  end
94
96
 
@@ -45,7 +45,7 @@ module WPScan
45
45
  def potential_usernames(res)
46
46
  usernames = []
47
47
 
48
- target.in_scope_uris(res, '//a/@href') do |uri, node|
48
+ target.in_scope_uris(res, '//a/@href[contains(., "author")]') do |uri, node|
49
49
  if uri.path =~ %r{/author/([^/\b]+)/?\z}i
50
50
  usernames << [Regexp.last_match[1], 'Author Pattern', 100]
51
51
  elsif /author=[0-9]+/.match?(uri.query)
@@ -8,11 +8,15 @@ module WPScan
8
8
  # @param [ String ] type plugins / themes
9
9
  # @param [ Boolean ] uniq Wether or not to apply the #uniq on the results
10
10
  #
11
- # @return [Array<String> ] The plugins/themes detected in the href, src attributes of the homepage
11
+ # @return [ Array<String> ] The plugins/themes detected in the href, src attributes of the page
12
12
  def items_from_links(type, uniq = true)
13
13
  found = []
14
+ xpath = format(
15
+ '(//@href|//@src|//@data-src)[contains(., "%s")]',
16
+ type == 'plugins' ? target.plugins_dir : target.content_dir
17
+ )
14
18
 
15
- target.in_scope_uris(page_res) do |uri|
19
+ target.in_scope_uris(page_res, xpath) do |uri|
16
20
  next unless uri.to_s =~ item_attribute_pattern(type)
17
21
 
18
22
  slug = Regexp.last_match[1]&.strip
@@ -67,13 +67,13 @@ module WPScan
67
67
  # @return [ Hash ] The params for Typhoeus::Request
68
68
  # @note Those params can't be overriden by CLI options
69
69
  def request_params
70
- @request_params ||= {
70
+ @request_params ||= Browser.instance.default_connect_request_params.merge(
71
71
  timeout: 600,
72
72
  connecttimeout: 300,
73
73
  accept_encoding: 'gzip, deflate',
74
74
  cache_ttl: 0,
75
- headers: { 'User-Agent' => Browser.instance.default_user_agent, 'Referer' => nil }
76
- }
75
+ headers: { 'User-Agent' => Browser.instance.default_user_agent }
76
+ )
77
77
  end
78
78
 
79
79
  # @return [ String ] The raw file URL associated with the given filename
@@ -85,7 +85,7 @@ module WPScan
85
85
  def remote_file_checksum(filename)
86
86
  url = "#{remote_file_url(filename)}.sha512"
87
87
 
88
- res = Browser.get(url, request_params)
88
+ res = Typhoeus.get(url, request_params)
89
89
  raise Error::Download, res if res.timed_out? || res.code != 200
90
90
 
91
91
  res.body.chomp
@@ -126,7 +126,7 @@ module WPScan
126
126
  file_path = local_file_path(filename)
127
127
  file_url = remote_file_url(filename)
128
128
 
129
- res = Browser.get(file_url, request_params)
129
+ res = Typhoeus.get(file_url, request_params)
130
130
  raise Error::Download, res if res.timed_out? || res.code != 200
131
131
 
132
132
  File.open(file_path, 'wb') { |f| f.write(res.body) }
@@ -23,7 +23,8 @@ module WPScan
23
23
  return {} unless token
24
24
  return {} if path.end_with?('/latest') # Remove this when api/v4 is up
25
25
 
26
- res = Browser.get(uri.join(path), params.merge(request_params))
26
+ # Typhoeus.get is used rather than Browser.get to avoid merging irrelevant params from the CLI
27
+ res = Typhoeus.get(uri.join(path), default_request_params.merge(params))
27
28
 
28
29
  return {} if res.code == 404 # This is for API inconsistencies when dots in path
29
30
  return JSON.parse(res.body) if NON_ERROR_CODES.include?(res.code)
@@ -65,16 +66,14 @@ module WPScan
65
66
  end
66
67
 
67
68
  # @return [ Hash ]
68
- def self.request_params
69
- {
69
+ # @note Those params can not be overriden by CLI options
70
+ def self.default_request_params
71
+ Browser.instance.default_connect_request_params.merge(
70
72
  headers: {
71
- 'Host' => uri.host, # Reset in case user provided a --vhost for the target
72
- 'Referer' => nil, # Removes referer set by the cmsscanner to the target url
73
- 'CF-Connecting-IP' => nil, # Removes in case user provided one for the target
74
73
  'User-Agent' => Browser.instance.default_user_agent,
75
74
  'Authorization' => "Token token=#{token}"
76
75
  }
77
- }
76
+ )
78
77
  end
79
78
  end
80
79
  end
@@ -32,8 +32,12 @@ module WPScan
32
32
 
33
33
  if %i[mixed aggressive].include?(detection_mode)
34
34
  %w[wp-admin/install.php wp-login.php].each do |path|
35
- return true if in_scope_uris(Browser.get_and_follow_location(url(path))).any? do |uri|
36
- WORDPRESS_PATTERN.match?(uri.path)
35
+ res = Browser.get_and_follow_location(url(path))
36
+
37
+ next unless res.code == 200
38
+
39
+ in_scope_uris(res, '//link/@href|//script/@src') do |uri|
40
+ return true if WORDPRESS_PATTERN.match?(uri.path)
37
41
  end
38
42
  end
39
43
  end
@@ -44,7 +48,7 @@ module WPScan
44
48
  # @param [ Typhoeus::Response ] response
45
49
  # @return [ Boolean ]
46
50
  def wordpress_from_meta_comments_or_scripts?(response)
47
- in_scope_uris(response) do |uri|
51
+ in_scope_uris(response, '//link/@href|//script/@src|//img/@src') do |uri|
48
52
  return true if WORDPRESS_PATTERN.match?(uri.path) || WP_JSON_OEMBED_PATTERN.match?(uri.path)
49
53
  end
50
54
 
@@ -100,8 +104,9 @@ module WPScan
100
104
 
101
105
  unless content_dir
102
106
  pattern = %r{https?://s\d\.wp\.com#{WORDPRESS_PATTERN}}i.freeze
107
+ xpath = '(//@href|//@src)[contains(., "wp.com")]'
103
108
 
104
- uris_from_page(homepage_res) do |uri|
109
+ uris_from_page(homepage_res, xpath) do |uri|
105
110
  return true if uri.to_s.match?(pattern)
106
111
  end
107
112
  end
@@ -105,9 +105,10 @@ module WPScan
105
105
 
106
106
  # url_pattern is from CMSScanner::Target
107
107
  pattern = %r{#{url_pattern}(.+?)/(?:xmlrpc\.php|wp\-includes/)}i
108
+ xpath = '(//@src|//@href|//@data-src)[contains(., "xmlrpc.php") or contains(., "wp-includes/")]'
108
109
 
109
110
  [homepage_res, error_404_res].each do |page_res|
110
- in_scope_uris(page_res) do |uri|
111
+ in_scope_uris(page_res, xpath) do |uri|
111
112
  return @sub_dir = Regexp.last_match[1] if uri.to_s.match(pattern)
112
113
  end
113
114
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Version
4
4
  module WPScan
5
- VERSION = '3.7.8'
5
+ VERSION = '3.7.9'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wpscan
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.7.8
4
+ version: 3.7.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - WPScanTeam
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-09 00:00:00.000000000 Z
11
+ date: 2020-02-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cms_scanner
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.8.1
19
+ version: 0.8.3
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.8.1
26
+ version: 0.8.3
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.6'
41
- - !ruby/object:Gem::Dependency
42
- name: coveralls
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 0.8.0
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 0.8.0
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: memory_profiler
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -114,14 +100,14 @@ dependencies:
114
100
  requirements:
115
101
  - - "~>"
116
102
  - !ruby/object:Gem::Version
117
- version: 0.79.0
103
+ version: 0.80.0
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
108
  - - "~>"
123
109
  - !ruby/object:Gem::Version
124
- version: 0.79.0
110
+ version: 0.80.0
125
111
  - !ruby/object:Gem::Dependency
126
112
  name: rubocop-performance
127
113
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +128,28 @@ dependencies:
142
128
  requirements:
143
129
  - - "~>"
144
130
  - !ruby/object:Gem::Version
145
- version: 0.16.1
131
+ version: 0.18.2
146
132
  type: :development
147
133
  prerelease: false
148
134
  version_requirements: !ruby/object:Gem::Requirement
149
135
  requirements:
150
136
  - - "~>"
151
137
  - !ruby/object:Gem::Version
152
- version: 0.16.1
138
+ version: 0.18.2
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov-lcov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 0.8.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 0.8.0
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: stackprof
155
155
  requirement: !ruby/object:Gem::Requirement