cms_scanner 0.0.14 → 0.0.15

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: b776de3125da0037eef520d8cf0f69caa17a9f22
4
- data.tar.gz: 1f328394f7c5395b8b3191ee37e98627f0b90d0c
3
+ metadata.gz: e4c298cb52add0fd3b06836ec3d5f5acc7fcc06c
4
+ data.tar.gz: 32c3dec825b5d3641b86938ea2641bafb34cc0bd
5
5
  SHA512:
6
- metadata.gz: f1b3aa71d953d878b8bbebdf70372ecaf7eb89352638008748d7b5cad16f4378c9ee26534042bf2c1ed32268c5f4b4e4a95ed1b88eab0186dfd0ef2bc4133d7b
7
- data.tar.gz: 1cfa9bb846e83bdf8702295f62049c175d850a9e19eae1bdc73d8a882690b298ab127056866355792f37126bd0a4257756128c5e4878d46835096f77913dcc19
6
+ metadata.gz: 4444cb50bf62d3b2715bd49054a539ae058aa234b4f27d013b6dda5fa5bfcc4664fd270e85a00f82d3de99add49729223f4f5333146262f92ad67360ea4d6665
7
+ data.tar.gz: dbd2746ebc6b5912d4bf3c828dbc413499d0b1e306dc2826dc8572017a5025adfa9a1b0c4528a49bd44ae5a704a3cee0c04e719376907679e97926913d88166d
data/.rubocop.yml CHANGED
@@ -5,6 +5,6 @@ ClassVars:
5
5
  MethodLength:
6
6
  Max: 15
7
7
  Metrics/AbcSize:
8
- Max: 20
8
+ Max: 22
9
9
  Metrics/CyclomaticComplexity:
10
10
  Max: 10
@@ -14,6 +14,8 @@ module CMSScanner
14
14
  end
15
15
 
16
16
  def before_scan
17
+ output('banner')
18
+
17
19
  setup_cache
18
20
 
19
21
  fail "The url supplied '#{target.url}' seems to be down" unless target.online?
@@ -1,4 +1,3 @@
1
- <%= render('banner') -%>
2
1
  <%= green('[+]') %> URL: <%= @url %>
3
2
  <%= green('[+]') %> Started: <%= @start_time.asctime %>
4
3
 
data/cms_scanner.gemspec CHANGED
@@ -21,12 +21,13 @@ Gem::Specification.new do |s|
21
21
  s.test_files = s.files.grep(/^(test|spec|features)\//)
22
22
  s.require_path = 'lib'
23
23
 
24
- s.add_dependency 'opt_parse_validator', '~> 0.0.8'
24
+ s.add_dependency 'opt_parse_validator', '~> 0.0.9'
25
25
  s.add_dependency 'typhoeus', '~> 0.7'
26
26
  s.add_dependency 'nokogiri', '~> 1.6'
27
27
  s.add_dependency 'addressable', '~> 2.3'
28
28
  s.add_dependency 'activesupport', '~> 4.2'
29
29
  s.add_dependency 'public_suffix', '~> 1.4'
30
+ s.add_dependency 'ruby-progressbar', '~> 1.7.1'
30
31
 
31
32
  s.add_development_dependency 'rake', '~> 10.4'
32
33
  s.add_development_dependency 'rspec', '~> 3.2'
data/lib/cms_scanner.rb CHANGED
@@ -5,6 +5,7 @@ require 'nokogiri'
5
5
  require 'active_support/inflector'
6
6
  require 'addressable/uri'
7
7
  require 'public_suffix'
8
+ require 'ruby-progressbar'
8
9
  # Standard Libs
9
10
  require 'erb'
10
11
  require 'fileutils'
@@ -57,6 +58,10 @@ module CMSScanner
57
58
  trace: e.backtrace,
58
59
  verbose: controllers.first.parsed_options[:verbose])
59
60
  ensure
61
+ # Ensures a clean abort of Hydra
62
+ Browser.instance.hydra.abort
63
+ Browser.instance.hydra.run
64
+
60
65
  formatter.beautify
61
66
  end
62
67
 
@@ -61,6 +61,11 @@ module CMSScanner
61
61
  formatter.render(*tpl_params(tpl, vars))
62
62
  end
63
63
 
64
+ # @return [ Boolean ]
65
+ def user_interaction?
66
+ formatter.user_interaction? && !parsed_options[:output]
67
+ end
68
+
64
69
  protected
65
70
 
