cms_scanner 0.0.43.2 → 0.0.44.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.rb +10 -10
- data/app/controllers/core/cli_options.rb +4 -1
- data/app/controllers/interesting_findings.rb +1 -1
- data/lib/cms_scanner.rb +1 -0
- data/lib/cms_scanner/browser.rb +1 -1
- data/lib/cms_scanner/browser/options.rb +2 -5
- data/lib/cms_scanner/controller.rb +7 -23
- data/lib/cms_scanner/controllers.rb +5 -6
- data/lib/cms_scanner/finders/finder/breadth_first_dictionary_attack.rb +1 -1
- data/lib/cms_scanner/parsed_cli.rb +38 -0
- data/lib/cms_scanner/scan.rb +2 -4
- data/lib/cms_scanner/target/platform/php.rb +1 -1
- data/lib/cms_scanner/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36cf3a147ed137b39e8b2d7f1663bfd454639cce4b8d0f45764af3e3ab0b4b48
|
4
|
+
data.tar.gz: a4e4d72d4b8951a04c4f619cc20d1e1293eba77b15533e668738a2e0e62d3306
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cadfdee997e1ef6c7f10ce9f7b8b841acdb1fd5818b5682070f3a07dd5ea34658d55ffd9d86055ac6b7ccf60b5fd965213ba61f22f138873fc6852e137997f0f
|
7
|
+
data.tar.gz: 4a37dc5d1eae53a72894f6317cb72132dc07541f76d48ce9067d15fdf4e89d026b074cc4314163883dce3d2006305ff7c607831d8d0cb9c1c4d22e4978b53a91
|
data/app/controllers/core.rb
CHANGED
@@ -7,12 +7,12 @@ module CMSScanner
|
|
7
7
|
# Core Controller
|
8
8
|
class Core < Base
|
9
9
|
def setup_cache
|
10
|
-
return unless
|
10
|
+
return unless NS::ParsedCli.cache_dir
|
11
11
|
|
12
|
-
storage_path = File.join(
|
12
|
+
storage_path = File.join(NS::ParsedCli.cache_dir, Digest::MD5.hexdigest(target.url))
|
13
13
|
|
14
14
|
Typhoeus::Config.cache = Cache::Typhoeus.new(storage_path)
|
15
|
-
Typhoeus::Config.cache.clean if
|
15
|
+
Typhoeus::Config.cache.clean if NS::ParsedCli.clear_cache
|
16
16
|
end
|
17
17
|
|
18
18
|
def before_scan
|
@@ -23,12 +23,12 @@ module CMSScanner
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def maybe_output_banner_help_and_version
|
26
|
-
output('banner') if
|
27
|
-
output('help', help: option_parser.simple_help, simple: true) if
|
28
|
-
output('help', help: option_parser.full_help, simple: false) if
|
29
|
-
output('version') if
|
26
|
+
output('banner') if NS::ParsedCli.banner
|
27
|
+
output('help', help: option_parser.simple_help, simple: true) if NS::ParsedCli.help
|
28
|
+
output('help', help: option_parser.full_help, simple: false) if NS::ParsedCli.hh
|
29
|
+
output('version') if NS::ParsedCli.version
|
30
30
|
|
31
|
-
exit(NS::ExitCode::OK) if
|
31
|
+
exit(NS::ExitCode::OK) if NS::ParsedCli.help || NS::ParsedCli.hh || NS::ParsedCli.version
|
32
32
|
end
|
33
33
|
|
34
34
|
# Checks that the target is accessible, raises related errors otherwise
|
@@ -43,7 +43,7 @@ module CMSScanner
|
|
43
43
|
when 401
|
44
44
|
raise Error::HTTPAuthRequired
|
45
45
|
when 403
|
46
|
-
raise Error::AccessForbidden,
|
46
|
+
raise Error::AccessForbidden, NS::ParsedCli.random_user_agent
|
47
47
|
when 407
|
48
48
|
raise Error::ProxyAuthRequired
|
49
49
|
end
|
@@ -54,7 +54,7 @@ module CMSScanner
|
|
54
54
|
|
55
55
|
return if target.in_scope?(effective_url)
|
56
56
|
|
57
|
-
raise Error::HTTPRedirect, effective_url unless
|
57
|
+
raise Error::HTTPRedirect, effective_url unless NS::ParsedCli.ignore_main_redirect
|
58
58
|
|
59
59
|
target.homepage_res = res
|
60
60
|
end
|
@@ -46,7 +46,10 @@ module CMSScanner
|
|
46
46
|
OptBoolean.new(['--random-user-agent', '--rua',
|
47
47
|
'Use a random user-agent for each scan']),
|
48
48
|
OptFilePath.new(['--user-agents-list FILE-PATH',
|
49
|
-
'List of agents to use with --random-user-agent'],
|
49
|
+
'List of agents to use with --random-user-agent'],
|
50
|
+
exists: true,
|
51
|
+
advanced: true,
|
52
|
+
default: APP_DIR.join('user_agents.txt')),
|
50
53
|
OptCredentials.new(['--http-auth login:password']),
|
51
54
|
OptPositiveInteger.new(['-t', '--max-threads VALUE', 'The max threads to use'],
|
52
55
|
default: 5),
|
@@ -15,7 +15,7 @@ module CMSScanner
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def run
|
18
|
-
mode =
|
18
|
+
mode = NS::ParsedCli.interesting_findings_detection || NS::ParsedCli.detection_mode
|
19
19
|
findings = target.interesting_findings(mode: mode)
|
20
20
|
|
21
21
|
output('findings', findings: findings) unless findings.empty?
|
data/lib/cms_scanner.rb
CHANGED
@@ -24,6 +24,7 @@ require 'cms_scanner/public_suffix/domain' # Adds a Domain#match method and logi
|
|
24
24
|
require 'cms_scanner/numeric' # Adds a Numeric#bytes_to_human
|
25
25
|
# Custom Libs
|
26
26
|
require 'cms_scanner/scan'
|
27
|
+
require 'cms_scanner/parsed_cli'
|
27
28
|
require 'cms_scanner/helper'
|
28
29
|
require 'cms_scanner/exit_code'
|
29
30
|
require 'cms_scanner/errors'
|
data/lib/cms_scanner/browser.rb
CHANGED
@@ -62,6 +62,8 @@ module CMSScanner
|
|
62
62
|
|
63
63
|
@user_agents = []
|
64
64
|
|
65
|
+
# The user_agents_list is managed by the CLI options, with the default being
|
66
|
+
# APP_DIR/user_agents.txt
|
65
67
|
File.open(user_agents_list).each do |line|
|
66
68
|
next if line == "\n" || line[0, 1] == '#'
|
67
69
|
|
@@ -71,11 +73,6 @@ module CMSScanner
|
|
71
73
|
@user_agents
|
72
74
|
end
|
73
75
|
|
74
|
-
# @return [ String ] The path to the user agents list
|
75
|
-
def user_agents_list
|
76
|
-
@user_agents_list ||= File.join(APP_DIR, 'user_agents.txt')
|
77
|
-
end
|
78
|
-
|
79
76
|
# @param [ value ] The throttle time in milliseconds
|
80
77
|
#
|
81
78
|
# if value > 0, the max_threads will be set to 1
|
@@ -22,15 +22,14 @@ module CMSScanner
|
|
22
22
|
# Reset all the class attibutes
|
23
23
|
# Currently only used in specs
|
24
24
|
def self.reset
|
25
|
-
@@target
|
26
|
-
@@
|
27
|
-
@@
|
28
|
-
@@formatter = nil
|
25
|
+
@@target = nil
|
26
|
+
@@datastore = nil
|
27
|
+
@@formatter = nil
|
29
28
|
end
|
30
29
|
|
31
30
|
# @return [ Target ]
|
32
31
|
def target
|
33
|
-
@@target ||= NS::Target.new(
|
32
|
+
@@target ||= NS::Target.new(NS::ParsedCli.url, NS::ParsedCli.options)
|
34
33
|
end
|
35
34
|
|
36
35
|
# @param [ OptParsevalidator::OptParser ] parser
|
@@ -43,21 +42,6 @@ module CMSScanner
|
|
43
42
|
@@option_parser
|
44
43
|
end
|
45
44
|
|
46
|
-
# Set the parsed options and initialize the browser
|
47
|
-
# with them
|
48
|
-
#
|
49
|
-
# @param [ Hash ] options
|
50
|
-
def self.parsed_options=(options)
|
51
|
-
@@parsed_options = options
|
52
|
-
|
53
|
-
NS::Browser.instance(options)
|
54
|
-
end
|
55
|
-
|
56
|
-
# @return [ Hash ]
|
57
|
-
def parsed_options
|
58
|
-
@@parsed_options ||= {}
|
59
|
-
end
|
60
|
-
|
61
45
|
# @return [ Hash ]
|
62
46
|
def datastore
|
63
47
|
@@datastore ||= {}
|
@@ -65,7 +49,7 @@ module CMSScanner
|
|
65
49
|
|
66
50
|
# @return [ Formatter::Base ]
|
67
51
|
def formatter
|
68
|
-
@@formatter ||= NS::Formatter.load(
|
52
|
+
@@formatter ||= NS::Formatter.load(NS::ParsedCli.format, datastore[:views])
|
69
53
|
end
|
70
54
|
|
71
55
|
# @see Formatter#output
|
@@ -84,7 +68,7 @@ module CMSScanner
|
|
84
68
|
|
85
69
|
# @return [ Boolean ]
|
86
70
|
def user_interaction?
|
87
|
-
formatter.user_interaction? && !
|
71
|
+
formatter.user_interaction? && !NS::ParsedCli.output
|
88
72
|
end
|
89
73
|
|
90
74
|
# @return [ String ]
|
@@ -108,7 +92,7 @@ module CMSScanner
|
|
108
92
|
|
109
93
|
# @return [ Hash ] All the instance variable keys (and their values) and the verbose value
|
110
94
|
def instance_variable_values
|
111
|
-
h = { verbose:
|
95
|
+
h = { verbose: NS::ParsedCli.verbose }
|
112
96
|
instance_variables.each do |a|
|
113
97
|
s = a.to_s
|
114
98
|
n = s[1..s.size]
|
@@ -35,13 +35,12 @@ module CMSScanner
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def run
|
38
|
-
|
39
|
-
first.class.option_parser
|
40
|
-
first.class.parsed_options = parsed_options
|
38
|
+
NS::ParsedCli.options = option_parser.results
|
39
|
+
first.class.option_parser = option_parser # To be able to output the help when -h/--hh
|
41
40
|
|
42
|
-
redirect_output_to_file(
|
41
|
+
redirect_output_to_file(NS::ParsedCli.output) if NS::ParsedCli.output
|
43
42
|
|
44
|
-
Timeout.timeout(
|
43
|
+
Timeout.timeout(NS::ParsedCli.max_scan_duration, NS::Error::MaxScanDurationReached) do
|
45
44
|
each(&:before_scan)
|
46
45
|
|
47
46
|
@running = true
|
@@ -49,7 +48,7 @@ module CMSScanner
|
|
49
48
|
each(&:run)
|
50
49
|
end
|
51
50
|
ensure
|
52
|
-
Browser.instance.hydra.abort
|
51
|
+
NS::Browser.instance.hydra.abort
|
53
52
|
|
54
53
|
# Reverse is used here as the app/controllers/core#after_scan finishes the output
|
55
54
|
# and must be the last one to be executed. It also guarantee that stats will be output
|
@@ -103,7 +103,7 @@ module CMSScanner
|
|
103
103
|
'Request timed out.'
|
104
104
|
elsif response.code.zero?
|
105
105
|
"No response from remote server. WAF/IPS? (#{response.return_message})"
|
106
|
-
elsif response.code.to_s
|
106
|
+
elsif /^50/.match?(response.code.to_s)
|
107
107
|
'Server error, try reducing the number of threads.'
|
108
108
|
else
|
109
109
|
"Unknown response received Code: #{response.code}\nBody: #{response.body}"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CMSScanner
|
4
|
+
# Class to hold the parsed CLI options and have them available via
|
5
|
+
# methods, such as #verbose?, rather than from the hash.
|
6
|
+
# This is similar to an OpenStruct, but class wise (rather than instance), and with
|
7
|
+
# the logic to update the Browser options accordinly
|
8
|
+
class ParsedCli
|
9
|
+
@options = {}
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_reader :options
|
13
|
+
end
|
14
|
+
|
15
|
+
# Sets the CLI options, and put them into the Browser as well
|
16
|
+
# @param [ Hash ] options
|
17
|
+
def self.options=(options)
|
18
|
+
@options = options.dup
|
19
|
+
|
20
|
+
NS::Browser.reset
|
21
|
+
NS::Browser.instance(@options)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [ Boolean ]
|
25
|
+
def self.verbose?
|
26
|
+
options[:verbose] ? true : false
|
27
|
+
end
|
28
|
+
|
29
|
+
# Unknown methods will return nil, this is the expected behaviour
|
30
|
+
# rubocop:disable Style/MissingRespondToMissing
|
31
|
+
def self.method_missing(method_name, *_args, &_block)
|
32
|
+
super if method_name == :new
|
33
|
+
|
34
|
+
options[method_name.to_sym]
|
35
|
+
end
|
36
|
+
# rubocop:enable Style/MissingRespondToMissing
|
37
|
+
end
|
38
|
+
end
|
data/lib/cms_scanner/scan.rb
CHANGED
@@ -32,7 +32,7 @@ module CMSScanner
|
|
32
32
|
formatter.output('@scan_aborted',
|
33
33
|
reason: e.is_a?(Interrupt) ? 'Canceled by User' : e.message,
|
34
34
|
trace: e.backtrace,
|
35
|
-
verbose:
|
35
|
+
verbose: NS::ParsedCli.verbose ||
|
36
36
|
run_error_exit_code == NS::ExitCode::EXCEPTION)
|
37
37
|
ensure
|
38
38
|
formatter.beautify
|
@@ -61,10 +61,8 @@ module CMSScanner
|
|
61
61
|
at_exit do
|
62
62
|
exit(run_error_exit_code) if run_error
|
63
63
|
|
64
|
-
controller = controllers.first
|
65
|
-
|
66
64
|
# The parsed_option[:url] must be checked to avoid raising erros when only -h/-v are given
|
67
|
-
exit(NS::ExitCode::VULNERABLE) if
|
65
|
+
exit(NS::ExitCode::VULNERABLE) if NS::ParsedCli.url && controllers.first.target.vulnerable?
|
68
66
|
exit(NS::ExitCode::OK)
|
69
67
|
end
|
70
68
|
end
|
@@ -20,7 +20,7 @@ module CMSScanner
|
|
20
20
|
# which can be huge (~ 2Go)
|
21
21
|
res = head_and_get(path, [200], get: params.merge(headers: { 'Range' => 'bytes=0-700' }))
|
22
22
|
|
23
|
-
res.body
|
23
|
+
res.body&.match?(pattern) ? true : false
|
24
24
|
end
|
25
25
|
|
26
26
|
# @param [ String ] path
|
data/lib/cms_scanner/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cms_scanner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.44.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- WPScanTeam
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-04-
|
11
|
+
date: 2019-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -184,14 +184,14 @@ dependencies:
|
|
184
184
|
requirements:
|
185
185
|
- - "~>"
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version: 0.
|
187
|
+
version: 0.67.1
|
188
188
|
type: :development
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
192
|
- - "~>"
|
193
193
|
- !ruby/object:Gem::Version
|
194
|
-
version: 0.
|
194
|
+
version: 0.67.1
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
196
|
name: simplecov
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -299,6 +299,7 @@ files:
|
|
299
299
|
- lib/cms_scanner/formatter/buffer.rb
|
300
300
|
- lib/cms_scanner/helper.rb
|
301
301
|
- lib/cms_scanner/numeric.rb
|
302
|
+
- lib/cms_scanner/parsed_cli.rb
|
302
303
|
- lib/cms_scanner/progressbar_null_output.rb
|
303
304
|
- lib/cms_scanner/public_suffix/domain.rb
|
304
305
|
- lib/cms_scanner/references.rb
|
@@ -330,7 +331,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
330
331
|
requirements:
|
331
332
|
- - ">="
|
332
333
|
- !ruby/object:Gem::Version
|
333
|
-
version: '2.
|
334
|
+
version: '2.4'
|
334
335
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
335
336
|
requirements:
|
336
337
|
- - ">="
|