wpscan 3.7.8 → 3.7.9

Sign up to get free protection for your applications and to get access to all the features.
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