cms_scanner 0.0.36 → 0.0.37

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
  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