cms_scanner 0.0.2
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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.rubocop.yml +6 -0
- data/.travis.yml +14 -0
- data/Gemfile +6 -0
- data/README.md +20 -0
- data/Rakefile +9 -0
- data/app/app.rb +4 -0
- data/app/controllers.rb +2 -0
- data/app/controllers/core.rb +46 -0
- data/app/controllers/core/cli_options.rb +68 -0
- data/app/controllers/interesting_files.rb +12 -0
- data/app/finders.rb +1 -0
- data/app/finders/interesting_files.rb +21 -0
- data/app/finders/interesting_files/fantastico_fileslist.rb +23 -0
- data/app/finders/interesting_files/headers.rb +15 -0
- data/app/finders/interesting_files/robots_txt.rb +22 -0
- data/app/finders/interesting_files/search_replace_db_2.rb +28 -0
- data/app/finders/interesting_files/xml_rpc.rb +62 -0
- data/app/formatters.rb +3 -0
- data/app/formatters/cli.rb +18 -0
- data/app/formatters/cli_no_colour.rb +15 -0
- data/app/formatters/json.rb +12 -0
- data/app/models.rb +5 -0
- data/app/models/fantastico_fileslist.rb +20 -0
- data/app/models/headers.rb +37 -0
- data/app/models/interesting_file.rb +30 -0
- data/app/models/robots_txt.rb +20 -0
- data/app/models/xml_rpc.rb +35 -0
- data/app/views/cli/core/finished.erb +4 -0
- data/app/views/cli/core/started.erb +3 -0
- data/app/views/cli/interesting_files/findings.erb +19 -0
- data/app/views/cli/scan_aborted.erb +4 -0
- data/app/views/json/core/finished.erb +3 -0
- data/app/views/json/core/started.erb +3 -0
- data/app/views/json/interesting_files/findings.erb +1 -0
- data/app/views/json/scan_aborted.erb +4 -0
- data/cms_scanner.gemspec +37 -0
- data/examples/views/cli/wp_custom/test.erb +1 -0
- data/examples/views/json/wp_custom/test.erb +1 -0
- data/examples/wpscan.rb +29 -0
- data/lib/cms_scanner.rb +71 -0
- data/lib/cms_scanner/browser.rb +68 -0
- data/lib/cms_scanner/browser/actions.rb +48 -0
- data/lib/cms_scanner/browser/options.rb +53 -0
- data/lib/cms_scanner/cache/file_store.rb +75 -0
- data/lib/cms_scanner/cache/typhoeus.rb +21 -0
- data/lib/cms_scanner/controller.rb +90 -0
- data/lib/cms_scanner/controllers.rb +34 -0
- data/lib/cms_scanner/errors/auth_errors.rb +15 -0
- data/lib/cms_scanner/finders.rb +5 -0
- data/lib/cms_scanner/finders/finder.rb +27 -0
- data/lib/cms_scanner/finders/finding.rb +32 -0
- data/lib/cms_scanner/finders/findings.rb +25 -0
- data/lib/cms_scanner/finders/independent_finder.rb +30 -0
- data/lib/cms_scanner/finders/independent_finders.rb +41 -0
- data/lib/cms_scanner/formatter.rb +118 -0
- data/lib/cms_scanner/formatter/buffer.rb +15 -0
- data/lib/cms_scanner/target.rb +33 -0
- data/lib/cms_scanner/target/platform.rb +2 -0
- data/lib/cms_scanner/target/platform/php.rb +39 -0
- data/lib/cms_scanner/target/platform/wordpress.rb +35 -0
- data/lib/cms_scanner/target/platform/wordpress/custom_directories.rb +62 -0
- data/lib/cms_scanner/target/server.rb +3 -0
- data/lib/cms_scanner/target/server/apache.rb +43 -0
- data/lib/cms_scanner/target/server/generic.rb +34 -0
- data/lib/cms_scanner/target/server/iis.rb +48 -0
- data/lib/cms_scanner/version.rb +4 -0
- data/lib/cms_scanner/web_site.rb +68 -0
- data/lib/helper.rb +24 -0
- data/spec/app/controllers/core_spec.rb +152 -0
- data/spec/app/controllers/interesting_files_spec.rb +50 -0
- data/spec/app/finders/interesting_files/fantastico_fileslist_spec.rb +68 -0
- data/spec/app/finders/interesting_files/headers_spec.rb +38 -0
- data/spec/app/finders/interesting_files/robots_txt_spec.rb +56 -0
- data/spec/app/finders/interesting_files/search_replace_db_2_spec.rb +55 -0
- data/spec/app/finders/interesting_files/xml_rpc_spec.rb +138 -0
- data/spec/app/finders/interesting_files_spec.rb +13 -0
- data/spec/app/formatters/cli_no_colour_spec.rb +17 -0
- data/spec/app/formatters/cli_spec.rb +21 -0
- data/spec/app/formatters/json_spec.rb +33 -0
- data/spec/app/models/fantastico_fileslist_spec.rb +32 -0
- data/spec/app/models/headers_spec.rb +52 -0
- data/spec/app/models/interesting_file_spec.rb +51 -0
- data/spec/app/models/robots_txt_spec.rb +28 -0
- data/spec/app/models/xml_rpc_spec.rb +47 -0
- data/spec/cache/.gitignore +4 -0
- data/spec/dummy_finders.rb +41 -0
- data/spec/fixtures/interesting_files/fantastico_fileslist/fantastico_fileslist.txt +12 -0
- data/spec/fixtures/interesting_files/file.txt +4 -0
- data/spec/fixtures/interesting_files/headers/interesting.txt +14 -0
- data/spec/fixtures/interesting_files/headers/no_interesting.txt +12 -0
- data/spec/fixtures/interesting_files/robots_txt/robots.txt +10 -0
- data/spec/fixtures/interesting_files/search_replace_db_2/searchreplacedb2.php +188 -0
- data/spec/fixtures/interesting_files/xml_rpc/homepage_in_scope_pingback.html +7 -0
- data/spec/fixtures/interesting_files/xml_rpc/homepage_out_of_scope_pingback.html +7 -0
- data/spec/fixtures/interesting_files/xml_rpc/xmlrpc.php +1 -0
- data/spec/fixtures/output.txt +0 -0
- data/spec/fixtures/target/platform/php/debug_log/debug.log +2 -0
- data/spec/fixtures/target/platform/php/fpd/wp_rss_functions.php +2 -0
- data/spec/fixtures/target/platform/wordpress/custom_directories/custom_w_spaces.html +10 -0
- data/spec/fixtures/target/platform/wordpress/custom_directories/default.html +14 -0
- data/spec/fixtures/target/platform/wordpress/custom_directories/https.html +12 -0
- data/spec/fixtures/target/platform/wordpress/detection/default.html +4 -0
- data/spec/fixtures/target/platform/wordpress/detection/not_wp.html +8 -0
- data/spec/fixtures/target/platform/wordpress/detection/wp_includes.html +3 -0
- data/spec/fixtures/target/server/apache/directory_listing/2.2.16.html +15 -0
- data/spec/fixtures/target/server/generic/server/apache/basic.txt +5 -0
- data/spec/fixtures/target/server/generic/server/iis/basic.txt +6 -0
- data/spec/fixtures/target/server/generic/server/not_detected.txt +3 -0
- data/spec/fixtures/target/server/iis/directory_listing/no_parent.html +3 -0
- data/spec/fixtures/target/server/iis/directory_listing/with_parent.html +3 -0
- data/spec/fixtures/views/base/ctrl/local.erb +1 -0
- data/spec/fixtures/views/base/ctrl/test.erb +3 -0
- data/spec/fixtures/views/base/global.erb +1 -0
- data/spec/fixtures/views/base/test.erb +2 -0
- data/spec/fixtures/views/based_format/test.erb +1 -0
- data/spec/fixtures/views/json/render_me.erb +4 -0
- data/spec/lib/browser_spec.rb +141 -0
- data/spec/lib/cache/file_store_spec.rb +101 -0
- data/spec/lib/cache/typhoeus_spec.rb +30 -0
- data/spec/lib/cms_scanner_spec.rb +45 -0
- data/spec/lib/controller_spec.rb +23 -0
- data/spec/lib/controllers_spec.rb +52 -0
- data/spec/lib/finders/findings_spec.rb +49 -0
- data/spec/lib/finders/independent_finders_spec.rb +98 -0
- data/spec/lib/formatter_spec.rb +136 -0
- data/spec/lib/sub_scanner_spec.rb +27 -0
- data/spec/lib/target/platforms_spec.rb +13 -0
- data/spec/lib/target/servers_spec.rb +13 -0
- data/spec/lib/target_spec.rb +50 -0
- data/spec/lib/web_site_spec.rb +124 -0
- data/spec/shared_examples.rb +11 -0
- data/spec/shared_examples/browser_actions.rb +32 -0
- data/spec/shared_examples/finding.rb +20 -0
- data/spec/shared_examples/formatter_buffer.rb +8 -0
- data/spec/shared_examples/formatter_class_methods.rb +26 -0
- data/spec/shared_examples/independent_finder.rb +33 -0
- data/spec/shared_examples/target/platform/php.rb +58 -0
- data/spec/shared_examples/target/platform/wordpress.rb +41 -0
- data/spec/shared_examples/target/platform/wordpress/custom_directories.rb +50 -0
- data/spec/shared_examples/target/server/apache.rb +33 -0
- data/spec/shared_examples/target/server/generic.rb +34 -0
- data/spec/shared_examples/target/server/iis.rb +38 -0
- data/spec/spec_helper.rb +41 -0
- metadata +432 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<html><head><title>ex.lo - /dir/</title></head><body><H1>ex.lo - /dir/</H1><hr>
|
|
2
|
+
|
|
3
|
+
<pre><A HREF="/">[To Parent Directory]</A><br><br> 10/8/2014 11:00 PM <dir> <A HREF="/sub-dir/">sub-dir</A>10/10/2014 10:00 PM 168 <A HREF="/web.config">web.config</A><br></pre><hr></body></html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Local View
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Global View
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Override the base/test.erb
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe CMSScanner::Browser do
|
|
4
|
+
|
|
5
|
+
it_behaves_like described_class::Actions
|
|
6
|
+
|
|
7
|
+
subject(:browser) { described_class.instance(options) }
|
|
8
|
+
before { described_class.reset }
|
|
9
|
+
let(:options) { {} }
|
|
10
|
+
let(:default) do
|
|
11
|
+
{
|
|
12
|
+
ssl_verifypeer: false, ssl_verifyhost: 2,
|
|
13
|
+
headers: { 'User-Agent' => "CMSScanner v#{CMSScanner::VERSION}" }
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe '#forge_request' do
|
|
18
|
+
it 'returns a Typhoeus::Request' do
|
|
19
|
+
expect(browser.forge_request('http://example.com')).to be_a Typhoeus::Request
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe '#default_request_params' do
|
|
24
|
+
its(:default_request_params) { should eq default }
|
|
25
|
+
|
|
26
|
+
context 'when some attributes are set' do
|
|
27
|
+
let(:options) do
|
|
28
|
+
{
|
|
29
|
+
cache_ttl: 200, connect_timeout: 10,
|
|
30
|
+
http_auth: { username: 'log', password: 'pwd' },
|
|
31
|
+
cookie_jar: '/tmp/cookie_jar.txt'
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
let(:expected) do
|
|
36
|
+
default.merge(
|
|
37
|
+
cache_ttl: 200, connecttimeout: 10, userpwd: 'log:pwd',
|
|
38
|
+
cookiejar: options[:cookie_jar], cookiefile: options[:cookie_jar]
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
its(:default_request_params) { should eq expected }
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe '#request_params' do
|
|
47
|
+
context 'when no param is given' do
|
|
48
|
+
its(:request_params) { should eq default }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context 'when params are supplied' do
|
|
52
|
+
let(:params) { { another_param: true, headers: { 'Accept' => 'None' } } }
|
|
53
|
+
|
|
54
|
+
it 'merges them (headers should be correctly merged)' do
|
|
55
|
+
expect(browser.request_params(params)).to eq default
|
|
56
|
+
.merge(params) { |key, oldval, newval| key == :headers ? oldval.merge(newval) : newval }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context 'when browser options' do
|
|
60
|
+
let(:options) { { proxy: 'http://127.0.0.1:8080' } }
|
|
61
|
+
|
|
62
|
+
it 'returns the correct hash' do
|
|
63
|
+
expect(browser.request_params(params)).to eq default
|
|
64
|
+
.merge(options)
|
|
65
|
+
.merge(params) { |key, oldval, newval| key == :headers ? oldval.merge(newval) : newval }
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe '#load_options' do
|
|
72
|
+
context 'when no options' do
|
|
73
|
+
it 'does not load anything' do
|
|
74
|
+
described_class::OPTIONS.each do |sym|
|
|
75
|
+
expected = sym == :user_agent ? "CMSScanner v#{CMSScanner::VERSION}" : nil
|
|
76
|
+
|
|
77
|
+
expect(browser.send(sym)).to eq expected
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context 'when options are supplied' do
|
|
83
|
+
module CMSScanner
|
|
84
|
+
# Test accessor
|
|
85
|
+
class Browser
|
|
86
|
+
attr_accessor :test
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
let(:options) do
|
|
91
|
+
{ cache_ttl: 200, max_threads: 10, test: 'should not be set',
|
|
92
|
+
user_agent: 'UA', proxy: false }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'merges the browser options only' do
|
|
96
|
+
described_class::OPTIONS.each do |sym|
|
|
97
|
+
expected = options.key?(sym) ? options[sym] : nil
|
|
98
|
+
|
|
99
|
+
expect(browser.send(sym)).to eq expected
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
expect(browser.test).to be nil
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
describe '#hydra' do
|
|
108
|
+
context 'when #max_threads is nil' do
|
|
109
|
+
its('hydra.max_concurrency') { should eq 1 }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context 'when #max_threads' do
|
|
113
|
+
let(:options) { { max_threads: 20 } }
|
|
114
|
+
|
|
115
|
+
its('hydra.max_concurrency') { should eq options[:max_threads] }
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
describe '#max_threads=' do
|
|
120
|
+
after do
|
|
121
|
+
browser.max_threads = @threads
|
|
122
|
+
|
|
123
|
+
expect(browser.max_threads).to eq @expected
|
|
124
|
+
expect(browser.hydra.max_concurrency).to eq @expected
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context 'when <= 0' do
|
|
128
|
+
it 'sets the @threads to 1' do
|
|
129
|
+
@threads = -2
|
|
130
|
+
@expected = 1
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context 'when > 0' do
|
|
135
|
+
it 'sets the @threads' do
|
|
136
|
+
@threads = 20
|
|
137
|
+
@expected = @threads
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe CMSScanner::Cache::FileStore do
|
|
4
|
+
|
|
5
|
+
let(:cache_dir) { File.join(CACHE, 'cache_file_store') }
|
|
6
|
+
subject(:cache) { described_class.new(cache_dir) }
|
|
7
|
+
|
|
8
|
+
before { FileUtils.rm_r(cache_dir, secure: true) if Dir.exist?(cache_dir) }
|
|
9
|
+
after { cache.clean }
|
|
10
|
+
|
|
11
|
+
describe '#new, #storage_path, #serializer' do
|
|
12
|
+
its(:serializer) { should be Marshal }
|
|
13
|
+
its(:storage_path) { should eq cache_dir }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe '#clean' do
|
|
17
|
+
it 'removes all files from the cache dir' do
|
|
18
|
+
# let's create some files into the directory first
|
|
19
|
+
(0..5).each do |i|
|
|
20
|
+
File.new(File.join(cache.storage_path, "file_#{i}.txt"), File::CREAT)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
expect(count_files_in_dir(cache.storage_path, 'file_*.txt')).to eq 6
|
|
24
|
+
cache.clean
|
|
25
|
+
expect(count_files_in_dir(cache.storage_path)).to eq 0
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe '#read_entry?' do
|
|
30
|
+
let(:key) { 'key1' }
|
|
31
|
+
|
|
32
|
+
after do
|
|
33
|
+
File.write(cache.entry_expiration_path(key), @expiration) if @expiration
|
|
34
|
+
|
|
35
|
+
expect(cache.read_entry(key)).to eq @expected
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context 'when the entry does not exists' do
|
|
39
|
+
it 'returns nil' do
|
|
40
|
+
@expected = nil
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'when the file is empty (marshal data too short error)' do
|
|
45
|
+
it 'returns nil' do
|
|
46
|
+
File.new(cache.entry_path(key), File::CREAT)
|
|
47
|
+
|
|
48
|
+
@expiration = Time.now.to_i + 200
|
|
49
|
+
@expected = nil
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'when the entry has expired' do
|
|
54
|
+
it 'returns nil' do
|
|
55
|
+
@expiration = Time.now.to_i - 200
|
|
56
|
+
@expected = nil
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context 'when the entry has not expired' do
|
|
61
|
+
it 'returns the entry' do
|
|
62
|
+
File.write(cache.entry_path(key), cache.serializer.dump('testing data'))
|
|
63
|
+
|
|
64
|
+
@expiration = Time.now.to_i + 600
|
|
65
|
+
@expected = 'testing data'
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe '#write_entry' do
|
|
71
|
+
after do
|
|
72
|
+
cache.write_entry(@key, @data, @ttl)
|
|
73
|
+
expect(cache.read_entry(@key)).to eq @expected
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'should get the correct entry (string)' do
|
|
77
|
+
@ttl = 10
|
|
78
|
+
@key = 'some_key'
|
|
79
|
+
@data = 'Hello World !'
|
|
80
|
+
@expected = @data
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'when cache_ttl <= 0' do
|
|
84
|
+
it 'does not write the entry' do
|
|
85
|
+
@ttl = 0
|
|
86
|
+
@key = 'another_key'
|
|
87
|
+
@data = 'Another Hello World !'
|
|
88
|
+
@expected = nil
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context 'when cache_ttl is nil' do
|
|
93
|
+
it 'does not write the entry' do
|
|
94
|
+
@ttl = nil
|
|
95
|
+
@key = 'test'
|
|
96
|
+
@data = 'test'
|
|
97
|
+
@expected = nil
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe CMSScanner::Cache::Typhoeus do
|
|
4
|
+
|
|
5
|
+
subject(:cache) { described_class.new(cache_dir) }
|
|
6
|
+
|
|
7
|
+
let(:cache_dir) { File.join(CACHE, 'typhoeus_cache') }
|
|
8
|
+
let(:url) { 'http://example.com' }
|
|
9
|
+
let(:request) { Typhoeus::Request.new(url, cache_ttl: 20) }
|
|
10
|
+
let(:key) { request.hash.to_s }
|
|
11
|
+
|
|
12
|
+
describe '#get' do
|
|
13
|
+
it 'calls #read_entry' do
|
|
14
|
+
expect(cache).to receive(:read_entry).with(key)
|
|
15
|
+
|
|
16
|
+
cache.get(request)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '#set' do
|
|
21
|
+
let(:response) { Typhoeus::Response.new }
|
|
22
|
+
|
|
23
|
+
it 'calls #write_entry' do
|
|
24
|
+
expect(cache).to receive(:write_entry).with(key, response, request.cache_ttl)
|
|
25
|
+
|
|
26
|
+
cache.set(request, response)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module CMSScanner
|
|
4
|
+
module Controller
|
|
5
|
+
# Failure class for testing
|
|
6
|
+
class SpecFailure < Base
|
|
7
|
+
def before_scan
|
|
8
|
+
fail 'error spotted'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe CMSScanner::Scan do
|
|
15
|
+
|
|
16
|
+
subject(:scanner) { described_class.new }
|
|
17
|
+
let(:controller) { CMSScanner::Controller }
|
|
18
|
+
|
|
19
|
+
describe '#new, #controllers' do
|
|
20
|
+
its(:controllers) { should eq([controller::Core.new]) }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe '#run' do
|
|
24
|
+
it 'runs the controlllers and calls the formatter#beautify' do
|
|
25
|
+
expect(scanner.controllers).to receive(:run)
|
|
26
|
+
expect(scanner.formatter).to receive(:beautify)
|
|
27
|
+
scanner.run
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'when an error is raised during the #run' do
|
|
31
|
+
it 'aborts the scan with the associated output' do
|
|
32
|
+
scanner.controllers[0] = controller::SpecFailure.new
|
|
33
|
+
|
|
34
|
+
expect(scanner.formatter).to receive(:output)
|
|
35
|
+
.with('@scan_aborted', hash_including(:reason, :trace, :verbose))
|
|
36
|
+
|
|
37
|
+
scanner.run
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe '#datastore' do
|
|
43
|
+
its(:datastore) { should eq({}) }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe CMSScanner::Controller do
|
|
4
|
+
|
|
5
|
+
subject(:controller) { described_class::Base.new }
|
|
6
|
+
|
|
7
|
+
context 'when parsed_options' do
|
|
8
|
+
before { described_class::Base.parsed_options = parsed_options }
|
|
9
|
+
let(:parsed_options) { { url: 'http://example.com/' } }
|
|
10
|
+
|
|
11
|
+
its(:parsed_options) { should eq(parsed_options) }
|
|
12
|
+
its(:formatter) { should be_a CMSScanner::Formatter::Cli }
|
|
13
|
+
its(:target) { should be_a CMSScanner::Target }
|
|
14
|
+
|
|
15
|
+
describe '#render' do
|
|
16
|
+
it 'calls the formatter#render' do
|
|
17
|
+
expect(controller.formatter).to receive(:render).with('test', { verbose: nil }, 'base')
|
|
18
|
+
controller.render('test')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module CMSScanner
|
|
4
|
+
module Controller
|
|
5
|
+
class Spec < Base
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe CMSScanner::Controllers do
|
|
11
|
+
|
|
12
|
+
subject(:controllers) { described_class.new }
|
|
13
|
+
let(:controller_mod) { CMSScanner::Controller }
|
|
14
|
+
|
|
15
|
+
describe '#<<' do
|
|
16
|
+
its(:size) { should be 0 }
|
|
17
|
+
|
|
18
|
+
context 'when controllers are added' do
|
|
19
|
+
before { controllers << controller_mod::Spec.new << controller_mod::Base.new }
|
|
20
|
+
|
|
21
|
+
its(:size) { should be 2 }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'when a controller is added twice' do
|
|
25
|
+
before { 2.times { controllers << controller_mod::Spec.new } }
|
|
26
|
+
|
|
27
|
+
its(:size) { should be 1 }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'returns self' do
|
|
31
|
+
expect(controllers << controller_mod::Spec.new).to be_a described_class
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe '#run' do
|
|
36
|
+
it 'runs the before_scan, run and after_scan methods of each controller' do
|
|
37
|
+
spec = controller_mod::Spec.new
|
|
38
|
+
base = controller_mod::Base.new
|
|
39
|
+
|
|
40
|
+
controllers << spec << base
|
|
41
|
+
|
|
42
|
+
# TODO: Any way to test the orders ? (after_scan should reverse the order)
|
|
43
|
+
[base, spec].each do |c|
|
|
44
|
+
expect(c).to receive(:before_scan)
|
|
45
|
+
expect(c).to receive(:run)
|
|
46
|
+
expect(c).to receive(:after_scan)
|
|
47
|
+
end
|
|
48
|
+
controllers.run
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|