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
@@ -1,53 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Finders::InterestingFiles::SearchReplaceDB2 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 + 'searchreplacedb2.php' }
8
- let(:fixtures) { File.join(FIXTURES_FINDERS, 'interesting_files', 'search_replace_db_2') }
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)
17
-
18
- expect(finder.aggressive).to eql @expected
19
- end
20
-
21
- let(:body) { '' }
22
-
23
- context 'when 404' do
24
- let(:status) { 404 }
25
-
26
- it 'returns nil' do
27
- @expected = nil
28
- end
29
- end
30
-
31
- context 'when 200' do
32
- let(:status) { 200 }
33
-
34
- context 'when the body is empty' do
35
- it 'returns nil' do
36
- @expected = nil
37
- end
38
- end
39
-
40
- context 'when the body matches' do
41
- let(:body) { File.new(File.join(fixtures, 'searchreplacedb2.php')).read }
42
-
43
- it 'returns the InterestingFile result' do
44
- @expected = CMSScanner::InterestingFile.new(
45
- file,
46
- confidence: 100,
47
- found_by: 'Search Replace Db2 (Aggressive Detection)'
48
- )
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,136 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Finders::InterestingFiles::XMLRPC do
4
- subject(:finder) { described_class.new(target) }
5
- let(:target) { CMSScanner::Target.new(url) }
6
- let(:url) { 'http://e.org/' }
7
- let(:xml_rpc_url) { url + 'xmlrpc.php' }
8
- let(:fixtures) { File.join(FIXTURES_FINDERS, 'interesting_files', 'xml_rpc') }
9
-
10
- describe '#potential_urls' do
11
- its(:potential_urls) { should be_empty }
12
- end
13
-
14
- describe '#passive' do
15
- before do
16
- expect(finder).to receive(:passive_headers).and_return(headers_stub)
17
- expect(finder).to receive(:passive_body).and_return(body_stub)
18
- end
19
-
20
- context 'when both passives return nil' do
21
- let(:headers_stub) { nil }
22
- let(:body_stub) { nil }
23
-
24
- its(:passive) { should be_empty }
25
- end
26
-
27
- context 'when one passive is not nil' do
28
- let(:headers_stub) { nil }
29
- let(:body_stub) { 'test' }
30
-
31
- its(:passive) { should eq %w(test) }
32
- end
33
- end
34
-
35
- describe '#passive_headers' do
36
- before { stub_request(:get, url).to_return(headers: headers) }
37
-
38
- let(:headers) { {} }
39
-
40
- context 'when no headers' do
41
- its(:passive_headers) { should be_nil }
42
- end
43
-
44
- context 'when headers' do
45
- context 'when URL is out of scope' do
46
- let(:headers) { { 'X-Pingback' => 'http://ex.org/yolo' } }
47
-
48
- its(:passive_headers) { should be_nil }
49
- end
50
-
51
- context 'when URL is in scope' do
52
- let(:headers) { { 'X-Pingback' => xml_rpc_url } }
53
-
54
- it 'adds the url to #potential_urls and returns the XMLRPC' do
55
- result = finder.passive_headers
56
-
57
- expect(finder.potential_urls).to eq [xml_rpc_url]
58
-
59
- expect(result).to be_a CMSScanner::XMLRPC
60
- expect(result).to eql CMSScanner::XMLRPC.new(
61
- xml_rpc_url,
62
- confidence: 30,
63
- found_by: 'Headers (passive detection)'
64
- )
65
- end
66
- end
67
- end
68
- end
69
-
70
- describe '#passive_body' do
71
- before { stub_request(:get, url).to_return(body: body) }
72
-
73
- context 'when no link rel="pingback" tag' do
74
- let(:body) { '' }
75
-
76
- its(:passive_body) { should be_nil }
77
- end
78
-
79
- context 'when the tag is present' do
80
- context 'when the URL is out of scope' do
81
- let(:body) { File.new(File.join(fixtures, 'homepage_out_of_scope_pingback.html')).read }
82
-
83
- its(:passive_body) { should be_nil }
84
- end
85
-
86
- context 'when URL is in scope' do
87
- let(:body) { File.new(File.join(fixtures, 'homepage_in_scope_pingback.html')).read }
88
- let(:expected_url) { 'http://e.org/wp/xmlrpc.php' }
89
-
90
- it 'adds the URL to the #potential_urls and returns the XMLRPC' do
91
- result = finder.passive_body
92
-
93
- expect(finder.potential_urls).to eq [expected_url]
94
-
95
- expect(result).to be_a CMSScanner::XMLRPC
96
- expect(result).to eql CMSScanner::XMLRPC.new(
97
- expected_url,
98
- confidence: 30,
99
- found_by: 'Link Tag (passive detection)'
100
- )
101
- end
102
- end
103
- end
104
- end
105
-
106
- describe '#aggressive' do
107
- # Adds an out of scope URL which should be ignored
108
- before { finder.potential_urls << 'htpp://ex.org' }
109
-
110
- after do
111
- stub_request(:get, xml_rpc_url).to_return(body: body)
112
-
113
- expect(finder.aggressive).to eql @expected
114
- end
115
-
116
- context 'when the body does not match' do
117
- let(:body) { '' }
118
-
119
- it 'returns nil' do
120
- @expected = nil
121
- end
122
- end
123
-
124
- context 'when the body matches' do
125
- let(:body) { File.new(File.join(fixtures, 'xmlrpc.php')).read }
126
-
127
- it 'returns the InterestingFile result' do
128
- @expected = CMSScanner::XMLRPC.new(
129
- xml_rpc_url,
130
- confidence: 100,
131
- found_by: described_class::DIRECT_ACCESS
132
- )
133
- end
134
- end
135
- end
136
- end
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Finders::InterestingFiles::Base do
4
- it_behaves_like CMSScanner::Finders::IndependentFinder do
5
- let(:expected_finders) { %w(Headers RobotsTxt FantasticoFileslist SearchReplaceDB2 XMLRPC) }
6
- let(:expected_finders_class) { CMSScanner::Finders::IndependentFinders }
7
- end
8
-
9
- subject(:files) { described_class.new(target) }
10
- let(:target) { CMSScanner::Target.new(url) }
11
- let(:url) { 'http://example.com/' }
12
- end
@@ -1,14 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Formatter::CliNoColour do
4
- subject(:formatter) { described_class.new }
5
-
6
- its(:format) { should eq 'cli' }
7
- its(:user_interaction?) { should be true }
8
-
9
- describe '#colorize' do
10
- it 'returns the text w/o any colour' do
11
- expect(formatter.red('Text')).to eq 'Text'
12
- end
13
- end
14
- end
@@ -1,30 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Formatter::Cli do
4
- subject(:formatter) { described_class.new }
5
-
6
- its(:format) { should eq 'cli' }
7
- its(:user_interaction?) { should be true }
8
-
9
- describe '#bold, #red, #green, #amber, #blue, #colorize' do
10
- it 'returns the correct bold string' do
11
- expect(formatter.bold('Text')).to eq "\e[1mText\e[0m"
12
- end
13
-
14
- it 'returns the correct red string' do
15
- expect(formatter.red('Text')).to eq "\e[31mText\e[0m"
16
- end
17
-
18
- it 'returns the correct green string' do
19
- expect(formatter.green('Another Text')).to eq "\e[32mAnother Text\e[0m"
20
- end
21
-
22
- it 'returns the correct amber string' do
23
- expect(formatter.amber('Text')).to eq "\e[33mText\e[0m"
24
- end
25
-
26
- it 'returns the correct blue string' do
27
- expect(formatter.blue('Text')).to eq "\e[34mText\e[0m"
28
- end
29
- end
30
- end
@@ -1,30 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Formatter::Json do
4
- it_behaves_like CMSScanner::Formatter::Buffer
5
-
6
- subject(:formatter) { described_class.new }
7
- let(:output_file) { File.join(FIXTURES, 'output.txt') }
8
-
9
- before { formatter.views_directories << FIXTURES_VIEWS }
10
-
11
- its(:format) { should eq 'json' }
12
- its(:user_interaction?) { should be false }
13
-
14
- describe '#output' do
15
- it 'puts the rendered text in the buffer' do
16
- 2.times { formatter.output('@render_me', test: 'Working') }
17
-
18
- expect(formatter.buffer).to eq "\"test\": \"Working\",\n" * 2
19
- end
20
- end
21
-
22
- describe '#beautify' do
23
- it 'writes the buffer in the file' do
24
- 2.times { formatter.output('@render_me', test: 'yolo') }
25
-
26
- expect($stdout).to receive(:puts).with(JSON.pretty_generate(JSON.parse('{"test": "yolo"}')))
27
- formatter.beautify
28
- end
29
- end
30
- end
@@ -1,31 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::FantasticoFileslist do
4
- subject(:file) { described_class.new(url) }
5
- let(:url) { 'http://example.com/robots.txt' }
6
- let(:fixtures) { File.join(FIXTURES_FINDERS, 'interesting_files', 'fantastico_fileslist') }
7
-
8
- describe '#interesting_entries' do
9
- let(:headers) { { 'Content-Type' => 'text/plain; charset=utf-8' } }
10
-
11
- after do
12
- body = File.new(File.join(fixtures, fixture)).read
13
-
14
- stub_request(:get, file.url).to_return(headers: headers, body: body)
15
-
16
- expect(file.interesting_entries).to eq @expected
17
- end
18
-
19
- context 'when empty or / entries' do
20
- let(:fixture) { 'fantastico_fileslist.txt' }
21
-
22
- it 'ignores them and only returns the others' do
23
- @expected = %w(data.sql admin.txt)
24
- end
25
- end
26
- end
27
-
28
- describe '#references' do
29
- its(:references) { should_not be_nil }
30
- end
31
- end
@@ -1,51 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::Headers do
4
- subject(:file) { described_class.new(url) }
5
- let(:url) { 'http://example.com/' }
6
- let(:fixtures) { File.join(FIXTURES_FINDERS, 'interesting_files', 'headers') }
7
- let(:fixture) { File.join(fixtures, 'interesting.txt') }
8
- let(:headers) { {} }
9
-
10
- before { stub_request(:get, file.url).to_return(headers: headers) }
11
-
12
- describe '#known_headers' do
13
- it 'does not contains dupliactes' do
14
- expect(file.known_headers).to eql file.known_headers.uniq
15
- end
16
- end
17
-
18
- describe '#entries' do
19
- after { expect(file.entries).to eq @expected if @expected }
20
-
21
- context 'when no headers' do
22
- its(:entries) { should eq({}) }
23
- end
24
-
25
- context 'when headers' do
26
- let(:headers) { parse_headers_file(fixture) }
27
-
28
- it 'returns the headers' do
29
- @expected = headers
30
- end
31
- end
32
- end
33
-
34
- describe '#interesting_entries' do
35
- after { expect(file.interesting_entries).to eq @expected if @expected }
36
-
37
- context 'when interesting headers' do
38
- let(:headers) { parse_headers_file(fixture) }
39
-
40
- it 'returns an array with the headers' do
41
- @expected = ['Server: nginx/1.1.19', 'X-Powered-By: ASP.NET, PHP', 'X-Article-Id: 12']
42
- end
43
- end
44
-
45
- context 'when no interesting headers' do
46
- let(:headers) { parse_headers_file(File.join(fixtures, 'no_interesting.txt')) }
47
-
48
- its(:interesting_entries) { should eq [] }
49
- end
50
- end
51
- end
@@ -1,69 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::InterestingFile do
4
- it_behaves_like CMSScanner::Finders::Finding
5
-
6
- subject(:file) { described_class.new(url, opts) }
7
- let(:opts) { {} }
8
- let(:url) { 'http://example.com/' }
9
- let(:fixtures) { File.join(FIXTURES_FINDERS, 'interesting_files') }
10
-
11
- describe '#entries' do
12
- after do
13
- stub_request(:get, file.url).to_return(headers: headers, body: @body)
14
-
15
- expect(file.entries).to eq @expected
16
- end
17
-
18
- context 'when content-type matches text/plain' do
19
- let(:headers) { { 'Content-Type' => 'text/plain; charset=utf-8' } }
20
-
21
- it 'returns the file content as an array w/o empty strings' do
22
- @body = File.new(File.join(fixtures, 'file.txt')).read
23
- @expected = ['This is', 'a test file', 'with some content']
24
- end
25
- end
26
-
27
- context 'when other content-type' do
28
- let(:headers) { { 'Content-Type' => 'text.html; charset=utf-8' } }
29
-
30
- it 'returns an empty array' do
31
- @expected = []
32
- end
33
- end
34
- end
35
-
36
- describe '#==' do
37
- context 'when same URL' do
38
- it 'returns true' do
39
- expect(file == described_class.new(url)).to be true
40
- end
41
- end
42
-
43
- context 'when not the same URL' do
44
- it 'returns false' do
45
- expect(file == described_class.new('http://e.org')).to be false
46
- end
47
- end
48
- end
49
-
50
- describe '#<=>' do
51
- context 'when same URL' do
52
- it 'returns 0' do
53
- expect(file <=> described_class.new(url)).to eql 0
54
- end
55
- end
56
-
57
- context 'when the other URL <= current one' do
58
- it 'returns 1' do
59
- expect(file <=> described_class.new('http://e.org')).to eql 1
60
- end
61
- end
62
-
63
- context 'when the other URL >= current one' do
64
- it 'returns -1' do
65
- expect(file <=> described_class.new('http://exi.org/')).to eql(-1)
66
- end
67
- end
68
- end
69
- end
@@ -1,27 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CMSScanner::RobotsTxt do
4
- subject(:file) { described_class.new(url) }
5
- let(:url) { 'http://example.com/robots.txt' }
6
- let(:fixtures) { File.join(FIXTURES_FINDERS, 'interesting_files', 'robots_txt') }
7
-
8
- describe '#interesting_entries' do
9
- let(:headers) { { 'Content-Type' => 'text/plain; charset=utf-8' } }
10
-
11
- after do
12
- body = File.new(File.join(fixtures, fixture)).read
13
-
14
- stub_request(:get, file.url).to_return(headers: headers, body: body)
15
-
16
- expect(file.interesting_entries).to eq @expected
17
- end
18
-
19
- context 'when empty or / entries' do
20
- let(:fixture) { 'robots.txt' }
21
-
22
- it 'ignores them and only returns the others' do
23
- @expected = %w(/admin /public/home)
24
- end
25
- end
26
- end
27
- end