cms_scanner 0.0.32 → 0.0.33
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/core/cli_options.rb +5 -5
- data/app/controllers/interesting_findings.rb +1 -3
- data/cms_scanner.gemspec +1 -1
- data/lib/cms_scanner.rb +29 -0
- data/lib/cms_scanner/errors/http.rb +15 -5
- data/lib/cms_scanner/exit_code.rb +20 -0
- data/lib/cms_scanner/public_suffix/domain.rb +13 -6
- data/lib/cms_scanner/target.rb +13 -3
- data/lib/cms_scanner/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f93aa617ff534c907d09aed61fc22f2cebb924d
|
4
|
+
data.tar.gz: cbb4ade08697eaec5c6dbdc8c1a73ec950093a85
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eccfe8a5c8748f6230e8ab5ac0c6d71ffdc1d1ad2e6946436f27407ee9b5878d7eaebcd3c637fe8ee6a7104cfd376cfe8f86cf33d8e69efadebc234b85d1799a
|
7
|
+
data.tar.gz: a407110fcb4b2e2f4460b167a7112c099890a874f0bde0b3ebf5a3b66d19e065525c2bcb7c7f87585624b0274862e96c11981e7ae62839737650542b69a3145b
|
@@ -6,18 +6,18 @@ module CMSScanner
|
|
6
6
|
formats = NS::Formatter.availables
|
7
7
|
|
8
8
|
[
|
9
|
-
OptURL.new(['-u', '--url URL'], required: true, default_protocol: 'http'),
|
9
|
+
OptURL.new(['-u', '--url URL', 'The URL to scan'], required: true, default_protocol: 'http'),
|
10
10
|
OptBoolean.new(['--ignore-main-redirect', 'Ignore the main redirect if any and scan the target url']),
|
11
11
|
OptBoolean.new(%w(-v --verbose)),
|
12
12
|
OptFilePath.new(['-o', '--output FILE', 'Output to FILE'], writable: true, exists: false),
|
13
13
|
OptChoice.new(['-f', '--format FORMAT',
|
14
|
-
|
15
|
-
OptChoice.new(['--detection-mode MODE'
|
14
|
+
'Output results in the format supplied'], choices: formats),
|
15
|
+
OptChoice.new(['--detection-mode MODE'],
|
16
16
|
choices: %w(mixed passive aggressive),
|
17
17
|
normalize: :to_sym,
|
18
18
|
default: :mixed),
|
19
19
|
OptArray.new(['--scope DOMAINS',
|
20
|
-
'Comma separated (sub-)domains to consider in scope. '
|
20
|
+
'Comma separated (sub-)domains to consider in scope. ',
|
21
21
|
'Wildcard(s) allowed in the trd of valid domains, e.g: *.target.tld'])
|
22
22
|
] + cli_browser_options
|
23
23
|
end
|
@@ -66,7 +66,7 @@ module CMSScanner
|
|
66
66
|
# @return [ Array<OptParseValidator::OptBase> ]
|
67
67
|
def cli_browser_cache_options
|
68
68
|
[
|
69
|
-
OptInteger.new(['--cache-ttl TIME_TO_LIVE'], default: 600),
|
69
|
+
OptInteger.new(['--cache-ttl TIME_TO_LIVE', 'The cache time to live in seconds'], default: 600),
|
70
70
|
OptBoolean.new(['--clear-cache', 'Clear the cache before the scan']),
|
71
71
|
OptDirectoryPath.new(['--cache-dir PATH'],
|
72
72
|
readable: true,
|
@@ -6,9 +6,7 @@ module CMSScanner
|
|
6
6
|
[
|
7
7
|
OptChoice.new(
|
8
8
|
['--interesting-findings-detection MODE',
|
9
|
-
'Use the supplied mode for the interesting findings detection. '
|
10
|
-
'Modes: mixed, passive, aggressive'
|
11
|
-
],
|
9
|
+
'Use the supplied mode for the interesting findings detection. '],
|
12
10
|
choices: %w(mixed passive aggressive),
|
13
11
|
normalize: :to_sym)
|
14
12
|
]
|
data/cms_scanner.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
32
32
|
s.require_path = 'lib'
|
33
33
|
|
34
|
-
s.add_dependency 'opt_parse_validator', '~> 0.0.
|
34
|
+
s.add_dependency 'opt_parse_validator', '~> 0.0.12.1'
|
35
35
|
s.add_dependency 'typhoeus', '~> 0.7'
|
36
36
|
s.add_dependency 'nokogiri', '~> 1.6.6'
|
37
37
|
s.add_dependency 'addressable', '~> 2.3.8'
|
data/lib/cms_scanner.rb
CHANGED
@@ -17,6 +17,7 @@ require 'cms_scanner/typhoeus/hydra'
|
|
17
17
|
require 'cms_scanner/public_suffix/domain'
|
18
18
|
# Custom Libs
|
19
19
|
require 'cms_scanner/helper'
|
20
|
+
require 'cms_scanner/exit_code'
|
20
21
|
require 'cms_scanner/errors/http'
|
21
22
|
require 'cms_scanner/cache/typhoeus'
|
22
23
|
require 'cms_scanner/target'
|
@@ -56,9 +57,13 @@ module CMSScanner
|
|
56
57
|
|
57
58
|
# Scan
|
58
59
|
class Scan
|
60
|
+
attr_reader :run_error
|
61
|
+
|
59
62
|
def initialize
|
60
63
|
controllers << NS::Controller::Core.new
|
61
64
|
|
65
|
+
exit_hook
|
66
|
+
|
62
67
|
yield self if block_given?
|
63
68
|
end
|
64
69
|
|
@@ -70,8 +75,12 @@ module CMSScanner
|
|
70
75
|
def run
|
71
76
|
controllers.run
|
72
77
|
rescue OptParseValidator::NoRequiredOption => e
|
78
|
+
@run_error = e
|
79
|
+
|
73
80
|
formatter.output('@usage', msg: e.message)
|
74
81
|
rescue => e
|
82
|
+
@run_error = e
|
83
|
+
|
75
84
|
formatter.output('@scan_aborted',
|
76
85
|
reason: e.message,
|
77
86
|
trace: e.backtrace,
|
@@ -92,6 +101,26 @@ module CMSScanner
|
|
92
101
|
def datastore
|
93
102
|
controllers.first.datastore
|
94
103
|
end
|
104
|
+
|
105
|
+
# Hook to be able to have an exit code returned
|
106
|
+
# depending on the findings / errors
|
107
|
+
def exit_hook
|
108
|
+
at_exit do
|
109
|
+
if run_error
|
110
|
+
exit(NS::ExitCode::CLI_OPTION_ERROR) if run_error.is_a?(OptParseValidator::Error) ||
|
111
|
+
run_error.is_a?(OptionParser::ParseError)
|
112
|
+
|
113
|
+
exit(NS::ExitCode::INTERRUPTED) if run_error.is_a?(Interrupt)
|
114
|
+
exit(NS::ExitCode::ERROR)
|
115
|
+
end
|
116
|
+
|
117
|
+
controller = controllers.first
|
118
|
+
|
119
|
+
# The parsed_option[:url] must be checked to avoid raising erros when only -h/-v are given
|
120
|
+
exit(NS::ExitCode::VULNERABLE) if controller.parsed_options[:url] && controller.target.vulnerable?
|
121
|
+
exit(NS::ExitCode::OK)
|
122
|
+
end
|
123
|
+
end
|
95
124
|
end
|
96
125
|
end
|
97
126
|
|
@@ -1,28 +1,37 @@
|
|
1
1
|
module CMSScanner
|
2
|
+
class Error < RuntimeError
|
3
|
+
end
|
4
|
+
|
2
5
|
# HTTP Authentication Required Error
|
3
|
-
class HTTPAuthRequiredError <
|
6
|
+
class HTTPAuthRequiredError < Error
|
7
|
+
# :nocov:
|
4
8
|
def to_s
|
5
9
|
'HTTP authentication required (or was invalid), please provide it with --http-auth'
|
6
10
|
end
|
11
|
+
# :nocov:
|
7
12
|
end
|
8
13
|
|
9
14
|
# Proxy Authentication Required Error
|
10
|
-
class ProxyAuthRequiredError <
|
15
|
+
class ProxyAuthRequiredError < Error
|
16
|
+
# :nocov:
|
11
17
|
def to_s
|
12
18
|
'Proxy authentication required (or was invalid), please provide it with --proxy-auth'
|
13
19
|
end
|
20
|
+
# :nocov:
|
14
21
|
end
|
15
22
|
|
16
23
|
# Access Forbidden Error
|
17
|
-
class AccessForbiddenError <
|
24
|
+
class AccessForbiddenError < Error
|
25
|
+
# :nocov:
|
18
26
|
def to_s
|
19
27
|
'The target is responding with a 403, this might be due to a WAF. ' \
|
20
28
|
'Please re-try with --random-user-agent'
|
21
29
|
end
|
30
|
+
# :nocov:
|
22
31
|
end
|
23
32
|
|
24
33
|
# HTTP Redirect Error
|
25
|
-
class HTTPRedirectError <
|
34
|
+
class HTTPRedirectError < Error
|
26
35
|
attr_reader :redirect_uri
|
27
36
|
|
28
37
|
# @param [ String ] url
|
@@ -31,7 +40,8 @@ module CMSScanner
|
|
31
40
|
end
|
32
41
|
|
33
42
|
def to_s
|
34
|
-
"The URL supplied redirects to #{redirect_uri}"
|
43
|
+
"The URL supplied redirects to #{redirect_uri}. Use the --ignore-main-redirect "\
|
44
|
+
'option to ignore the redirection and scan the target.'
|
35
45
|
end
|
36
46
|
end
|
37
47
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
# Exit Code Values
|
3
|
+
module ExitCode
|
4
|
+
# No error, scan finished w/o any vulnerabilies found
|
5
|
+
OK = 0
|
6
|
+
|
7
|
+
# All exceptions raised by OptParseValidator and OptionParser
|
8
|
+
CLI_OPTION_ERROR = 1
|
9
|
+
|
10
|
+
# Interrupt received
|
11
|
+
INTERRUPTED = 2
|
12
|
+
|
13
|
+
# Exceptions
|
14
|
+
ERROR = 3
|
15
|
+
|
16
|
+
# The target has at least one vulnerability.
|
17
|
+
# Currently, the interesting findings do not count as vulnerable things
|
18
|
+
VULNERABLE = 4
|
19
|
+
end
|
20
|
+
end
|
@@ -6,28 +6,35 @@ module PublicSuffix
|
|
6
6
|
name == other.name
|
7
7
|
end
|
8
8
|
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# @return [ Boolean ]
|
10
|
+
#
|
11
11
|
def match(pattern)
|
12
12
|
pattern = PublicSuffix.parse(pattern) unless pattern.is_a?(PublicSuffix::Domain)
|
13
13
|
|
14
14
|
return name == pattern.name unless pattern.trd
|
15
15
|
return false unless tld == pattern.tld && sld == pattern.sld
|
16
16
|
|
17
|
+
matching_pattern?(pattern)
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
# @rturn [ Boolean ]
|
23
|
+
def matching_pattern?(pattern)
|
17
24
|
pattern_trds = pattern.trd.split('.')
|
18
25
|
domain_trds = trd.split('.')
|
19
26
|
|
20
27
|
case pattern_trds.first
|
21
28
|
when '*'
|
22
|
-
pattern_trds[1
|
29
|
+
pattern_trds[1..-1] == domain_trds[1..-1]
|
23
30
|
when '**'
|
24
|
-
pa = pattern_trds[1
|
31
|
+
pa = pattern_trds[1..-1]
|
32
|
+
pa_size = pa.size
|
25
33
|
|
26
|
-
domain_trds[domain_trds.size -
|
34
|
+
domain_trds[domain_trds.size - pa_size, pa_size] == pa
|
27
35
|
else
|
28
36
|
name == pattern.name
|
29
37
|
end
|
30
38
|
end
|
31
|
-
# rubocop:enable all
|
32
39
|
end
|
33
40
|
end
|
data/lib/cms_scanner/target.rb
CHANGED
@@ -26,6 +26,15 @@ module CMSScanner
|
|
26
26
|
@interesting_findings ||= NS::Finders::InterestingFindings::Base.find(self, opts)
|
27
27
|
end
|
28
28
|
|
29
|
+
# Weteher or not vulnerabilities have been found.
|
30
|
+
# Used to set the exit code of the script
|
31
|
+
# and it should be overriden in the implementation
|
32
|
+
#
|
33
|
+
# @return [ Boolean ]
|
34
|
+
def vulnerable?
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
29
38
|
# @param [ Regexp ] pattern
|
30
39
|
# @param [ Typhoeus::Response, String ] page
|
31
40
|
#
|
@@ -63,13 +72,14 @@ module CMSScanner
|
|
63
72
|
|
64
73
|
next unless attr_value && !attr_value.empty?
|
65
74
|
|
66
|
-
tag_uri
|
75
|
+
tag_uri = uri.join(attr_value.strip) rescue next
|
76
|
+
tag_uri_string = tag_uri.to_s
|
67
77
|
|
68
78
|
next unless tag_uri.host
|
69
79
|
|
70
|
-
yield
|
80
|
+
yield tag_uri_string, tag if block_given? && !found.include?(tag_uri_string)
|
71
81
|
|
72
|
-
found <<
|
82
|
+
found << tag_uri_string
|
73
83
|
end
|
74
84
|
end
|
75
85
|
|
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.33
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- WPScanTeam - Erwan Le Rousseau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06
|
11
|
+
date: 2015-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opt_parse_validator
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.0.
|
19
|
+
version: 0.0.12.1
|
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.0.
|
26
|
+
version: 0.0.12.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: typhoeus
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -261,6 +261,7 @@ files:
|
|
261
261
|
- lib/cms_scanner/controller.rb
|
262
262
|
- lib/cms_scanner/controllers.rb
|
263
263
|
- lib/cms_scanner/errors/http.rb
|
264
|
+
- lib/cms_scanner/exit_code.rb
|
264
265
|
- lib/cms_scanner/finders.rb
|
265
266
|
- lib/cms_scanner/finders/finder.rb
|
266
267
|
- lib/cms_scanner/finders/finder/enumerator.rb
|