cms_scanner 0.0.6 → 0.0.7
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 +4 -4
- data/app/finders/interesting_files/xml_rpc.rb +1 -3
- data/app/models.rb +1 -0
- data/app/models/interesting_file.rb +0 -4
- data/app/models/version.rb +17 -0
- data/app/views/cli/core/finished.erb +0 -1
- data/app/views/cli/interesting_files/findings.erb +1 -1
- data/cms_scanner.gemspec +2 -2
- data/lib/cms_scanner.rb +1 -0
- data/lib/cms_scanner/finders.rb +2 -0
- data/lib/cms_scanner/finders/finding.rb +4 -0
- data/lib/cms_scanner/finders/independent_finders.rb +1 -1
- data/lib/cms_scanner/finders/unique_finder.rb +17 -0
- data/lib/cms_scanner/finders/unique_finders.rb +39 -0
- data/lib/cms_scanner/target.rb +1 -0
- data/lib/cms_scanner/target/platform/wordpress.rb +2 -4
- data/lib/cms_scanner/target/platform/wordpress/custom_directories.rb +1 -2
- data/lib/cms_scanner/target/server/apache.rb +3 -2
- data/lib/cms_scanner/target/server/iis.rb +1 -2
- data/lib/cms_scanner/typhoeus/response.rb +9 -0
- data/lib/cms_scanner/version.rb +1 -1
- data/spec/app/controllers/core_spec.rb +0 -2
- data/spec/app/controllers/interesting_files_spec.rb +0 -2
- data/spec/app/finders/interesting_files/fantastico_fileslist_spec.rb +0 -2
- data/spec/app/finders/interesting_files/headers_spec.rb +0 -2
- data/spec/app/finders/interesting_files/robots_txt_spec.rb +0 -2
- data/spec/app/finders/interesting_files/search_replace_db_2_spec.rb +0 -2
- data/spec/app/finders/interesting_files/xml_rpc_spec.rb +0 -2
- data/spec/app/finders/interesting_files_spec.rb +1 -2
- data/spec/app/formatters/cli_no_colour_spec.rb +0 -2
- data/spec/app/formatters/cli_spec.rb +0 -2
- data/spec/app/formatters/json_spec.rb +0 -2
- data/spec/app/models/fantastico_fileslist_spec.rb +0 -1
- data/spec/app/models/headers_spec.rb +0 -1
- data/spec/app/models/interesting_file_spec.rb +0 -2
- data/spec/app/models/robots_txt_spec.rb +0 -1
- data/spec/app/models/version_spec.rb +23 -0
- data/spec/app/models/xml_rpc_spec.rb +0 -1
- data/spec/app/views_spec.rb +0 -2
- data/spec/dummy_finding.rb +21 -0
- data/spec/dummy_independent_finders.rb +25 -0
- data/spec/dummy_unique_finders.rb +32 -0
- data/spec/lib/browser_spec.rb +0 -1
- data/spec/lib/cache/file_store_spec.rb +0 -1
- data/spec/lib/cache/typhoeus_spec.rb +0 -2
- data/spec/lib/cms_scanner_spec.rb +0 -1
- data/spec/lib/controller_spec.rb +0 -2
- data/spec/lib/controllers_spec.rb +0 -2
- data/spec/lib/finders/findings_spec.rb +1 -3
- data/spec/lib/finders/independent_finders_spec.rb +4 -6
- data/spec/lib/finders/unique_finder_spec.rb +24 -0
- data/spec/lib/finders/unique_finders_spec.rb +133 -0
- data/spec/lib/formatter_spec.rb +0 -3
- data/spec/lib/target_spec.rb +0 -2
- data/spec/lib/web_site_spec.rb +0 -3
- data/spec/output/core/finished.cli_no_colour +0 -1
- data/spec/output/interesting_files/empty.cli_no_colour +1 -0
- data/spec/output/interesting_files/findings.cli_no_colour +1 -0
- data/spec/shared_examples/browser_actions.rb +0 -2
- data/spec/shared_examples/finding.rb +21 -1
- data/spec/shared_examples/formatter_buffer.rb +0 -2
- data/spec/shared_examples/independent_finder.rb +1 -3
- data/spec/shared_examples/target/platform/php.rb +0 -1
- data/spec/shared_examples/target/platform/wordpress.rb +0 -2
- data/spec/shared_examples/target/server/apache.rb +0 -1
- data/spec/shared_examples/target/server/generic.rb +0 -1
- data/spec/shared_examples/target/server/iis.rb +0 -1
- data/spec/shared_examples/views/core.rb +0 -1
- data/spec/shared_examples/views/interesting_files.rb +0 -1
- metadata +21 -7
- data/spec/dummy_finders.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0866fc4bfc65ce2c0b92ac2b4d8b0e6d412f0f4e
|
4
|
+
data.tar.gz: d1a849df9cfb4d7e2efb41bf836b62df007e02b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6351f6c0f03e6c4a7983933c723a9f479cc1b9a39d5ff4683930f9bb91b1c6f9b4f087b0ffaa5e193c7fcbfb00bb41317884cd9da25d062d0df4604e416c8e15
|
7
|
+
data.tar.gz: 40fa45e9e46359b1f9b5c818ed470213fe7434c73fdbf93eeed173ea27c5c0f8a3ef589f7c61c510cb6c90ae7da19568947a2d571a5723695dadb32a3a5ed00d
|
@@ -25,9 +25,7 @@ module CMSScanner
|
|
25
25
|
|
26
26
|
# @return [ XMLRPC ]
|
27
27
|
def passive_body(_opts = {})
|
28
|
-
|
29
|
-
|
30
|
-
page.css('link[rel="pingback"]').each do |tag|
|
28
|
+
NS::Browser.get(target.url).html.css('link[rel="pingback"]').each do |tag|
|
31
29
|
url = tag.attribute('href').to_s
|
32
30
|
|
33
31
|
next unless target.in_scope?(url)
|
data/app/models.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
# Version
|
3
|
+
class Version
|
4
|
+
include NS::Finders::Finding
|
5
|
+
|
6
|
+
attr_reader :number
|
7
|
+
|
8
|
+
def initialize(number, opts = {})
|
9
|
+
@number = number
|
10
|
+
parse_finding_options(opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
def ==(other)
|
14
|
+
number == other.number
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -18,4 +18,4 @@ Interesting Findings: <%= @findings.size %>
|
|
18
18
|
<% end -%>
|
19
19
|
<%= render('_array', a: finding.references, s: 'Reference', p: 'References') -%>
|
20
20
|
<%= render('_array', a: finding.interesting_entries, s: 'Interesting Entry', p: 'Interesting Entries') -%>
|
21
|
-
<% end
|
21
|
+
<% end %>
|
data/cms_scanner.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.version = CMSScanner::VERSION
|
10
10
|
s.platform = Gem::Platform::RUBY
|
11
11
|
s.required_ruby_version = '>= 2.0.0'
|
12
|
-
s.authors = ['WPScanTeam - Erwan
|
12
|
+
s.authors = ['WPScanTeam - Erwan Le Rousseau']
|
13
13
|
s.email = ['erwan.lr@gmail.com']
|
14
14
|
s.summary = 'Experimental CMSScanner'
|
15
15
|
s.description = 'Experimental CMSScanner'
|
@@ -31,7 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
s.add_development_dependency 'rspec', '~> 3.1'
|
32
32
|
s.add_development_dependency 'rspec-its'
|
33
33
|
s.add_development_dependency 'bundler', '~> 1.6'
|
34
|
-
s.add_development_dependency 'rubocop', '~> 0.
|
34
|
+
s.add_development_dependency 'rubocop', '~> 0.28'
|
35
35
|
s.add_development_dependency 'webmock', '>= 1.18'
|
36
36
|
s.add_development_dependency 'simplecov', '~> 0.9'
|
37
37
|
end
|
data/lib/cms_scanner.rb
CHANGED
data/lib/cms_scanner/finders.rb
CHANGED
@@ -3,3 +3,5 @@ require 'cms_scanner/finders/finding'
|
|
3
3
|
require 'cms_scanner/finders/findings'
|
4
4
|
require 'cms_scanner/finders/independent_finders'
|
5
5
|
require 'cms_scanner/finders/independent_finder'
|
6
|
+
require 'cms_scanner/finders/unique_finders'
|
7
|
+
require 'cms_scanner/finders/unique_finder'
|
@@ -32,6 +32,10 @@ module CMSScanner
|
|
32
32
|
def parse_finding_options(opts = {})
|
33
33
|
FINDING_OPTS.each { |opt| send("#{opt}=", opts[opt]) if opts.key?(opt) }
|
34
34
|
end
|
35
|
+
|
36
|
+
def eql?(other)
|
37
|
+
self == other && confidence == other.confidence && found_by == other.found_by
|
38
|
+
end
|
35
39
|
end
|
36
40
|
end
|
37
41
|
end
|
@@ -2,7 +2,7 @@ module CMSScanner
|
|
2
2
|
module Finders
|
3
3
|
# Independent Finders container
|
4
4
|
# This class is designed to handle independent results
|
5
|
-
# which are not related with others
|
5
|
+
# which are not related with each others
|
6
6
|
# e.g: interesting files
|
7
7
|
class IndependentFinders < Array
|
8
8
|
# @return [ Findings ]
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
module Finders
|
3
|
+
# Unique Finder
|
4
|
+
module UniqueFinder
|
5
|
+
def self.included(klass)
|
6
|
+
klass.class_eval do
|
7
|
+
include IndependentFinder
|
8
|
+
|
9
|
+
# @return [ Array ]
|
10
|
+
def finders
|
11
|
+
@finders ||= NS::Finders::UniqueFinders.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
module Finders
|
3
|
+
# Unique Finders container
|
4
|
+
#
|
5
|
+
# This class is designed to return a unique result such as a version
|
6
|
+
# Note: Finders contained can return multiple results but the #run will only
|
7
|
+
# returned the best finding
|
8
|
+
class UniqueFinders < IndependentFinders
|
9
|
+
# @param [ Hash ] opts
|
10
|
+
# @option opts [ Symbol ] mode :mixed, :passive or :aggressive
|
11
|
+
# @option opts [ Int ] :confidence_threshold If a finding's confidence reaches this value,
|
12
|
+
# it will be returned as the best finding.
|
13
|
+
# Default is 100.
|
14
|
+
# If <= 0, all finders will be ran.
|
15
|
+
#
|
16
|
+
# @return [ Object ]
|
17
|
+
def run(opts = {})
|
18
|
+
opts[:confidence_threshold] ||= 100
|
19
|
+
|
20
|
+
symbols_from_mode(opts[:mode]).each do |symbol|
|
21
|
+
each do |finder|
|
22
|
+
[*finder.send(symbol, opts)].each do |found|
|
23
|
+
findings << found
|
24
|
+
end
|
25
|
+
|
26
|
+
next if opts[:confidence_threshold] <= 0
|
27
|
+
|
28
|
+
findings.each do |f|
|
29
|
+
return f if f.confidence >= opts[:confidence_threshold]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# results are sorted by confidence ASC
|
35
|
+
findings.sort_by(&:confidence).last
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/cms_scanner/target.rb
CHANGED
@@ -6,6 +6,7 @@ module CMSScanner
|
|
6
6
|
# Target to Scan
|
7
7
|
class Target < WebSite
|
8
8
|
include Server::Generic
|
9
|
+
|
9
10
|
# @note Subdomains are considered out of scope (maybe consider them in ?)
|
10
11
|
# Also, // are handled by Addressable::URI, but worngly :/
|
11
12
|
# e.g: Addressable::URI.parse('//file').host => file
|
@@ -9,12 +9,10 @@ module CMSScanner
|
|
9
9
|
module WordPress
|
10
10
|
include PHP
|
11
11
|
|
12
|
-
WORDPRESS_PATTERN = %r{/(?:(?:wp-content/(?:themes|plugins|
|
12
|
+
WORDPRESS_PATTERN = %r{/(?:(?:wp-content/(?:themes|plugins|uploads))|wp-includes)/}i
|
13
13
|
|
14
14
|
def wordpress?
|
15
|
-
|
16
|
-
|
17
|
-
page.css('script, link').each do |tag|
|
15
|
+
NS::Browser.get(url).html.css('script, link').each do |tag|
|
18
16
|
tag_url = tag.attribute('href').to_s
|
19
17
|
|
20
18
|
next unless in_scope?(tag_url)
|
@@ -14,11 +14,10 @@ module CMSScanner
|
|
14
14
|
# @return [ String ] The wp-content directory
|
15
15
|
def content_dir
|
16
16
|
unless @content_dir
|
17
|
-
page = Nokogiri::HTML(Browser.get(url).body)
|
18
17
|
escaped_url = Regexp.escape(url).gsub(/https?/i, 'https?')
|
19
18
|
pattern = %r{#{escaped_url}(.+?)\/(?:themes|plugins|uploads)\/}i
|
20
19
|
|
21
|
-
|
20
|
+
NS::Browser.get(url).html.css('link,script,style,img').each do |tag|
|
22
21
|
%w(href src).each do |attribute|
|
23
22
|
attr_value = tag.attribute(attribute).to_s
|
24
23
|
|
@@ -30,10 +30,11 @@ module CMSScanner
|
|
30
30
|
def directory_listing_entries(path = nil, params = {})
|
31
31
|
return [] unless directory_listing?(path, params)
|
32
32
|
|
33
|
-
doc = Nokogiri::HTML(NS::Browser.get(url(path), params).body)
|
34
33
|
found = []
|
35
34
|
|
36
|
-
|
35
|
+
NS::Browser.get(url(path), params).html.css('td a').each do |node|
|
36
|
+
found << node.text.to_s
|
37
|
+
end
|
37
38
|
|
38
39
|
found[1..-1] # returns the array w/o the first element 'Parent Directory'
|
39
40
|
end
|
@@ -30,10 +30,9 @@ module CMSScanner
|
|
30
30
|
def directory_listing_entries(path = nil, params = {})
|
31
31
|
return [] unless directory_listing?(path, params)
|
32
32
|
|
33
|
-
doc = Nokogiri::HTML(NS::Browser.get(url(path), params).body)
|
34
33
|
found = []
|
35
34
|
|
36
|
-
|
35
|
+
NS::Browser.get(url(path), params).html.css('pre a').each do |node|
|
37
36
|
entry = node.text.to_s
|
38
37
|
|
39
38
|
next if entry == '[To Parent Directory]'
|
data/lib/cms_scanner/version.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CMSScanner::Controller::Core do
|
4
|
-
|
5
4
|
subject(:core) { described_class.new }
|
6
5
|
let(:target_url) { 'http://example.com/' }
|
7
6
|
let(:parsed_options) { { url: target_url } }
|
@@ -148,5 +147,4 @@ describe CMSScanner::Controller::Core do
|
|
148
147
|
core.after_scan
|
149
148
|
end
|
150
149
|
end
|
151
|
-
|
152
150
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CMSScanner::Controller::InterestingFiles do
|
4
|
-
|
5
4
|
subject(:controller) { described_class.new }
|
6
5
|
let(:target_url) { 'http://example.com/' }
|
7
6
|
let(:parsed_options) { { url: target_url } }
|
@@ -46,5 +45,4 @@ describe CMSScanner::Controller::InterestingFiles do
|
|
46
45
|
end
|
47
46
|
end
|
48
47
|
end
|
49
|
-
|
50
48
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CMSScanner::Finders::InterestingFile::FantasticoFileslist do
|
4
|
-
|
5
4
|
subject(:finder) { described_class.new(target) }
|
6
5
|
let(:target) { CMSScanner::Target.new(url) }
|
7
6
|
let(:url) { 'http://example.com/' }
|
@@ -64,5 +63,4 @@ describe CMSScanner::Finders::InterestingFile::FantasticoFileslist do
|
|
64
63
|
end
|
65
64
|
end
|
66
65
|
end
|
67
|
-
|
68
66
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CMSScanner::Finders::InterestingFile::Headers do
|
4
|
-
|
5
4
|
subject(:finder) { described_class.new(target) }
|
6
5
|
let(:target) { CMSScanner::Target.new(url) }
|
7
6
|
let(:url) { 'http://example.com/' }
|
@@ -34,5 +33,4 @@ describe CMSScanner::Finders::InterestingFile::Headers do
|
|
34
33
|
end
|
35
34
|
end
|
36
35
|
end
|
37
|
-
|
38
36
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CMSScanner::Finders::InterestingFile::RobotsTxt do
|
4
|
-
|
5
4
|
subject(:finder) { described_class.new(target) }
|
6
5
|
let(:target) { CMSScanner::Target.new(url) }
|
7
6
|
let(:url) { 'http://example.com/' }
|
@@ -52,5 +51,4 @@ describe CMSScanner::Finders::InterestingFile::RobotsTxt do
|
|
52
51
|
end
|
53
52
|
end
|
54
53
|
end
|
55
|
-
|
56
54
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CMSScanner::Finders::InterestingFile::SearchReplaceDB2 do
|
4
|
-
|
5
4
|
subject(:finder) { described_class.new(target) }
|
6
5
|
let(:target) { CMSScanner::Target.new(url) }
|
7
6
|
let(:url) { 'http://example.com/' }
|
@@ -51,5 +50,4 @@ describe CMSScanner::Finders::InterestingFile::SearchReplaceDB2 do
|
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
54
|
-
|
55
53
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CMSScanner::Finders::InterestingFile::XMLRPC do
|
4
|
-
|
5
4
|
subject(:finder) { described_class.new(target) }
|
6
5
|
let(:target) { CMSScanner::Target.new(url) }
|
7
6
|
let(:url) { 'http://ex.lo/' }
|
@@ -134,5 +133,4 @@ describe CMSScanner::Finders::InterestingFile::XMLRPC do
|
|
134
133
|
end
|
135
134
|
end
|
136
135
|
end
|
137
|
-
|
138
136
|
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CMSScanner::Finders::InterestingFiles do
|
4
|
-
|
5
4
|
it_behaves_like CMSScanner::Finders::IndependentFinder do
|
6
5
|
let(:expected_finders) { %w(Headers RobotsTxt FantasticoFileslist SearchReplaceDB2 XMLRPC) }
|
6
|
+
let(:expected_finders_class) { CMSScanner::Finders::IndependentFinders }
|
7
7
|
end
|
8
8
|
|
9
9
|
subject(:files) { described_class.new(target) }
|
10
10
|
let(:target) { CMSScanner::Target.new(url) }
|
11
11
|
let(:url) { 'http://example.com/' }
|
12
|
-
|
13
12
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CMSScanner::Formatter::CliNoColour do
|
4
|
-
|
5
4
|
subject(:formatter) { described_class.new }
|
6
5
|
|
7
6
|
describe '#format' do
|
@@ -13,5 +12,4 @@ describe CMSScanner::Formatter::CliNoColour do
|
|
13
12
|
expect(formatter.red('Text')).to eq 'Text'
|
14
13
|
end
|
15
14
|
end
|
16
|
-
|
17
15
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CMSScanner::Formatter::Cli do
|
4
|
-
|
5
4
|
subject(:formatter) { described_class.new }
|
6
5
|
|
7
6
|
describe '#format' do
|
@@ -17,5 +16,4 @@ describe CMSScanner::Formatter::Cli do
|
|
17
16
|
expect(formatter.green('Another Text')).to eq "\e[32mAnother Text\e[0m"
|
18
17
|
end
|
19
18
|
end
|
20
|
-
|
21
19
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CMSScanner::Formatter::Json do
|
4
|
-
|
5
4
|
it_behaves_like CMSScanner::Formatter::Buffer
|
6
5
|
|
7
6
|
subject(:formatter) { described_class.new }
|
@@ -29,5 +28,4 @@ describe CMSScanner::Formatter::Json do
|
|
29
28
|
formatter.beautify
|
30
29
|
end
|
31
30
|
end
|
32
|
-
|
33
31
|
end
|