66
71
  # @param [ String ] tpl
@@ -1,4 +1,5 @@
1
1
  require 'cms_scanner/finders/finder/smart_url_checker'
2
+ require 'cms_scanner/finders/finder/enumerator'
2
3
 
3
4
  module CMSScanner
4
5
  module Finders
@@ -0,0 +1,72 @@
1
+ module CMSScanner
2
+ module Finders
3
+ class Finder
4
+ # Module to provide an easy way to enumerate items such as plugins, themes etc
5
+ module Enumerator
6
+ # @param [ Hash ] opts
7
+ # @option opts [ Boolean ] :show_progression Wether or not to display the progress bar
8
+ # @option opts [ Regexp ] :exclude_content
9
+ #
10
+ # @yield [ Typhoeus::Response, String ]
11
+ def enumerate(opts = {})
12
+ targets = target_urls(opts)
13
+ bar = progress_bar(targets.size) if opts[:show_progression]
14
+
15
+ targets.each do |url, id|
16
+ request = browser.forge_request(url, request_params)
17
+
18
+ request.on_complete do |res|
19
+ bar.progress += 1 if opts[:show_progression]
20
+
21
+ next if target.homepage_or_404?(res)
22
+ next if opts[:exclude_content] && res.body.match(opts[:exclude_content])
23
+
24
+ yield res, id
25
+ end
26
+
27
+ hydra.queue(request)
28
+ end
29
+
30
+ hydra.run
31
+ end
32
+
33
+ # @param [ Hash ] opts
34
+ #
35
+ # @return [ Hash ]
36
+ def target_urls(_opts = {})
37
+ fail NotImplementedError
38
+ end
39
+
40
+ # @param [ Integer ] total
41
+ #
42
+ # @return [ ProgressBar ]
43
+ # :nocov:
44
+ def progress_bar(total)
45
+ ProgressBar.create(
46
+ format: '%t %a <%B> (%c / %C) %P%% %e',
47
+ title: ' ', # Used to craete a left margin
48
+ total: total
49
+ )
50
+ end
51
+ # :nocov:
52
+
53
+ # @return [ CMSScanner::Browser ]
54
+ def browser
55
+ @browser ||= NS::Browser.instance
56
+ end
57
+
58
+ def request_params
59
+ # disabling the cache, as it causes a 'stack level too deep' exception
60
+ # with a large number of requests :/
61
+ # See https://github.com/typhoeus/typhoeus/issues/408
62
+ { cache_ttl: 0 }
63
+ end
64
+
65
+ # @return [ Typhoeus::Hydra ]
66
+ def hydra
67
+ @hydra ||= browser.hydra
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -58,6 +58,11 @@ module CMSScanner
58
58
  self.class.name.demodulize.underscore
59
59
  end
60
60
 
61
+ # @return [ Boolean ]
62
+ def user_interaction?
63
+ format == 'cli'
64
+ end
65
+
61
66
  # @return [ String ] The underscored format to use as a base
62
67
  def base_format; end
63
68
 
@@ -14,13 +14,13 @@ module CMSScanner
14
14
 
15
15
  # @return [ String ] The hash of the homepage
16
16
  def homepage_hash
17
- @homepage_hash ||= Target.page_hash(url)
17
+ @homepage_hash ||= self.class.page_hash(url)
18
18
  end
19
19
 
20
20
  # @note This is used to detect potential custom 404 responding with a 200
21
21
  # @return [ String ] The hash of a 404
22
22
  def error_404_hash
23
- @error_404_hash ||= Target.page_hash(non_existant_page_url)
23
+ @error_404_hash ||= self.class.page_hash(non_existant_page_url)
24
24
  end
25
25
 
26
26
  # @return [ String ] The URL of an unlikely existant page
@@ -31,7 +31,7 @@ module CMSScanner
31
31
  # @param [ Typhoeus::Response, String ] page
32
32
  # @return [ Boolean ] Wether or not the page is a the homepage or a 404 based on its md5sum
33
33
  def homepage_or_404?(page)
34
- md5sum = Target.page_hash(page)
34
+ md5sum = self.class.page_hash(page)
35
35
 
36
36
  md5sum == homepage_hash || md5sum == error_404_hash
37
37
  end
@@ -1,4 +1,4 @@
1
1
  # Version
2
2
  module CMSScanner
3
- VERSION = '0.0.14'
3
+ VERSION = '0.0.15'
4
4
  end
