cms_scanner 0.0.18 → 0.0.19

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