cms_scanner 0.0.18 → 0.0.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/core.rb +4 -3
  3. data/app/views/cli/core/finished.erb +1 -0
  4. data/app/views/json/core/finished.erb +1 -0
  5. data/cms_scanner.gemspec +13 -3
  6. data/lib/cms_scanner.rb +14 -2
  7. data/lib/cms_scanner/finders/finder.rb +16 -7
  8. data/lib/cms_scanner/finders/finder/enumerator.rb +4 -28
  9. data/lib/cms_scanner/finders/finder/fingerprinter.rb +60 -0
  10. data/lib/cms_scanner/finders/finding.rb +1 -1
  11. data/lib/cms_scanner/target/scope.rb +4 -1
  12. data/lib/cms_scanner/target/server/generic.rb +1 -1
  13. data/lib/cms_scanner/typhoeus/hydra.rb +10 -0
  14. data/lib/cms_scanner/version.rb +1 -1
  15. metadata +5 -203
  16. data/.gitignore +0 -7
  17. data/.rspec +0 -2
  18. data/.rubocop.yml +0 -10
  19. data/.travis.yml +0 -17
  20. data/Gemfile +0 -6
  21. data/Rakefile +0 -9
  22. data/spec/app/controllers/core_spec.rb +0 -167
  23. data/spec/app/controllers/interesting_files_spec.rb +0 -70
  24. data/spec/app/finders/interesting_files/fantastico_fileslist_spec.rb +0 -66
  25. data/spec/app/finders/interesting_files/headers_spec.rb +0 -36
  26. data/spec/app/finders/interesting_files/robots_txt_spec.rb +0 -54
  27. data/spec/app/finders/interesting_files/search_replace_db_2_spec.rb +0 -53
  28. data/spec/app/finders/interesting_files/xml_rpc_spec.rb +0 -136
  29. data/spec/app/finders/interesting_files_spec.rb +0 -12
  30. data/spec/app/formatters/cli_no_colour_spec.rb +0 -14
  31. data/spec/app/formatters/cli_spec.rb +0 -30
  32. data/spec/app/formatters/json_spec.rb +0 -30
  33. data/spec/app/models/fantastico_fileslist_spec.rb +0 -31
  34. data/spec/app/models/headers_spec.rb +0 -51
  35. data/spec/app/models/interesting_file_spec.rb +0 -69
  36. data/spec/app/models/robots_txt_spec.rb +0 -27
  37. data/spec/app/models/version_spec.rb +0 -51
  38. data/spec/app/models/xml_rpc_spec.rb +0 -46
  39. data/spec/app/views_spec.rb +0 -35
  40. data/spec/cache/.gitignore +0 -4
  41. data/spec/dummy_finding.rb +0 -25
  42. data/spec/dummy_independent_finders.rb +0 -26
  43. data/spec/dummy_unique_finders.rb +0 -33
  44. data/spec/fixtures/finders/interesting_files/fantastico_fileslist/fantastico_fileslist.txt +0 -12
  45. data/spec/fixtures/finders/interesting_files/file.txt +0 -4
  46. data/spec/fixtures/finders/interesting_files/headers/interesting.txt +0 -16
  47. data/spec/fixtures/finders/interesting_files/headers/no_interesting.txt +0 -12
  48. data/spec/fixtures/finders/interesting_files/robots_txt/robots.txt +0 -10
  49. data/spec/fixtures/finders/interesting_files/search_replace_db_2/searchreplacedb2.php +0 -188
  50. data/spec/fixtures/finders/interesting_files/xml_rpc/homepage_in_scope_pingback.html +0 -7
  51. data/spec/fixtures/finders/interesting_files/xml_rpc/homepage_out_of_scope_pingback.html +0 -7
  52. data/spec/fixtures/finders/interesting_files/xml_rpc/xmlrpc.php +0 -1
  53. data/spec/fixtures/output.txt +0 -0
  54. data/spec/fixtures/target/comments.html +0 -29
  55. data/spec/fixtures/target/platform/php/debug_log/debug.log +0 -2
  56. data/spec/fixtures/target/platform/php/fpd/wp_rss_functions.php +0 -2
  57. data/spec/fixtures/target/scope/index.html +0 -23
  58. data/spec/fixtures/target/server/apache/directory_listing/2.2.16.html +0 -15
  59. data/spec/fixtures/target/server/generic/server/apache/basic.txt +0 -5
  60. data/spec/fixtures/target/server/generic/server/iis/basic.txt +0 -6
  61. data/spec/fixtures/target/server/generic/server/not_detected.txt +0 -3
  62. data/spec/fixtures/target/server/iis/directory_listing/no_parent.html +0 -3
  63. data/spec/fixtures/target/server/iis/directory_listing/with_parent.html +0 -3
  64. data/spec/fixtures/views/base/ctrl/local.erb +0 -1
  65. data/spec/fixtures/views/base/ctrl/test.erb +0 -3
  66. data/spec/fixtures/views/base/global.erb +0 -1
  67. data/spec/fixtures/views/base/test.erb +0 -2
  68. data/spec/fixtures/views/based_format/test.erb +0 -1
  69. data/spec/fixtures/views/json/render_me.erb +0 -4
  70. data/spec/lib/browser_spec.rb +0 -140
  71. data/spec/lib/cache/file_store_spec.rb +0 -100
  72. data/spec/lib/cache/typhoeus_spec.rb +0 -28
  73. data/spec/lib/cms_scanner_spec.rb +0 -49
  74. data/spec/lib/controller_spec.rb +0 -30
  75. data/spec/lib/controllers_spec.rb +0 -48
  76. data/spec/lib/finders/confidence_spec.rb +0 -39
  77. data/spec/lib/finders/finder/enumerator_spec.rb +0 -89
  78. data/spec/lib/finders/finder/smart_url_checker/findings_spec.rb +0 -39
  79. data/spec/lib/finders/finder/smart_url_checker_spec.rb +0 -50
  80. data/spec/lib/finders/finder_spec.rb +0 -11
  81. data/spec/lib/finders/findings_spec.rb +0 -36
  82. data/spec/lib/finders/independent_finders_spec.rb +0 -134
  83. data/spec/lib/finders/same_type_finder_spec.rb +0 -24
  84. data/spec/lib/finders/same_type_finders_spec.rb +0 -126
  85. data/spec/lib/finders/unique_finder_spec.rb +0 -24
  86. data/spec/lib/finders/unique_finders_spec.rb +0 -222
  87. data/spec/lib/formatter_spec.rb +0 -145
  88. data/spec/lib/public_suffix/domain_spec.rb +0 -49
  89. data/spec/lib/sub_scanner_spec.rb +0 -45
  90. data/spec/lib/target/hashes_spec.rb +0 -90
  91. data/spec/lib/target/platforms_spec.rb +0 -13
  92. data/spec/lib/target/scope_spec.rb +0 -103
  93. data/spec/lib/target/servers_spec.rb +0 -13
  94. data/spec/lib/target_spec.rb +0 -69
  95. data/spec/lib/vulnerability/references_spec.rb +0 -75
  96. data/spec/lib/vulnerability_spec.rb +0 -27
  97. data/spec/lib/web_site_spec.rb +0 -121
  98. data/spec/output/core/finished.cli_no_colour +0 -3
  99. data/spec/output/core/finished.json +0 -5
  100. data/spec/output/core/started.cli_no_colour +0 -3
  101. data/spec/output/core/started.json +0 -5
  102. data/spec/output/interesting_files/empty.cli_no_colour +0 -2
  103. data/spec/output/interesting_files/empty.json +0 -5
  104. data/spec/output/interesting_files/findings.cli_no_colour +0 -30
  105. data/spec/output/interesting_files/findings.json +0 -75
  106. data/spec/shared_examples.rb +0 -11
  107. data/spec/shared_examples/browser_actions.rb +0 -30
  108. data/spec/shared_examples/finding.rb +0 -54
  109. data/spec/shared_examples/formatter_buffer.rb +0 -6
  110. data/spec/shared_examples/formatter_class_methods.rb +0 -26
  111. data/spec/shared_examples/independent_finder.rb +0 -31
  112. data/spec/shared_examples/target/platform/php.rb +0 -56
  113. data/spec/shared_examples/target/server/apache.rb +0 -32
  114. data/spec/shared_examples/target/server/generic.rb +0 -33
  115. data/spec/shared_examples/target/server/iis.rb +0 -37
  116. data/spec/shared_examples/views/core.rb +0 -26
  117. data/spec/shared_examples/views/interesting_files.rb +0 -36
  118. data/spec/spec_helper.rb +0 -43