@@ -36,6 +36,8 @@ describe CMSScanner::Controller::Core do
36
36
  end
37
37
 
38
38
  describe '#before_scan' do
39
+ before { expect(core.formatter).to receive(:output) }
40
+
39
41
  it 'does not raise an error when everything is fine' do
40
42
  stub_request(:get, target_url).to_return(status: 200)
41
43
 
@@ -3,9 +3,8 @@ require 'spec_helper'
3
3
  describe CMSScanner::Formatter::CliNoColour do
4
4
  subject(:formatter) { described_class.new }
5
5
 
6
- describe '#format' do
7
- its(:format) { should eq 'cli' }
8
- end
6
+ its(:format) { should eq 'cli' }
7
+ its(:user_interaction?) { should be true }
9
8
 
10
9
  describe '#colorize' do
11
10
  it 'returns the text w/o any colour' do
@@ -3,9 +3,8 @@ require 'spec_helper'
3
3
  describe CMSScanner::Formatter::Cli do
4
4
  subject(:formatter) { described_class.new }
5
5
 
6
- describe '#format' do
7
- its(:format) { should eq 'cli' }
8
- end
6
+ its(:format) { should eq 'cli' }
7
+ its(:user_interaction?) { should be true }
9
8
 
10
9
  describe '#bold, #red, #green, #amber, #blue, #colorize' do
11
10
  it 'returns the correct bold string' do
@@ -8,9 +8,8 @@ describe CMSScanner::Formatter::Json do
8
8
 
9
9
  before { formatter.views_directories << FIXTURES_VIEWS }
10
10
 
11
- describe '#format' do
12
- its(:format) { should eq 'json' }
13
- end
11
+ its(:format) { should eq 'json' }
12
+ its(:user_interaction?) { should be false }
14
13
 
15
14
  describe '#output' do
16
15
  it 'puts the rendered text in the buffer' do
@@ -21,8 +21,13 @@ describe CMSScanner::Scan do
21
21
 
22
22
  describe '#run' do
23
23
  it 'runs the controlllers and calls the formatter#beautify' do
24
+ hydra = CMSScanner::Browser.instance.hydra
25
+
24
26
  expect(scanner.controllers).to receive(:run).ordered
27
+ expect(hydra).to receive(:abort).ordered
28
+ expect(hydra).to receive(:run).ordered
25
29
  expect(scanner.formatter).to receive(:beautify).ordered
30
+
26
31
  scanner.run
27
32
  end
28
33
 
@@ -10,9 +10,16 @@ describe CMSScanner::Controller do
10
10
 
11
11
  its(:parsed_options) { should eq(parsed_options) }
12
12
  its(:formatter) { should be_a CMSScanner::Formatter::Cli }
13
+ its(:user_interaction?) { should be true }
13
14
  its(:target) { should be_a CMSScanner::Target }
14
15
  its('target.scope.domains') { should eq [PublicSuffix.parse('example.com')] }
15
16
 
17
+ context 'when output option' do
18
+ let(:parsed_options) { super().merge(output: '/tmp/spec.txt') }
19
+
20
+ its(:user_interaction?) { should be false }
21
+ end
22
+
16
23
  describe '#render' do
17
24
  it 'calls the formatter#render' do
