cms_scanner 0.0.36 → 0.0.37

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
  SHA1:
3
- metadata.gz: 4bfb8bab5a963e2803fa4991564f4affe3e7415d
4
- data.tar.gz: 50faf8b01e45138166d74d3b4d769dbf5bf828ea
3
+ metadata.gz: acd54c82dac47f135bd9a9eb739493617a114f8c
4
+ data.tar.gz: 0cd17341caa2bd782beb2d07b2666d2dbf132d06
5
5
  SHA512:
6
- metadata.gz: a49537023c9c2ba55ab12641dc6fb9407e357e88ca358b1c9428d533bb984df8f1f6e07e7218c9195cd9459f20da24c4f4e268c63ae30bc75a083db5fae58309
7
- data.tar.gz: 7ad19781bcda3f02d744eb0eceb0b3e43289cc3d323950df3b2060b051426053cf1ef3957c9ae5df417ce5f18006881e908b3cbcca6b9e63afc1981a07856d77
6
+ metadata.gz: d5d16f8d26a3873ea5a76c09c48e69f4c67f1dddca9e30a41f775060cccb4543b998845133be7ee937bb21bc0cb63dcf8523c12facc5e773fb8959d20ba5b752
7
+ data.tar.gz: 581b8ea2a409f4854fbbb214f09b3c3dc7cb00c308665a9545bef7e507475da3da3d56841ee4e6022adb903d66f37fa771610ae3c8d4879f24b15ca9e64c8fb4
@@ -18,11 +18,25 @@ module CMSScanner
18
18
 
19
19
  setup_cache
20
20
 
21
- fail "The url supplied '#{target.url}' seems to be down" unless target.online?
21
+ check_target_availability
22
+ end
22
23
 
23
- fail AccessForbiddenError if target.access_forbidden?
24
- fail HTTPAuthRequiredError if target.http_auth?
25
- fail ProxyAuthRequiredError if target.proxy_auth?
24
+ # Checks that the target is accessible, raises related errors otherwise
25
+ #
26
+ # @return [ Void ]
27
+ def check_target_availability
28
+ res = NS::Browser.get(target.url)
29
+
30
+ case res.code
31
+ when 0
32
+ fail TargetDownError, res
33
+ when 401
34
+ fail HTTPAuthRequiredError
35
+ when 403
36
+ fail AccessForbiddenError
37
+ when 407
38
+ fail ProxyAuthRequiredError
39
+ end
26
40
 
27
41
  redirection = target.redirection
28
42
  fail HTTPRedirectError, redirection if redirection && !parsed_options[:ignore_main_redirect]
@@ -34,6 +34,8 @@ module CMSScanner
34
34
  OptCredentials.new(['--http-auth login:password']),
35
35
  OptPositiveInteger.new(['--max-threads VALUE', '-t', 'The max threads to use'],
36
36
  default: 5),
37
+ OptPositiveInteger.new(['--throttle MilliSeconds', 'Milliseconds to wait before doing another web request. ' \
38
+ 'If used, the max threads will be set to 1.']),
37
39
  OptPositiveInteger.new(['--request-timeout SECONDS', 'The request timeout in seconds'],
38
40
  default: 60),