data/.gitignore DELETED
@@ -1,7 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- coverage
6
- pkg
7
- Gemfile.lock
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --fail-fast
data/.rubocop.yml DELETED
@@ -1,10 +0,0 @@
1
- LineLength:
2
- Max: 100
3
- ClassVars:
4
- Enabled: false
5
- MethodLength:
6
- Max: 15
7
- Metrics/AbcSize:
8
- Max: 25
9
- Metrics/CyclomaticComplexity:
10
- Max: 10
data/.travis.yml DELETED
@@ -1,17 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.0.0
4
- - 2.1.0
5
- - 2.1.1
6
- - 2.1.2
7
- - 2.1.3
8
- - 2.1.4
9
- - 2.1.5
10
- - 2.2.0
11
- - ruby-head
12
- matrix:
13
- allow_failures:
14
- - rvm: ruby-head
15
- script:
16
- - bundle exec rspec
17
- - bundle exec rubocop
data/Gemfile DELETED
@@ -1,6 +0,0 @@
1
- source 'https://rubygems.org'
2
- gemspec
3
-
4
- group :test do
5
- gem 'coveralls', '~> 0.7', require: false
6
- end
data/Rakefile DELETED
@@ -1,9 +0,0 @@
1
- require 'bundler/gem_tasks'
2
- require 'rspec/core/rake_task'
3
- require 'rubocop/rake_task'
4
-
5
- RuboCop::RakeTask.new
6
- RSpec::Core::RakeTask.new(:spec)
7
-
8
- # Run rubocop & rspec before the build
9
- task build: [:rubocop, :spec]
@@ -1,167 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Controller::Core do
4
- subject(:core) { described_class.new }
5
- let(:target_url) { 'http://example.com/' }
6
- let(:parsed_options) { { url: target_url } }
7
-
8
- before do
9
- CMSScanner::Browser.reset
10
- described_class.parsed_options = parsed_options
11
- end
12
-
13
- its(:cli_options) { should_not be_empty }
14
- its(:cli_options) { should be_a Array }
15
-
16
- describe '#setup_cache' do
17
- context 'when no cache_dir supplied (or default)' do
18
- it 'returns nil' do
19
- expect(core.setup_cache).to eq nil
20
- end
21
- end
22
-
23
- context 'when cache_dir' do
24
- let(:parsed_options) { super().merge(cache_dir: CACHE) }
25
- let(:cache) { Typhoeus::Config.cache }
26
- let(:storage) { File.join(parsed_options[:cache_dir], Digest::MD5.hexdigest(target_url)) }
27
-
28
- before { core.setup_cache }
29
- after { Typhoeus::Config.cache = nil }
30
-
31
- it 'sets up the cache' do
32
- expect(cache).to be_a CMSScanner::Cache::Typhoeus
33
- expect(cache.storage_path).to eq storage
34
- end
35
- end
36
- end
37
-
38
- describe '#before_scan' do
39
- before { expect(core.formatter).to receive(:output) }
40
-
41
- it 'does not raise an error when everything is fine' do
42
- stub_request(:get, target_url).to_return(status: 200)
43
-
44
- expect { core.before_scan }.to_not raise_error
45
- end
46
-
47
- it 'raise an error when the site is down' do
48
- stub_request(:get, target_url).to_return(status: 0)
49
-
50
- expect { core.before_scan }
51
- .to raise_error("The url supplied '#{target_url}' seems to be down")
52
- end
53
-
54
- it 'raises an error when the site redirects' do
55
- redirection = 'http://somewhere.com'
56
-
57
- expect(core.target).to receive(:redirection).and_return(redirection)
58
-
59
- stub_request(:get, target_url).to_return(status: 301, headers: { location: redirection })
60
-
61
- expect { core.before_scan }
62
- .to raise_error("The url supplied redirects to #{redirection}")
63
- end
64
-
65
- context 'when access is forbidden' do
66
- before { stub_request(:get, target_url).to_return(status: 403) }
67
-
68
- it 'raises an error' do
69
- expect { core.before_scan }.to raise_error(CMSScanner::AccessForbiddenError)
70
- end
71
- end
72
-
73
- # This is quite a mess (as Webmock doesn't issue itself another 401
74
- # when credential are incorrect :/)
75
- context 'when http authentication' do
76
- context 'when no credentials' do
77
- before { stub_request(:get, target_url).to_return(status: 401) }
78
-
79
- it 'raises an error' do
80
- expect { core.before_scan }.to raise_error(CMSScanner::HTTPAuthRequiredError)
81
- end
82
- end
83
-
84
- context 'when credentials' do
85
- context 'when valid' do
86
- before { stub_request(:get, 'http://user:pass@example.com') }
87
-
88
- let(:parsed_options) { super().merge(http_auth: { username: 'user', password: 'pass' }) }
89
-
90
- it 'does not raise any error' do
91
- expect { core.before_scan }.to_not raise_error
92
- end
93
- end
94
-
95
- context 'when invalid' do
96
- before { stub_request(:get, 'http://user:p@ss@example.com').to_return(status: 401) }
97
-
98
- let(:parsed_options) { super().merge(http_auth: { username: 'user', password: 'p@ss' }) }
99
-
100
- it 'raises an error' do
101
- expect { core.before_scan }.to raise_error(CMSScanner::HTTPAuthRequiredError)
102
- end
103
- end
104
- end
105
- end
106
-
107
- context 'when proxy authentication' do
108
- before { stub_request(:get, target_url).to_return(status: 407) }
109
-
110
- context 'when no credentials' do
111
- it 'raises an error' do
112
- expect { core.before_scan }.to raise_error(CMSScanner::ProxyAuthRequiredError)
113
- end
114
- end
115
-
116
- context 'when invalid credentials' do
117
- let(:parsed_options) { super().merge(proxy_auth: { username: 'user', password: 'p@ss' }) }
118
-
119
- it 'raises an error' do
120
- expect(CMSScanner::Browser.instance.proxy_auth).to eq(parsed_options[:proxy_auth])
121
-
122
- expect { core.before_scan }.to raise_error(CMSScanner::ProxyAuthRequiredError)
123
- end
124
- end
125
-
126
- context 'when valid credentials' do
127
- before { stub_request(:get, target_url) }
128
-
129
- let(:parsed_options) { super().merge(proxy_auth: { username: 'user', password: 'pass' }) }
130
-
131
- it 'raises an error' do
132
- expect(CMSScanner::Browser.instance.proxy_auth).to eq(parsed_options[:proxy_auth])
133
-
134
- expect { core.before_scan }.to_not raise_error
135
- end
136
- end
137
- end
138
- end
139
-
140
- describe '#run' do
141
- it 'calls the formatter with the correct parameters' do
142
- expect(core.formatter).to receive(:output)
143
- .with('started',
144
- hash_including(:start_memory, :start_time, :verbose, url: target_url),
145
- 'core')
146
-
147
- core.run
148
- end
149
- end
150
-
151
- describe '#after_scan' do
152
- let(:keys) { [:verbose, :start_time, :stop_time, :start_memory, :elapsed, :used_memory] }
153
-
154
- it 'calls the formatter with the correct parameters' do
155
- # Call the #run once to ensure that @start_time & @start_memory are set
156
- expect(core).to receive(:output).with('started', url: target_url)
157
- core.run
158
-
159
- RSpec::Mocks.space.proxy_for(core).reset # Must reset due to the above statements
160
-
161
- expect(core.formatter).to receive(:output)
162
- .with('finished', hash_including(*keys), 'core')
163
-
164
- core.after_scan
165
- end
166
- end
167
- end
@@ -1,70 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Controller::InterestingFiles do
4
- subject(:controller) { described_class.new }
5
- let(:target_url) { 'http://example.com/' }
6
- let(:parsed_options) { { url: target_url } }
7
-
8
- before do
9
- CMSScanner::Browser.reset
10
- described_class.parsed_options = parsed_options
11
- end
12
-
13
- its(:before_scan) { should be_nil }
14
- its(:after_scan) { should be_nil }
15
-
16
- describe '#cli_options' do
17
- its(:cli_options) { should_not be_empty }
18
- its(:cli_options) { should be_a Array }
19
-
20
- it 'contains to correct options' do
21
- expect(controller.cli_options.map(&:to_sym)).to eq [:interesting_files_detection]
22
- end
23
- end
24
-
25
- describe '#run' do
26
- before do
27
- expect(controller.target).to receive(:interesting_files)
28
- .with(
29
- mode: parsed_options[:interesting_files_detection] || parsed_options[:detection_mode]
30
- ).and_return(stubbed)
31
- end
32
-
33
- after { controller.run }
34
-
35
- [:mixed, :passive, :aggressive].each do |mode|
36
- context "when --detection-mode #{mode}" do
37
- let(:parsed_options) { super().merge(detection_mode: mode) }
38
-
39
- context 'when no findings' do
40
- let(:stubbed) { [] }
41
-
42
- before { expect(controller.formatter).to_not receive(:output) }
43
-
44
- it 'does not call the formatter' do
45
- # Handled by the before statements above
46
- end
47
-
48
- context 'when --interesting-files-detection mode supplied' do
49
- let(:parsed_options) do
50
- super().merge(interesting_files_detection: :passive)
51
- end
52
-
53
- it 'gives the correct detection paramter' do
54
- # Handled by before/after statements
55
- end
56
- end
57
- end
58
-
59
- context 'when findings' do
60
- let(:stubbed) { ['yolo'] }
61
-
62
- it 'calls the formatter with the correct parameter' do
63
- expect(controller.formatter).to receive(:output)
64
- .with('findings', hash_including(findings: stubbed), 'interesting_files')
65
- end
66
- end
67
- end
68
- end
69
- end
70
- end
@@ -1,66 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Finders::InterestingFiles::FantasticoFileslist do
4
- subject(:finder) { described_class.new(target) }
5
- let(:target) { CMSScanner::Target.new(url) }
6
- let(:url) { 'http://example.com/' }
7
- let(:file) { url + 'fantastico_fileslist.txt' }
8
- let(:fixtures) { File.join(FIXTURES_FINDERS, 'interesting_files', 'fantastico_fileslist') }
9
-
10
- describe '#url' do
11
- its(:url) { should eq file }
12
- end
13
-
14
- describe '#aggressive' do
15
- after do
16
- stub_request(:get, file).to_return(status: status, body: body, headers: headers)
17
-
18
- result = finder.aggressive
19
-
20
- expect(result).to be_a CMSScanner::FantasticoFileslist if @expected
21
- expect(result).to eql @expected
22
- end
23
-
24
- let(:body) { '' }
25
- let(:headers) { { 'Content-Type' => 'text/html ' } }
26
-
27
- context 'when 404' do
28
- let(:status) { 404 }
29
-
30
- it 'returns nil' do
31
- @expected = nil
32
- end
33
- end
34
-
35
- context 'when 200' do
36
- let(:status) { 200 }
37
-
38
- context 'when the body is empty' do
39
- it 'returns nil' do
40
- @expected = nil
41
- end
42
- end
43
-
44
- context 'when not a text/plain Content-Type' do
45
- let(:body) { 'not an empty body' }
46
-
47
- it 'returns nil' do
48
- @expected = nil
49
- end
50
- end
51
-
52
- context 'when the body matches and Content-Type = text/plain' do
53
- let(:body) { File.new(File.join(fixtures, 'fantastico_fileslist.txt')).read }
54
- let(:headers) { { 'Content-Type' => 'text/plain' } }
55
-
56
- it 'returns the InterestingFile result' do
57
- @expected = CMSScanner::FantasticoFileslist.new(
58
- file,
59
- confidence: 100,
60
- found_by: 'Fantastico Fileslist (Aggressive Detection)'
61
- )
62
- end
63
- end
64
- end
65
- end
66
- end
@@ -1,36 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Finders::InterestingFiles::Headers do
4
- subject(:finder) { described_class.new(target) }
5
- let(:target) { CMSScanner::Target.new(url) }
6
- let(:url) { 'http://example.com/' }
7
- let(:fixtures) { File.join(FIXTURES_FINDERS, 'interesting_files', 'headers') }
8
- let(:fixture) { File.join(fixtures, 'interesting.txt') }
9
- let(:headers) { parse_headers_file(fixture) }
10
-
11
- describe '#passive' do
12
- before { stub_request(:get, url).to_return(headers: headers) }
13
-
14
- after do
15
- if @expected
16
- result = finder.passive
17
-
18
- expect(result).to be_a CMSScanner::Headers
19
- expect(result).to eql @expected
20
- end
21
- end
22
-
23
- context 'when no headers' do
24
- let(:headers) { {} }
25
-
26
- its(:passive) { should be nil }
27
- end
28
-
29
- context 'when headers' do
30
- it 'returns the result' do
31
- opts = { confidence: 100, found_by: 'Headers (Passive Detection)' }
32
- @expected = CMSScanner::Headers.new(url, opts)
33
- end
34
- end
35
- end
36
- end
@@ -1,54 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Finders::InterestingFiles::RobotsTxt do
4
- subject(:finder) { described_class.new(target) }
5
- let(:target) { CMSScanner::Target.new(url) }
6
- let(:url) { 'http://example.com/' }
7
- let(:robots_txt) { url + 'robots.txt' }
8
- let(:fixtures) { File.join(FIXTURES_FINDERS, 'interesting_files', 'robots_txt') }
9
-
10
- describe '#url' do
11
- its(:url) { should eq robots_txt }
12
- end
13
-
14
- describe '#aggressive' do
15
- after do
16
- stub_request(:get, robots_txt).to_return(status: status, body: body)
17
-
18
- result = finder.aggressive
19
-
20
- expect(result).to be_a CMSScanner::RobotsTxt if @expected
21
- expect(finder.aggressive).to eql @expected
22
- end
23
-
24
- let(:body) { '' }
25
-
26
- context 'when 404' do
27
- let(:status) { 404 }
28
-
29
- it 'returns nil' do
30
- @expected = nil
31
- end
32
- end
33
-
34
- context 'when 200' do
35
- let(:status) { 200 }
36
-
37
- context 'when the body is empty' do
38
- it 'returns nil' do
39
- @expected = nil
40
- end
41
- end
42
-
43
- context 'when the body matches a robots.txt' do
44
- let(:body) { File.new(File.join(fixtures, 'robots.txt')).read }
45
-
46
- it 'returns the InterestingFile result' do
47
- @expected = CMSScanner::RobotsTxt.new(robots_txt,
48
- confidence: 100,
49
- found_by: 'Robots Txt (Aggressive Detection)')
50
- end
51
- end
52
- end
53
- end
54
- end