wpscan 4.1.0 → 4.2.0
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 +4 -4
- data/app/controllers/core/cli_options.rb +6 -1
- data/app/finders/users/wp_json_api.rb +3 -0
- data/app/formatters/sarif.rb +14 -3
- data/lib/opt_parse_validator/hacks.rb +1 -2
- data/lib/opt_parse_validator/opts/positive_integer.rb +2 -0
- data/lib/wpscan/browser/options.rb +1 -0
- data/lib/wpscan/browser.rb +6 -1
- data/lib/wpscan/cache/file_store.rb +8 -0
- data/lib/wpscan/controllers.rb +1 -2
- data/lib/wpscan/parsed_cli.rb +1 -2
- data/lib/wpscan/public_suffix/domain.rb +1 -2
- data/lib/wpscan/target/scope.rb +1 -2
- data/lib/wpscan/typhoeus/response_size_cap.rb +47 -0
- data/lib/wpscan/version.rb +1 -1
- data/lib/wpscan.rb +1 -0
- metadata +8 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b66209f9f28c78f30d0d121c6841ffe370dc0109e3dde221a1212187522a0ff1
|
|
4
|
+
data.tar.gz: 12c257dbfc4ec49bfb438cc1abceeebebfc313690251d0e9e059978b76ac940e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8623ccd870f308d9bf7f8ce19dc77c7281b50155ade1e73c14f82644c0e30085dc7aaf4f7ff61513f9b7d757bfb1c3b77dbde0999a1fc59a8d44f9cd2c2b1fb4
|
|
7
|
+
data.tar.gz: 8bc2e65b6320bc40f069495a8359c91bc3edb7ae91242e54df552eb77a5e73c76a4a3ddfdd677a07bed6cdee5df34a5f910835eeb1e13b3f27bee03fdd63eba6
|
|
@@ -87,7 +87,12 @@ module WPScan
|
|
|
87
87
|
default: 30),
|
|
88
88
|
OptBoolean.new(['--disable-tls-checks',
|
|
89
89
|
'Disables SSL/TLS certificate verification, and downgrade to TLS1.0+ ' \
|
|
90
|
-
'(requires cURL 7.66 for the latter)'])
|
|
90
|
+
'(requires cURL 7.66 for the latter)']),
|
|
91
|
+
OptPositiveInteger.new(['--max-response-size MiB',
|
|
92
|
+
'Stop reading any response once it exceeds this size, in MiB. ' \
|
|
93
|
+
'Guards against memory exhaustion on targets serving very large ' \
|
|
94
|
+
'or endless responses. At most 2047, as a 2 GiB body cannot be parsed.'],
|
|
95
|
+
default: 16, max: 2047, advanced: true)
|
|
91
96
|
] + cli_browser_proxy_options + cli_browser_cookies_options + cli_browser_cache_options
|
|
92
97
|
end
|
|
93
98
|
|
data/app/formatters/sarif.rb
CHANGED
|
@@ -96,12 +96,17 @@ module WPScan
|
|
|
96
96
|
def components(data)
|
|
97
97
|
list = []
|
|
98
98
|
list << core_component(data) if data['version']
|
|
99
|
-
list
|
|
100
|
-
(data['themes'] || {}).each_value { |theme| list << theme_component(theme) }
|
|
99
|
+
list.concat(theme_components(data))
|
|
101
100
|
(data['plugins'] || {}).each { |slug, plugin| list << plugin_component(slug, plugin) }
|
|
102
101
|
list
|
|
103
102
|
end
|
|
104
103
|
|
|
104
|
+
def theme_components(data)
|
|
105
|
+
themes = [data['main_theme'], *(data['themes'] || {}).values].compact
|
|
106
|
+
themes.concat(themes.flat_map { |theme| Array(theme['parents']) })
|
|
107
|
+
themes.map { |theme| theme_component(theme) }.uniq
|
|
108
|
+
end
|
|
109
|
+
|
|
105
110
|
def core_component(data)
|
|
106
111
|
{
|
|
107
112
|
kind: 'core',
|
|
@@ -285,7 +290,13 @@ module WPScan
|
|
|
285
290
|
end
|
|
286
291
|
|
|
287
292
|
def invocation(data)
|
|
288
|
-
|
|
293
|
+
failure = data['scan_aborted'] || data['update_aborted']
|
|
294
|
+
inv = { 'executionSuccessful' => failure.nil? }
|
|
295
|
+
if failure
|
|
296
|
+
inv['toolExecutionNotifications'] = [
|
|
297
|
+
{ 'level' => 'error', 'message' => { 'text' => failure.to_s } }
|
|
298
|
+
]
|
|
299
|
+
end
|
|
289
300
|
inv['commandLine'] = "wpscan #{data['command_line']}" if data['command_line']
|
|
290
301
|
inv['hostname'] = data['hostname'] if data['hostname']
|
|
291
302
|
inv['startTimeUtc'] = to_iso8601(data['start_time']) if data['start_time']
|
|
@@ -8,12 +8,11 @@ class OptionParser
|
|
|
8
8
|
class << self
|
|
9
9
|
alias original_candidate candidate
|
|
10
10
|
|
|
11
|
-
# rubocop:disable Style/OptionalBooleanParameter
|
|
11
|
+
# rubocop:disable-next Style/OptionalBooleanParameter
|
|
12
12
|
def candidate(key, icase = false, pat = nil, &)
|
|
13
13
|
# Maybe also do this for -v/--version ?
|
|
14
14
|
key == 'h' ? original_candidate('help', icase, pat, &) : []
|
|
15
15
|
end
|
|
16
|
-
# rubocop:enable Style/OptionalBooleanParameter
|
|
17
16
|
end
|
|
18
17
|
end
|
|
19
18
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module OptParseValidator
|
|
4
4
|
# Implementation of the Positive Integer Option
|
|
5
|
+
# attrs[:max], when given, is the highest value accepted
|
|
5
6
|
class OptPositiveInteger < OptInteger
|
|
6
7
|
# @param [ String ] value
|
|
7
8
|
#
|
|
@@ -9,6 +10,7 @@ module OptParseValidator
|
|
|
9
10
|
def validate(value)
|
|
10
11
|
i = super
|
|
11
12
|
raise Error, "#{i} is not > 0" unless i.positive?
|
|
13
|
+
raise Error, "#{i} is not <= #{attrs[:max]}" if attrs[:max] && i > attrs[:max]
|
|
12
14
|
|
|
13
15
|
i
|
|
14
16
|
end
|
data/lib/wpscan/browser.rb
CHANGED
|
@@ -37,7 +37,12 @@ module WPScan
|
|
|
37
37
|
#
|
|
38
38
|
# @return [ Typhoeus::Request ]
|
|
39
39
|
def forge_request(url, params = {})
|
|
40
|
-
Typhoeus::Request.new(url, request_params(params))
|
|
40
|
+
request = Typhoeus::Request.new(url, request_params(params))
|
|
41
|
+
# Detection reads the head of a document rather than its tail, so the cap is well above
|
|
42
|
+
# anything a finder needs. See WPScan::ResponseSizeCap
|
|
43
|
+
request.max_response_size = max_response_size.to_i * 1024 * 1024
|
|
44
|
+
|
|
45
|
+
request
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
# @return [ Hash ] The request params used to connect to the target as well as other systems (e.g. API).
|
|
@@ -46,6 +46,14 @@ module WPScan
|
|
|
46
46
|
|
|
47
47
|
File.write(entry_path(key), serializer.dump(data_to_store))
|
|
48
48
|
File.write(entry_expiration_path(key), Time.now.to_i + cache_ttl)
|
|
49
|
+
rescue TypeError => e
|
|
50
|
+
# Marshal raises TypeError("long too big to dump") for a String of 2GiB or more, which a
|
|
51
|
+
# target can produce with a single chunked response. Such an entry is not cacheable, but
|
|
52
|
+
# failing to cache it is not a reason to abort the scan. Any other TypeError (e.g. an
|
|
53
|
+
# object Marshal cannot dump) is a bug and must surface.
|
|
54
|
+
raise unless e.message.include?('too big to dump')
|
|
55
|
+
|
|
56
|
+
nil
|
|
49
57
|
end
|
|
50
58
|
|
|
51
59
|
# @param [ String ] key
|
data/lib/wpscan/controllers.rb
CHANGED
|
@@ -72,9 +72,8 @@ module WPScan
|
|
|
72
72
|
end
|
|
73
73
|
ensure
|
|
74
74
|
# The rescue prevents unfinished requests from raising, which would stop reverse_each from running.
|
|
75
|
-
# rubocop:disable Style/RescueModifier
|
|
75
|
+
# rubocop:disable-next Style/RescueModifier
|
|
76
76
|
WPScan::Browser.instance.hydra.abort rescue nil
|
|
77
|
-
# rubocop:enable Style/RescueModifier
|
|
78
77
|
|
|
79
78
|
# Reverse order: app/controllers/core#after_scan finishes the output and must be last.
|
|
80
79
|
# Guarantees stats are output even on error. after_scan runs only if scan was actually running
|
data/lib/wpscan/parsed_cli.rb
CHANGED
|
@@ -25,12 +25,11 @@ module WPScan
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
# Unknown methods return nil — expected behaviour for option lookups.
|
|
28
|
-
# rubocop:disable Style/MissingRespondToMissing
|
|
28
|
+
# rubocop:disable-next Style/MissingRespondToMissing
|
|
29
29
|
def self.method_missing(method_name, *_args, &)
|
|
30
30
|
super if method_name == :new
|
|
31
31
|
|
|
32
32
|
options[method_name.to_sym]
|
|
33
33
|
end
|
|
34
|
-
# rubocop:enable Style/MissingRespondToMissing
|
|
35
34
|
end
|
|
36
35
|
end
|
|
@@ -10,7 +10,7 @@ module PublicSuffix
|
|
|
10
10
|
|
|
11
11
|
# @return [ Boolean ]
|
|
12
12
|
#
|
|
13
|
-
# rubocop:disable Naming/PredicateMethod
|
|
13
|
+
# rubocop:disable-next Naming/PredicateMethod
|
|
14
14
|
def match(pattern)
|
|
15
15
|
pattern = PublicSuffix.parse(pattern) unless pattern.is_a?(PublicSuffix::Domain)
|
|
16
16
|
|
|
@@ -19,7 +19,6 @@ module PublicSuffix
|
|
|
19
19
|
|
|
20
20
|
matching_pattern?(pattern)
|
|
21
21
|
end
|
|
22
|
-
# rubocop:enable Naming/PredicateMethod
|
|
23
22
|
|
|
24
23
|
protected
|
|
25
24
|
|
data/lib/wpscan/target/scope.rb
CHANGED
|
@@ -46,7 +46,7 @@ module WPScan
|
|
|
46
46
|
#
|
|
47
47
|
# @return [ Regexp ] The pattern related to the target url and in scope domains,
|
|
48
48
|
# it also matches escaped /, such as in JSON JS data: http:\/\/t.com\/
|
|
49
|
-
# rubocop:disable Metrics/AbcSize
|
|
49
|
+
# rubocop:disable-next Metrics/AbcSize
|
|
50
50
|
def scope_url_pattern
|
|
51
51
|
return @scope_url_pattern if @scope_url_pattern
|
|
52
52
|
|
|
@@ -64,7 +64,6 @@ module WPScan
|
|
|
64
64
|
|
|
65
65
|
@scope_url_pattern = %r{https?:\\?/\\?/(?:#{domains.join('|')})\\?/?}i
|
|
66
66
|
end
|
|
67
|
-
# rubocop:enable Metrics/AbcSize
|
|
68
67
|
|
|
69
68
|
# Scope Implementation
|
|
70
69
|
class Scope
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WPScan
|
|
4
|
+
# Bounds how much of a response is kept in memory, for requests carrying a #max_response_size.
|
|
5
|
+
#
|
|
6
|
+
# libcurl's maxfilesize is not enough on its own: it acts on the advertised Content-Length, so it
|
|
7
|
+
# is a no-op against the chunked responses a dynamic site serves. Only an on_body callback can
|
|
8
|
+
# stop a transfer by how much has actually arrived.
|
|
9
|
+
#
|
|
10
|
+
# The callback is installed on the Ethon easy rather than through Typhoeus::Request#on_body: the
|
|
11
|
+
# latter puts the request in streaming mode, where Response#body is left empty, and Typhoeus
|
|
12
|
+
# caches the response before any on_complete could put the body back. Returning :unyielded
|
|
13
|
+
# tells Ethon to accumulate the chunk as it would with no callback, so the body is intact when
|
|
14
|
+
# the response is cached, just shorter.
|
|
15
|
+
module ResponseSizeCap
|
|
16
|
+
# Adds the per request cap, in bytes. nil or 0 disables it.
|
|
17
|
+
module Request
|
|
18
|
+
attr_accessor :max_response_size
|
|
19
|
+
|
|
20
|
+
# A capped response may be truncated, so it must not be served from the cache to a request
|
|
21
|
+
# allowing a larger one. Uncapped requests keep the stock key.
|
|
22
|
+
def cache_key
|
|
23
|
+
max_size = max_response_size.to_i
|
|
24
|
+
|
|
25
|
+
max_size.zero? ? super : "#{super}-max_response_size:#{max_size}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Installs the cap when the easy is built, i.e. after any on_body a caller has added.
|
|
30
|
+
module EasyFactory
|
|
31
|
+
def set_callback
|
|
32
|
+
super
|
|
33
|
+
|
|
34
|
+
max_size = request.max_response_size.to_i
|
|
35
|
+
# A caller doing its own streaming (e.g. Target#log_file?) has its own handling
|
|
36
|
+
return if max_size.zero? || request.streaming?
|
|
37
|
+
|
|
38
|
+
easy.on_body do |_chunk, easy_handle|
|
|
39
|
+
easy_handle.response_body.bytesize >= max_size ? :abort : :unyielded
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
Typhoeus::Request.prepend(WPScan::ResponseSizeCap::Request)
|
|
47
|
+
Typhoeus::EasyFactory.prepend(WPScan::ResponseSizeCap::EasyFactory)
|
data/lib/wpscan/version.rb
CHANGED
data/lib/wpscan.rb
CHANGED
|
@@ -27,6 +27,7 @@ require 'xmlrpc/client'
|
|
|
27
27
|
# Monkey Patches/Fixes
|
|
28
28
|
require 'wpscan/typhoeus/response' # Adds Response#html and from_vuln_api?
|
|
29
29
|
require 'wpscan/typhoeus/hydra' # https://github.com/typhoeus/typhoeus/issues/439
|
|
30
|
+
require 'wpscan/typhoeus/response_size_cap' # Adds Request#max_response_size
|
|
30
31
|
require 'wpscan/public_suffix/domain' # Adds Domain#match
|
|
31
32
|
require 'wpscan/numeric' # Adds Numeric#bytes_to_human
|
|
32
33
|
# Custom Libs
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: wpscan
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- WPScanTeam
|
|
@@ -323,14 +323,14 @@ dependencies:
|
|
|
323
323
|
requirements:
|
|
324
324
|
- - "~>"
|
|
325
325
|
- !ruby/object:Gem::Version
|
|
326
|
-
version:
|
|
326
|
+
version: 1.92.0
|
|
327
327
|
type: :development
|
|
328
328
|
prerelease: false
|
|
329
329
|
version_requirements: !ruby/object:Gem::Requirement
|
|
330
330
|
requirements:
|
|
331
331
|
- - "~>"
|
|
332
332
|
- !ruby/object:Gem::Version
|
|
333
|
-
version:
|
|
333
|
+
version: 1.92.0
|
|
334
334
|
- !ruby/object:Gem::Dependency
|
|
335
335
|
name: rubocop-performance
|
|
336
336
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -351,14 +351,14 @@ dependencies:
|
|
|
351
351
|
requirements:
|
|
352
352
|
- - "~>"
|
|
353
353
|
- !ruby/object:Gem::Version
|
|
354
|
-
version: 1.
|
|
354
|
+
version: 1.3.0
|
|
355
355
|
type: :development
|
|
356
356
|
prerelease: false
|
|
357
357
|
version_requirements: !ruby/object:Gem::Requirement
|
|
358
358
|
requirements:
|
|
359
359
|
- - "~>"
|
|
360
360
|
- !ruby/object:Gem::Version
|
|
361
|
-
version: 1.
|
|
361
|
+
version: 1.3.0
|
|
362
362
|
- !ruby/object:Gem::Dependency
|
|
363
363
|
name: simplecov-lcov
|
|
364
364
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -393,14 +393,14 @@ dependencies:
|
|
|
393
393
|
requirements:
|
|
394
394
|
- - "~>"
|
|
395
395
|
- !ruby/object:Gem::Version
|
|
396
|
-
version: 3.
|
|
396
|
+
version: 3.34.0
|
|
397
397
|
type: :development
|
|
398
398
|
prerelease: false
|
|
399
399
|
version_requirements: !ruby/object:Gem::Requirement
|
|
400
400
|
requirements:
|
|
401
401
|
- - "~>"
|
|
402
402
|
- !ruby/object:Gem::Version
|
|
403
|
-
version: 3.
|
|
403
|
+
version: 3.34.0
|
|
404
404
|
description: WPScan is a black box WordPress vulnerability scanner.
|
|
405
405
|
email:
|
|
406
406
|
- contact@wpscan.com
|
|
@@ -717,6 +717,7 @@ files:
|
|
|
717
717
|
- lib/wpscan/target/server/nginx.rb
|
|
718
718
|
- lib/wpscan/typhoeus/hydra.rb
|
|
719
719
|
- lib/wpscan/typhoeus/response.rb
|
|
720
|
+
- lib/wpscan/typhoeus/response_size_cap.rb
|
|
720
721
|
- lib/wpscan/version.rb
|
|
721
722
|
- lib/wpscan/vulnerability.rb
|
|
722
723
|
- lib/wpscan/vulnerability_filter.rb
|