18
25
  expect(controller.formatter).to receive(:render).with('test', { verbose: nil }, 'base')
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::Finders::Finder::Enumerator do
4
+ # Dummy class to test the module
5
+ class DummyFinder < CMSScanner::Finders::Finder
6
+ include CMSScanner::Finders::Finder::Enumerator
7
+ end
8
+
9
+ subject(:finder) { DummyFinder.new(target) }
10
+ let(:target) { CMSScanner::Target.new('http://e.org') }
11
+
12
+ context 'when #target_urls not implemented' do
13
+ it 'raises errors' do
14
+ expect { finder.target_urls }.to raise_error NotImplementedError
15
+ end
16
+ end
17
+
18
+ describe '#progress_bar' do
19
+ it 'returns a ProgressBar' do
20
+ expect(finder.progress_bar(2)).to be_a ProgressBar::Base
21
+ end
22
+ end
23
+
24
+ its(:browser) { should be_a CMSScanner::Browser }
25
+
26
+ its(:request_params) { should eql(cache_ttl: 0) }
27
+
28
+ its(:hydra) { should be_a Typhoeus::Hydra }
29
+
30
+ describe '#aggressive' do
31
+ before do
32
+ expect(finder).to receive(:target_urls).and_return(target_urls)
33
+ target_urls.each { |url, _| stub_request(:get, url).to_return(status: 200, body: 'rspec') }
34
+ end
35
+
36
+ let(:target_urls) do
37
+ {
38
+ target.url('1') => 1,
39
+ target.url('2') => 2
40
+ }
41
+ end
42
+
43
+ context 'when no opts' do
44
+ let(:opts) { {} }
45
+
46
+ context 'when response are the homepage or custom 404' do
47
+ before { expect(finder.target).to receive(:homepage_or_404?).twice.and_return(true) }
48
+
49
+ it 'does not yield anything' do
50
+ expect { |b| finder.enumerate(opts, &b) }.to_not yield_control
51
+ end
52
+ end
53
+
54
+ context 'when not the hompage or 404' do
55
+ before { expect(finder.target).to receive(:homepage_or_404?).twice }
56
+
57
+ it 'yield the expected items' do
58
+ expect { |b| finder.enumerate(opts, &b) }.to yield_successive_args(
59
+ [Typhoeus::Response, 1], [Typhoeus::Response, 2]
60
+ )
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'when opts' do
66
+ context 'when :exclude_content' do
67
+ before { expect(finder.target).to receive(:homepage_or_404?).twice }
68
+
69
+ context 'when it matches' do
70
+ let(:opts) { { exclude_content: /spec/i } }
71
+
72
+ it 'does not yield anything' do
73
+ expect { |b| finder.enumerate(opts, &b) }.to_not yield_control
74
+ end
75
+ end
76
+
77
+ context 'when it does not match' do
78
+ let(:opts) { { exclude_content: /not/i } }
79
+
80
+ it 'yield the expected items' do
81
+ expect { |b| finder.enumerate(opts, &b) }.to yield_successive_args(
82
+ [Typhoeus::Response, 1], [Typhoeus::Response, 2]
83
+ )
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -33,6 +33,18 @@ describe CMSScanner::Formatter::Base do
33
33
  its(:format) { should eq 'base' }
34
34
  end
35
35
 
36
+ describe '#user_interaction?' do
37
+ context 'when not a cli format' do
38
+ its(:user_interaction?) { should be false }
39
+ end
40
+
41
+ context 'when a cli format' do
42
+ before { expect(formatter).to receive(:format).and_return('cli') }
43
+
44
+ its(:user_interaction?) { should be true }
45
+ end
46
+ end
47
+
36
48
  describe '#render, output' do
37
49
  before { formatter.views_directories << FIXTURES_VIEWS }
38
50
 
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.14
4
+ version: 0.0.15
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-02-18 00:00:00.000000000 Z
11
+ date: 2015-02-21 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.8
19
+ version: 0.0.9
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.8
26
+ version: 0.0.9
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: typhoeus
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '1.4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: ruby-progressbar
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 1.7.1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 1.7.1
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: rake
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -253,6 +267,7 @@ files:
253
267
  - lib/cms_scanner/finders.rb
254
268
  - lib/cms_scanner/finders/confidence.rb
255
269
  - lib/cms_scanner/finders/finder.rb
270
+ - lib/cms_scanner/finders/finder/enumerator.rb
256
271
  - lib/cms_scanner/finders/finder/smart_url_checker.rb
257
272
  - lib/cms_scanner/finders/finder/smart_url_checker/findings.rb
258
273
  - lib/cms_scanner/finders/finding.rb
@@ -335,6 +350,7 @@ files:
335
350
  - spec/lib/controller_spec.rb
336
351
  - spec/lib/controllers_spec.rb
337
352
  - spec/lib/finders/confidence_spec.rb
353
+ - spec/lib/finders/finder/enumerator_spec.rb
338
354
  - spec/lib/finders/finder/smart_url_checker/findings_spec.rb
339
355
  - spec/lib/finders/finder/smart_url_checker_spec.rb
340
356
  - spec/lib/finders/findings_spec.rb
@@ -454,6 +470,7 @@ test_files:
454
470
  - spec/lib/controller_spec.rb
455
471
  - spec/lib/controllers_spec.rb
456
472
  - spec/lib/finders/confidence_spec.rb
473
+ - spec/lib/finders/finder/enumerator_spec.rb
457
474
  - spec/lib/finders/finder/smart_url_checker/findings_spec.rb
458
475
  - spec/lib/finders/finder/smart_url_checker_spec.rb
459
476
  - spec/lib/finders/findings_spec.rb