cms_scanner 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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,11 @@
|
|
1
|
+
|
2
|
+
require 'shared_examples/browser_actions'
|
3
|
+
require 'shared_examples/formatter_buffer'
|
4
|
+
require 'shared_examples/formatter_class_methods'
|
5
|
+
require 'shared_examples/finding'
|
6
|
+
require 'shared_examples/independent_finder'
|
7
|
+
require 'shared_examples/target/platform/wordpress'
|
8
|
+
require 'shared_examples/target/platform/php'
|
9
|
+
require 'shared_examples/target/server/generic'
|
10
|
+
require 'shared_examples/target/server/apache'
|
11
|
+
require 'shared_examples/target/server/iis'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
shared_examples CMSScanner::Browser::Actions do
|
3
|
+
|
4
|
+
let(:url) { 'http://example.com/file.txt' }
|
5
|
+
let(:browser) { CMSScanner::Browser }
|
6
|
+
|
7
|
+
describe '#get, #post, #head' do
|
8
|
+
[:get, :post, :head].each do |method|
|
9
|
+
it 'calls the method and returns a Typhoeus::Response' do
|
10
|
+
stub_request(method, url)
|
11
|
+
|
12
|
+
expect(browser.send(method, url)).to be_a Typhoeus::Response
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#get_and_follow_location' do
|
18
|
+
let(:redirection) { 'http://redirect.me' }
|
19
|
+
|
20
|
+
it 'follows the location' do
|
21
|
+
stub_request(:get, url).to_return(status: 301, headers: { location: redirection })
|
22
|
+
stub_request(:get, redirection).to_return(status: 200, body: 'Got me')
|
23
|
+
|
24
|
+
response = browser.get_and_follow_location(url)
|
25
|
+
expect(response).to be_a Typhoeus::Response
|
26
|
+
# Line below is not working due to an issue in Typhoeus/Webmock
|
27
|
+
# See https://github.com/typhoeus/typhoeus/issues/279
|
28
|
+
# expect(response.body).to eq 'Got me'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
shared_examples CMSScanner::Finders::Finding do
|
3
|
+
|
4
|
+
[:references, :confirmed_by, :interesting_entries].each do |opt|
|
5
|
+
describe "##{opt}" do
|
6
|
+
its(opt) { should eq [] }
|
7
|
+
|
8
|
+
context 'when supplied in the #new' do
|
9
|
+
let(:opts) { { opt => 'test' } }
|
10
|
+
|
11
|
+
its(opt) { should eq 'test' }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#parse_finding_options' do
|
17
|
+
xit
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
shared_examples CMSScanner::Formatter::ClassMethods do
|
3
|
+
describe '#load' do
|
4
|
+
context 'w/o parameter' do
|
5
|
+
it 'loads the default formatter' do
|
6
|
+
expect(subject.load).to be_a subject::Cli
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'loads the correct formatter' do
|
11
|
+
expect(subject.load('cli_no_colour')).to be_a subject::CliNoColour
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'adds the custom_views' do
|
15
|
+
formatter = subject.load(nil, %w(/path/views1 /path2/views))
|
16
|
+
|
17
|
+
expect(formatter.views_directories).to include('/path/views1', '/path2/views')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#availables' do
|
22
|
+
it 'returns the right list' do
|
23
|
+
expect(subject.availables).to match_array(%w(json cli-no-colour cli))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
shared_examples CMSScanner::Finders::IndependentFinder do
|
3
|
+
|
4
|
+
describe '::find' do
|
5
|
+
it 'creates a new object and call finders#find' do
|
6
|
+
created = described_class.new(target)
|
7
|
+
|
8
|
+
expect(described_class).to receive(:new).and_return(created)
|
9
|
+
expect(created).to receive(:find)
|
10
|
+
|
11
|
+
described_class.find(target)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#find' do
|
16
|
+
it 'calls finders#run' do
|
17
|
+
expect(subject.finders).to receive(:run).with({})
|
18
|
+
subject.find
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#finders' do
|
23
|
+
its(:finders) { should be_a CMSScanner::Finders::IndependentFinders }
|
24
|
+
|
25
|
+
it 'returns the correct finders' do
|
26
|
+
finders = subject.finders
|
27
|
+
|
28
|
+
expect(finders.size).to eq expected_finders.size
|
29
|
+
expect(finders.map { |f| f.class.to_s.demodulize }).to eq expected_finders
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
shared_examples CMSScanner::Target::Platform::PHP do
|
3
|
+
|
4
|
+
before { stub_request(:get, target.url(path)).to_return(body: body) }
|
5
|
+
|
6
|
+
describe '#debug_log?' do
|
7
|
+
let(:path) { 'd.log' }
|
8
|
+
|
9
|
+
context 'when the body matches' do
|
10
|
+
%w(debug.log).each do |file|
|
11
|
+
context "when #{file} body" do
|
12
|
+
let(:body) { File.read(File.join(fixtures, 'debug_log', file)) }
|
13
|
+
|
14
|
+
it 'returns true' do
|
15
|
+
expect(target.debug_log?(path)).to be true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when the body does not match' do
|
22
|
+
let(:body) { '' }
|
23
|
+
|
24
|
+
it 'returns false' do
|
25
|
+
expect(target.debug_log?(path)).to be false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#full_path_disclosure?, #full_path_disclosure_entries' do
|
31
|
+
let(:path) { 'p.php' }
|
32
|
+
|
33
|
+
context 'when the body matches a FPD' do
|
34
|
+
{
|
35
|
+
'wp_rss_functions.php' => %w(/short-path/rss-f.php)
|
36
|
+
}
|
37
|
+
.each do |file, expected|
|
38
|
+
context "when #{file} body" do
|
39
|
+
let(:body) { File.read(File.join(fixtures, 'fpd', file)) }
|
40
|
+
|
41
|
+
it 'returns the expected array' do
|
42
|
+
expect(target.full_path_disclosure_entries(path)).to eql expected
|
43
|
+
expect(target.full_path_disclosure?(path)).to be true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when no FPD' do
|
50
|
+
let(:body) { '' }
|
51
|
+
|
52
|
+
it 'returns an empty array' do
|
53
|
+
expect(target.full_path_disclosure_entries(path)).to eq []
|
54
|
+
expect(target.full_path_disclosure?(path)).to be false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative 'wordpress/custom_directories'
|
2
|
+
|
3
|
+
shared_examples CMSScanner::Target::Platform::WordPress do
|
4
|
+
|
5
|
+
it_behaves_like 'WordPress::CustomDirectories'
|
6
|
+
|
7
|
+
describe '#wordpress?' do
|
8
|
+
let(:fixtures) { File.join(super(), 'detection') }
|
9
|
+
|
10
|
+
before do
|
11
|
+
stub_request(:get, target.url).to_return(body: File.read(File.join(fixtures, "#{body}.html")))
|
12
|
+
end
|
13
|
+
|
14
|
+
%w(default wp_includes).each do |file|
|
15
|
+
context "when a wordpress page (#{file}.html)" do
|
16
|
+
let(:body) { file }
|
17
|
+
|
18
|
+
its(:wordpress?) { should be true }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
%w(not_wp).each do |file|
|
23
|
+
context "when not a wordpress page (#{file}.html)" do
|
24
|
+
let(:body) { file }
|
25
|
+
|
26
|
+
its(:wordpress?) { should be false }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#wordpress_hosted?' do
|
32
|
+
its(:wordpress_hosted?) { should be false }
|
33
|
+
|
34
|
+
context 'when the target host matches' do
|
35
|
+
let(:url) { 'http://ex.wordpress.com' }
|
36
|
+
|
37
|
+
its(:wordpress_hosted?) { should be true }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
shared_examples 'WordPress::CustomDirectories' do
|
3
|
+
let(:fixtures) { File.join(super(), 'custom_directories') }
|
4
|
+
|
5
|
+
describe '#content_dir' do
|
6
|
+
{
|
7
|
+
default: 'wp-content', https: 'wp-content', custom_w_spaces: 'custom content spaces'
|
8
|
+
}
|
9
|
+
.each do |file, expected|
|
10
|
+
it "returns #{expected} for #{file}.html" do
|
11
|
+
fixture = File.join(fixtures, "#{file}.html")
|
12
|
+
|
13
|
+
stub_request(:get, target.url).to_return(body: File.read(fixture))
|
14
|
+
|
15
|
+
expect(target.content_dir).to eql expected
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#content_dir=, #plugins_dir=' do
|
21
|
+
['wp-content' 'wp-custom'].each do |dir|
|
22
|
+
context "when content_dir = #{dir} and no plugins_dir" do
|
23
|
+
before { target.content_dir = dir }
|
24
|
+
|
25
|
+
its(:content_dir) { should eq dir.chomp('/') }
|
26
|
+
its(:plugins_dir) { should eq dir.chomp('/') + '/plugins' }
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when content_dir = #{dir} and plugins_dir = #{dir}" do
|
30
|
+
before do
|
31
|
+
target.content_dir = dir
|
32
|
+
target.plugins_dir = dir
|
33
|
+
end
|
34
|
+
|
35
|
+
its(:content_dir) { should eq dir.chomp('/') }
|
36
|
+
its(:plugins_dir) { should eq dir.chomp('/') }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#content_uri, #content_url, #plugins_uri, #plugins_url' do
|
42
|
+
before { target.content_dir = 'wp-content' }
|
43
|
+
|
44
|
+
its(:content_uri) { should eq Addressable::URI.parse("#{url}/wp-content/") }
|
45
|
+
its(:content_url) { should eq "#{url}/wp-content/" }
|
46
|
+
|
47
|
+
its(:plugins_uri) { should eq Addressable::URI.parse("#{url}/wp-content/plugins/") }
|
48
|
+
its(:plugins_url) { should eq "#{url}/wp-content/plugins/" }
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples CMSScanner::Target::Server::Apache do
|
4
|
+
|
5
|
+
describe '#server' do
|
6
|
+
its(:server) { should eq :Apache }
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#directory_listing?, #directory_listing_entries' do
|
10
|
+
before { stub_request(:get, target.url(path)).to_return(body: body, status: status) }
|
11
|
+
let(:path) { 'somedir' }
|
12
|
+
|
13
|
+
context 'when not a 200' do
|
14
|
+
let(:status) { 404 }
|
15
|
+
let(:body) { '' }
|
16
|
+
|
17
|
+
it 'returns false and an empty array' do
|
18
|
+
expect(target.directory_listing?(path)).to be false
|
19
|
+
expect(target.directory_listing_entries(path)).to eql []
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when 200' do
|
24
|
+
let(:status) { 200 }
|
25
|
+
let(:body) { File.read(File.join(fixtures, 'directory_listing', '2.2.16.html')) }
|
26
|
+
|
27
|
+
it 'returns true and the expected array' do
|
28
|
+
expect(target.directory_listing?(path)).to be true
|
29
|
+
expect(target.directory_listing_entries(path)).to eq %w(backup.php database-empty.php)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples CMSScanner::Target::Server::Generic do
|
4
|
+
|
5
|
+
describe '#server' do
|
6
|
+
before { stub_request(:head, target.url).to_return(headers: parse_headers_file(fixture)) }
|
7
|
+
|
8
|
+
context 'when apache headers' do
|
9
|
+
%w(basic.txt).each do |file|
|
10
|
+
context "when #{file} headers" do
|
11
|
+
let(:fixture) { File.join(fixtures, 'server', 'apache', file) }
|
12
|
+
|
13
|
+
its(:server) { should eq :Apache }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when iis headers' do
|
19
|
+
%w(basic.txt).each do |file|
|
20
|
+
context "when #{file} headers" do
|
21
|
+
let(:fixture) { File.join(fixtures, 'server', 'iis', file) }
|
22
|
+
|
23
|
+
its(:server) { should eq :IIS }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'not detected' do
|
29
|
+
let(:fixture) { File.join(fixtures, 'server', 'not_detected.txt') }
|
30
|
+
|
31
|
+
its(:server) { should be nil }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples CMSScanner::Target::Server::IIS do
|
4
|
+
|
5
|
+
describe '#server' do
|
6
|
+
its(:server) { should eq :IIS }
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#directory_listing?, #directory_listing_entries' do
|
10
|
+
before { stub_request(:get, target.url(path)).to_return(body: body, status: status) }
|
11
|
+
let(:path) { 'dir' }
|
12
|
+
|
13
|
+
context 'when not a 200' do
|
14
|
+
let(:status) { 404 }
|
15
|
+
let(:body) { '' }
|
16
|
+
|
17
|
+
it 'returns false and an empty array' do
|
18
|
+
expect(target.directory_listing?(path)).to be false
|
19
|
+
expect(target.directory_listing_entries(path)).to eql []
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when 200' do
|
24
|
+
let(:status) { 200 }
|
25
|
+
|
26
|
+
%w(with_parent.html no_parent.html).each do |file|
|
27
|
+
context "when #{file} body" do
|
28
|
+
let(:body) { File.read(File.join(fixtures, 'directory_listing', file)) }
|
29
|
+
|
30
|
+
it 'returns true and the expected array' do
|
31
|
+
expect(target.directory_listing?(path)).to be true
|
32
|
+
expect(target.directory_listing_entries(path)).to eq %w(sub-dir web.config)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
|
3
|
+
require 'simplecov'
|
4
|
+
require 'rspec/its'
|
5
|
+
require 'webmock/rspec'
|
6
|
+
|
7
|
+
if ENV['TRAVIS']
|
8
|
+
require 'coveralls'
|
9
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
10
|
+
end
|
11
|
+
|
12
|
+
SimpleCov.start do
|
13
|
+
add_filter '/spec/'
|
14
|
+
add_filter 'helper'
|
15
|
+
end
|
16
|
+
|
17
|
+
# See http://betterspecs.org/
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.expect_with :rspec do |c|
|
20
|
+
c.syntax = :expect
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def count_files_in_dir(absolute_dir_path, files_pattern = '*')
|
25
|
+
Dir.glob(File.join(absolute_dir_path, files_pattern)).count
|
26
|
+
end
|
27
|
+
|
28
|
+
# Parse a file containing raw headers and return the associated Hash
|
29
|
+
# @return [ Hash ]
|
30
|
+
def parse_headers_file(filepath)
|
31
|
+
Typhoeus::Response::Header.new(File.read(filepath))
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'cms_scanner'
|
35
|
+
require 'shared_examples'
|
36
|
+
|
37
|
+
SPECS = Pathname.new(__FILE__).dirname.to_s
|
38
|
+
CACHE = File.join(SPECS, 'cache')
|
39
|
+
FIXTURES = File.join(SPECS, 'fixtures')
|
40
|
+
FIXTURES_VIEWS = File.join(FIXTURES, 'views')
|
41
|
+
APP_VIEWS = File.join(CMSScanner::APP_DIR, 'views')
|