39
41
  OptPositiveInteger.new(['--connect-timeout SECONDS', 'The connection timeout in seconds'],
@@ -26,13 +26,14 @@ module CMSScanner
26
26
  res.body.split("\n").reject { |s| s.strip.empty? }
27
27
  end
28
28
 
29
+ # @return [ String ]
29
30
  def to_s
30
31
  @to_s || url
31
32
  end
32
33
 
34
+ # @return [ Bollean ]
33
35
  def ==(other)
34
- return false unless self.class == other.class
35
- to_s == other.to_s
36
+ self.class == other.class && to_s == other.to_s
36
37
  end
37
38
  end
38
39
  end
@@ -14,7 +14,8 @@ module CMSScanner
14
14
 
15
15
  results << match
16
16
  end
17
- results
17
+
18
+ results.uniq
18
19
  end
19
20
  end
20
21
  end
@@ -1,9 +1,9 @@
1
- "interesting_findings": [
1
+ "interesting_findings": {
2
2
  <% unless @findings.empty? -%>
3
- {
4
3
  <% last_index = @findings.size - 1 %>
5
4
  <% @findings.each.with_index do |finding, index| -%>
6
- <%= finding.url.to_s.to_json %>: {
5
+ <%= finding.to_s.to_json %>: {
6
+ "url": <%= finding.url.to_s.to_json %>,
7
7
  "found_by": <%= finding.found_by.to_s.to_json %>,
8
8
  "confidence": <%= finding.confidence.to_json %>,
9
9
  "confirmed_by": [
@@ -20,6 +20,5 @@
20
20
  "interesting_entries": <%= finding.interesting_entries.to_json %>
21
21
  }<% unless index == last_index %>,<% end %>
22
22
  <% end -%>
23
- }
24
23
  <% end -%>
25
- ],
24
+ },
data/cms_scanner.gemspec CHANGED
@@ -31,19 +31,20 @@ 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.13'
35
- s.add_dependency 'typhoeus', '~> 0.7'
34
+ s.add_dependency 'typhoeus', '~> 0.8'
36
35
  s.add_dependency 'nokogiri', '~> 1.6.6'
36
+ s.add_dependency 'yajl-ruby', '~> 1.2.1' # Better JSON parser regarding memory usage
37
37
  s.add_dependency 'addressable', '~> 2.3.8'
38
38
  s.add_dependency 'activesupport', '~> 4.2'
39
39
  s.add_dependency 'public_suffix', '~> 1.5'
40
40
  s.add_dependency 'ruby-progressbar', '~> 1.7.5'
41
+ s.add_dependency 'opt_parse_validator', '~> 0.0.13'
41
42
 
42
43
  s.add_development_dependency 'rake', '~> 10.4.2'
43
44
  s.add_development_dependency 'rspec', '~> 3.3'
44
45
  s.add_development_dependency 'rspec-its', '~> 1.2'
45
46
  s.add_development_dependency 'bundler', '~> 1.6'
46
- s.add_development_dependency 'rubocop', '~> 0.32'
47
- s.add_development_dependency 'webmock', '~> 1.21'
47
+ s.add_development_dependency 'rubocop', '~> 0.34'
48
+ s.add_development_dependency 'webmock', '~> 1.22'
48
49
  s.add_development_dependency 'simplecov', '~> 0.10'
49
50
  end
data/lib/cms_scanner.rb CHANGED
@@ -1,12 +1,13 @@
1
1
  # Gems
2
- require 'opt_parse_validator'
3
2
  require 'typhoeus'
4
3
  require 'nokogiri'
5
- require 'active_support/inflector'
6
- require 'active_support/concern'
7
- require 'addressable/uri'
4
+ require 'yajl/json_gem'
8
5
  require 'public_suffix'
6
+ require 'addressable/uri'
9
7
  require 'ruby-progressbar'
8
+ require 'opt_parse_validator'
9
+ require 'active_support/concern'
10
+ require 'active_support/inflector'
10
11
  # Standard Libs
11
12
  require 'erb'
12
13
  require 'uri'
@@ -38,7 +39,11 @@ module CMSScanner
38
39
 
39
40
  # Number of requests performed to display at the end of the scan
40
41
  Typhoeus.on_complete do |response|
41
- self.total_requests += 1 unless response.cached?
42
+ next if response.cached?
43
+
44
+ self.total_requests += 1
45
+
46
+ NS::Browser.instance.trottle!
42
47
  end
43
48
 
44
49
  # Module to be able to use these class methods when the CMSScanner
@@ -10,6 +10,8 @@ module CMSScanner
10
10
  #
11
11
  # @return [ Void ]
12
12
  def initialize(parsed_options = {})
13
+ self.throttle = 0
14
+
13
15
  load_options(parsed_options)
14
16
  end
15
17
 
@@ -12,6 +12,7 @@ module CMSScanner
12
12
  :proxy_auth,
13
13
  :random_user_agent,
14
14
  :request_timeout,
15
+ :throttle,
15
16
  :user_agent,
16
17
  :user_agents_list,
17
18
  :vhost
@@ -19,6 +20,15 @@ module CMSScanner
19
20
 
20
21
  attr_accessor(*OPTIONS)
21
22
 
23
+ # @return [ String ]
24
+ def default_user_agent
25
+ "#{NS} v#{NS::VERSION}"
26
+ end
27
+
28
+ def hydra
29
+ @hydra ||= Typhoeus::Hydra.new(max_concurrency: max_threads || 1)
30
+ end
31
+
22
32
  # @param [ Hash ] options
23
33
  def load_options(options = {})
24
34
  OPTIONS.each do |sym|
@@ -26,22 +36,21 @@ module CMSScanner
26
36
  end
27
37
  end
28
38
 
29
- def hydra
30
- @hydra ||= Typhoeus::Hydra.new(max_concurrency: max_threads || 1)
31
- end
32
-
33
39
  # Set the threads attribute and update
34
40
  # the max_concurrency of Typhoeus::Hydra
35
41
  #
42
+ # If the throttle attribute is > 0, max_threads will be forced to 1
43
+ #
36
44
  # @param [ Integer ] number
37
45
  def max_threads=(number)
38
- @max_threads = number.to_i > 0 ? number.to_i : 1
46
+ @max_threads = number.to_i > 0 && throttle == 0 ? number.to_i : 1
47
+
39
48
  hydra.max_concurrency = @max_threads
40
49
  end
41
50
 
42
- # @return [ String ] The path to the user agents list
43
- def user_agents_list
44
- @user_agents_list ||= File.join(APP_DIR, 'user_agents.txt')
51
+ # @return [ String ] The user agent
52
+ def user_agent
53
+ @user_agent ||= random_user_agent ? user_agents.sample : default_user_agent
45
54
  end
46
55
 
47
56
  # @return [ Array<String> ]
@@ -58,14 +67,22 @@ module CMSScanner
58
67
  @user_agents
59
68
  end
60
69
 
61
- # @return [ String ]
62
- def default_user_agent
63
- "#{NS} v#{NS::VERSION}"
70
+ # @return [ String ] The path to the user agents list
71
+ def user_agents_list
72
+ @user_agents_list ||= File.join(APP_DIR, 'user_agents.txt')
64
73
  end
65
74
 
66
- # @return [ String ] The user agent
67
- def user_agent
68
- @user_agent ||= random_user_agent ? user_agents.sample : default_user_agent
75
+ # @param [ value ] The throttle time in milliseconds
76
+ #
77
+ # if value > 0, the max_threads will be set to 1
78
+ def throttle=(value)
79
+ @throttle = value.to_i.abs / 1000.0
80
+
81
+ self.max_threads = 1 if @throttle > 0
82
+ end
83
+
84
+ def trottle!
85
+ sleep(throttle) if throttle > 0
69
86
  end
70
87
  end
71
88
  end
@@ -1,5 +1,18 @@
1
1
  module CMSScanner
2
- class Error < RuntimeError
2
+ class Error < StandardError
3
+ end
4
+
5
+ # Target Down Error
6
+ class TargetDownError < Error
7
+ attr_reader :response
8
+
9
+ def initialize(response)
10
+ @response = response
11
+ end
12
+
13
+ def to_s
14
+ "The url supplied '#{response.request.url}' seems to be down (#{response.return_message})"
15
+ end
3
16
  end
4
17
 
5
18
  # HTTP Authentication Required Error
@@ -14,7 +14,7 @@ module CMSScanner
14
14
  format ||= 'cli'
15
15
  custom_views ||= []
16
16
 
17
- f = const_get(format.gsub(/-/, '_').camelize).new
17
+ f = const_get(format.tr('-', '_').camelize).new
18
18
  custom_views.each { |v| f.views_directories << v }
19
19
  f
20
20
  end
@@ -1,4 +1,4 @@
1
1
  # Version
2
2
  module CMSScanner
3
- VERSION = '0.0.36'
3
+ VERSION = '0.0.37'
4
4
  end
@@ -77,7 +77,7 @@ module CMSScanner
77
77
 
78
78
  return unless [301, 302].include?(NS::Browser.get(url).code)
79
79
 
80
- res = NS::Browser.get(url, followlocation: true)
80
+ res = NS::Browser.get(url, followlocation: true)
81
81
 
82
82
  res.effective_url == url ? nil : res.effective_url
83
83
  end
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cms_scanner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.36
4
+ version: 0.0.37
5
5
  platform: ruby
6
6
  authors:
7
7
  - WPScanTeam
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-23 00:00:00.000000000 Z
11
+ date: 2015-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: opt_parse_validator
14
+ name: typhoeus
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.0.13
19
+ version: '0.8'
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.13
26
+ version: '0.8'
27
27
  - !ruby/object:Gem::Dependency
28
- name: typhoeus
28
+ name: nokogiri
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.7'
33
+ version: 1.6.6
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.7'
40
+ version: 1.6.6
41
41
  - !ruby/object:Gem::Dependency
42
- name: nokogiri
42
+ name: yajl-ruby
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.6.6
47
+ version: 1.2.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.6.6
54
+ version: 1.2.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: addressable
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: 1.7.5
111
+ - !ruby/object:Gem::Dependency
112
+ name: opt_parse_validator
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.0.13
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.0.13
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: rake
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -170,28 +184,28 @@ dependencies:
170
184
  requirements:
171
185
  - - "~>"
172
186
  - !ruby/object:Gem::Version
173
- version: '0.32'
187
+ version: '0.34'
174
188
  type: :development
175
189
  prerelease: false
176
190
  version_requirements: !ruby/object:Gem::Requirement
177
191
  requirements:
178
192
  - - "~>"
179
193
  - !ruby/object:Gem::Version
180
- version: '0.32'
194
+ version: '0.34'
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: webmock
183
197
  requirement: !ruby/object:Gem::Requirement
184
198
  requirements:
185
199
  - - "~>"
186
200
  - !ruby/object:Gem::Version
187
- version: '1.21'
201
+ version: '1.22'
188
202
  type: :development
189
203
  prerelease: false
190
204
  version_requirements: !ruby/object:Gem::Requirement
191
205
  requirements:
192
206
  - - "~>"
193
207
  - !ruby/object:Gem::Version
194
- version: '1.21'
208
+ version: '1.22'
195
209
  - !ruby/object:Gem::Dependency
196
210
  name: simplecov
197
211
  requirement: !ruby/object:Gem::Requirement