cms_scanner 0.0.2
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 +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
data/app/models.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module CMSScanner
|
|
2
|
+
# FantasticoFileslist
|
|
3
|
+
class FantasticoFileslist < InterestingFile
|
|
4
|
+
# @return [ Array<String> ] The interesting files/dirs detected
|
|
5
|
+
def interesting_entries
|
|
6
|
+
results = []
|
|
7
|
+
|
|
8
|
+
entries.each do |entry|
|
|
9
|
+
next unless entry =~ /(?:admin|\.log|\.sql|\.db)/i
|
|
10
|
+
|
|
11
|
+
results << entry
|
|
12
|
+
end
|
|
13
|
+
results
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def references
|
|
17
|
+
%w(http://www.acunetix.com/vulnerabilities/fantastico-fileslist/)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module CMSScanner
|
|
2
|
+
# Not really an interesting file, but will use this class for convenience
|
|
3
|
+
class Headers < InterestingFile
|
|
4
|
+
# @return [ Hash ] The headers
|
|
5
|
+
def entries
|
|
6
|
+
res = NS::Browser.get(url)
|
|
7
|
+
return [] unless res && res.headers
|
|
8
|
+
res.headers
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @return [ Array<String> ] The interesting headers detected
|
|
12
|
+
def interesting_entries
|
|
13
|
+
results = []
|
|
14
|
+
|
|
15
|
+
entries.each do |header, value|
|
|
16
|
+
next if known_headers.include?(header.downcase)
|
|
17
|
+
|
|
18
|
+
results << "#{header}: #{value}"
|
|
19
|
+
end
|
|
20
|
+
results
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @return [ Array<String> ] Downcased known headers
|
|
24
|
+
def known_headers
|
|
25
|
+
%w(
|
|
26
|
+
age accept-ranges cache-control content-type content-length connection date etag expires
|
|
27
|
+
location last-modified link pragma set-cookie strict-transport-security transfer-encoding
|
|
28
|
+
vary x-cache x-content-security-policy x-content-type-options x-frame-options x-language
|
|
29
|
+
x-permitted-cross-domain-policies x-pingback x-varnish x-webkit-csp x-xss-protection
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def eql?(other)
|
|
34
|
+
super(other) && interesting_entries == other.interesting_entries
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module CMSScanner
|
|
2
|
+
# Interesting File
|
|
3
|
+
class InterestingFile
|
|
4
|
+
include NS::Finders::Finding
|
|
5
|
+
|
|
6
|
+
attr_reader :url
|
|
7
|
+
|
|
8
|
+
def initialize(url, opts = {})
|
|
9
|
+
@url = url
|
|
10
|
+
parse_finding_options(opts)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @return [ Array<String> ]
|
|
14
|
+
def entries
|
|
15
|
+
res = NS::Browser.get(url)
|
|
16
|
+
|
|
17
|
+
return [] unless res && res.headers['Content-Type'] =~ /\Atext\/plain;/i
|
|
18
|
+
|
|
19
|
+
res.body.split("\n").reject { |s| s.strip.empty? }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def ==(other)
|
|
23
|
+
url == other.url
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def eql?(other)
|
|
27
|
+
url == other.url && confidence == other.confidence && found_by == other.found_by
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module CMSScanner
|
|
2
|
+
# Robots.txt
|
|
3
|
+
class RobotsTxt < InterestingFile
|
|
4
|
+
# @todo Better detection, currently everythinh not empty or / is returned
|
|
5
|
+
#
|
|
6
|
+
# @return [ Array<String> ] The interesting Allow/Disallow rules detected
|
|
7
|
+
def interesting_entries
|
|
8
|
+
results = []
|
|
9
|
+
|
|
10
|
+
entries.each do |entry|
|
|
11
|
+
next unless entry =~ /\A(?:dis)?allow:\s*(.+)\z/i
|
|
12
|
+
match = Regexp.last_match(1)
|
|
13
|
+
next if match == '/'
|
|
14
|
+
|
|
15
|
+
results << match
|
|
16
|
+
end
|
|
17
|
+
results
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module CMSScanner
|
|
2
|
+
# XML RPC
|
|
3
|
+
class XMLRPC < InterestingFile
|
|
4
|
+
# @param [ String ] method
|
|
5
|
+
# @param [ Array ] params
|
|
6
|
+
# @param [ Hash ] request_params
|
|
7
|
+
#
|
|
8
|
+
# @return [ Typhoeus::Response ]
|
|
9
|
+
def call(method, params = [], request_params = {})
|
|
10
|
+
NS::Browser.post(url, request_params.merge(body: request_body(method, params)))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Might be better to use Nokogiri to create the XML body ?
|
|
14
|
+
#
|
|
15
|
+
# @param [ String ] method
|
|
16
|
+
# @param [ Array ] params
|
|
17
|
+
#
|
|
18
|
+
# @return [ String ] The body of the XML RPC request
|
|
19
|
+
def request_body(method, params = [])
|
|
20
|
+
p_body = ''
|
|
21
|
+
|
|
22
|
+
params.each { |p| p_body << "<param><value><string>#{p}</string></value></param>" }
|
|
23
|
+
|
|
24
|
+
body = '<?xml version="1.0"?><methodCall>'
|
|
25
|
+
body << "<methodName>#{method}</methodName>"
|
|
26
|
+
body << "<params>#{p_body}</params>" unless p_body.length == 0
|
|
27
|
+
body << '</methodCall>'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Use the system.listMethods to get the list of available methods ?
|
|
31
|
+
# def entries
|
|
32
|
+
#
|
|
33
|
+
# end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Interesting Findings: <%= @findings.size %>
|
|
2
|
+
|
|
3
|
+
<% @findings.each do |finding| -%>
|
|
4
|
+
[+] <%= finding.url %>
|
|
5
|
+
| Confidence: <%= finding.confidence %>%
|
|
6
|
+
| Found By: <%= finding.found_by %>
|
|
7
|
+
<% unless (confirmed = finding.confirmed_by).empty? -%>
|
|
8
|
+
| Confirmed By:
|
|
9
|
+
<% confirmed.each do |c| -%>
|
|
10
|
+
| - <%= c.found_by %>, <%= c.confidence %>% confidence
|
|
11
|
+
<% end -%>
|
|
12
|
+
<% end -%>
|
|
13
|
+
<% unless (entries = finding.interesting_entries).empty? -%>
|
|
14
|
+
| Interesting Entries:
|
|
15
|
+
<% entries.each do |entry| -%>
|
|
16
|
+
| - <%= entry %>
|
|
17
|
+
<% end -%>
|
|
18
|
+
<% end %>
|
|
19
|
+
<% end %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"todo": "Not yet done",
|
data/cms_scanner.gemspec
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
|
|
5
|
+
require 'cms_scanner/version'
|
|
6
|
+
|
|
7
|
+
Gem::Specification.new do |s|
|
|
8
|
+
s.name = 'cms_scanner'
|
|
9
|
+
s.version = CMSScanner::VERSION
|
|
10
|
+
s.platform = Gem::Platform::RUBY
|
|
11
|
+
s.required_ruby_version = '>= 2.0.0'
|
|
12
|
+
s.authors = ['WPScanTeam - Erwan le Rousseau']
|
|
13
|
+
s.email = ['erwan.lr@gmail.com']
|
|
14
|
+
s.summary = 'Experimental CMSScanner'
|
|
15
|
+
s.description = 'Experimental CMSScanner'
|
|
16
|
+
s.homepage = 'https://github.com/wpscanteam/CMSScanner'
|
|
17
|
+
s.license = 'MIT'
|
|
18
|
+
|
|
19
|
+
s.files = `git ls-files -z`.split("\x0")
|
|
20
|
+
s.executables = s.files.grep(/^bin\//) { |f| File.basename(f) }
|
|
21
|
+
s.test_files = s.files.grep(/^(test|spec|features)\//)
|
|
22
|
+
s.require_path = 'lib'
|
|
23
|
+
|
|
24
|
+
s.add_dependency 'opt_parse_validator', '~> 0.0.2'
|
|
25
|
+
s.add_dependency 'typhoeus'
|
|
26
|
+
s.add_dependency 'nokogiri'
|
|
27
|
+
s.add_dependency 'addressable'
|
|
28
|
+
s.add_dependency 'activesupport'
|
|
29
|
+
|
|
30
|
+
s.add_development_dependency 'rake'
|
|
31
|
+
s.add_development_dependency 'rspec', '~> 3.1'
|
|
32
|
+
s.add_development_dependency 'rspec-its'
|
|
33
|
+
s.add_development_dependency 'bundler', '~> 1.6'
|
|
34
|
+
s.add_development_dependency 'rubocop', '~> 0.26'
|
|
35
|
+
s.add_development_dependency 'webmock', '>= 1.18'
|
|
36
|
+
s.add_development_dependency 'simplecov', '~> 0.9'
|
|
37
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Testing! --wpscan-option = <%= @option %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"--wpscan-option": <%= @option.to_json %>,
|
data/examples/wpscan.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'cms_scanner'
|
|
4
|
+
|
|
5
|
+
# Custom WPScan Scanner
|
|
6
|
+
module WPScan
|
|
7
|
+
include CMSScanner
|
|
8
|
+
|
|
9
|
+
module Controller
|
|
10
|
+
# Custom WPScan Controller
|
|
11
|
+
class WpCustom < CMSScanner::Controller::Base
|
|
12
|
+
def cli_options
|
|
13
|
+
[
|
|
14
|
+
OptString.new(['--wpscan-option VALUE'])
|
|
15
|
+
]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def run
|
|
19
|
+
output('test', option: parsed_options[:wpscan_option])
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
WPScan::Scan.new do |s|
|
|
26
|
+
s.controllers << WPScan::Controller::WpCustom.new
|
|
27
|
+
s.views_directories << Pathname.new(__FILE__).dirname.join('views').to_s
|
|
28
|
+
s.run
|
|
29
|
+
end
|
data/lib/cms_scanner.rb
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Gems
|
|
2
|
+
require 'opt_parse_validator'
|
|
3
|
+
require 'typhoeus'
|
|
4
|
+
require 'nokogiri'
|
|
5
|
+
require 'active_support/inflector'
|
|
6
|
+
require 'addressable/uri'
|
|
7
|
+
# Standard Libs
|
|
8
|
+
require 'erb'
|
|
9
|
+
require 'fileutils'
|
|
10
|
+
require 'pathname'
|
|
11
|
+
# Custom Libs
|
|
12
|
+
require 'helper'
|
|
13
|
+
require 'cms_scanner/errors/auth_errors'
|
|
14
|
+
require 'cms_scanner/cache/typhoeus'
|
|
15
|
+
require 'cms_scanner/target'
|
|
16
|
+
require 'cms_scanner/browser'
|
|
17
|
+
require 'cms_scanner/version'
|
|
18
|
+
require 'cms_scanner/controller'
|
|
19
|
+
require 'cms_scanner/controllers'
|
|
20
|
+
require 'cms_scanner/formatter'
|
|
21
|
+
require 'cms_scanner/finders'
|
|
22
|
+
|
|
23
|
+
# Module
|
|
24
|
+
module CMSScanner
|
|
25
|
+
APP_DIR = Pathname.new(__FILE__).dirname.join('..', 'app').expand_path
|
|
26
|
+
NS = self
|
|
27
|
+
|
|
28
|
+
def self.included(base)
|
|
29
|
+
remove_const(:NS)
|
|
30
|
+
const_set(:NS, base)
|
|
31
|
+
super(base)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Scan
|
|
35
|
+
class Scan
|
|
36
|
+
def initialize
|
|
37
|
+
controllers << NS::Controller::Core.new
|
|
38
|
+
|
|
39
|
+
yield self if block_given?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @return [ Controllers ]
|
|
43
|
+
def controllers
|
|
44
|
+
@controllers ||= NS::Controllers.new
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def run
|
|
48
|
+
controllers.run
|
|
49
|
+
rescue => e
|
|
50
|
+
formatter.output('@scan_aborted',
|
|
51
|
+
reason: e.message,
|
|
52
|
+
trace: e.backtrace,
|
|
53
|
+
verbose: controllers.first.parsed_options[:verbose])
|
|
54
|
+
ensure
|
|
55
|
+
formatter.beautify
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Used for convenience
|
|
59
|
+
# @See Formatter
|
|
60
|
+
def formatter
|
|
61
|
+
controllers.first.formatter
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [ Hash ]
|
|
65
|
+
def datastore
|
|
66
|
+
controllers.first.datastore
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
require "#{CMSScanner::APP_DIR}/app"
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require 'cms_scanner/browser/actions'
|
|
2
|
+
require 'cms_scanner/browser/options'
|
|
3
|
+
|
|
4
|
+
module CMSScanner
|
|
5
|
+
# Singleton used to perform HTTP/HTTPS request to the target
|
|
6
|
+
class Browser
|
|
7
|
+
extend Actions
|
|
8
|
+
|
|
9
|
+
# @param [ Hash ] parsed_options
|
|
10
|
+
#
|
|
11
|
+
# @return [ Void ]
|
|
12
|
+
def initialize(parsed_options = {})
|
|
13
|
+
load_options(parsed_options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private_class_method :new
|
|
17
|
+
|
|
18
|
+
# @param [ Hash ] parsed_options
|
|
19
|
+
#
|
|
20
|
+
# @return [ Browser ] The instance
|
|
21
|
+
def self.instance(parsed_options = {})
|
|
22
|
+
@@instance ||= new(parsed_options)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.reset
|
|
26
|
+
@@instance = nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @param [ String ] url
|
|
30
|
+
# @param [ Hash ] params
|
|
31
|
+
#
|
|
32
|
+
# @return [ Typhoeus::Request ]
|
|
33
|
+
def forge_request(url, params = {})
|
|
34
|
+
Typhoeus::Request.new(url, request_params(params))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @return [ Hash ]
|
|
38
|
+
def default_request_params
|
|
39
|
+
params = {
|
|
40
|
+
ssl_verifypeer: false, # Disable SSL-Certificate checks
|
|
41
|
+
ssl_verifyhost: 2, # Disable SSL-Certificate checks
|
|
42
|
+
headers: { 'User-Agent' => user_agent }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
{ connecttimeout: :connect_timeout, cache_ttl: :cache_ttl,
|
|
46
|
+
proxy: :proxy, timeout: :request_timeout, cookiejar: :cookie_jar,
|
|
47
|
+
cookiefile: :cookie_jar, cookie: :cookie_string
|
|
48
|
+
}.each do |typhoeus_opt, browser_opt|
|
|
49
|
+
attr_value = public_send(browser_opt)
|
|
50
|
+
params[typhoeus_opt] = attr_value unless attr_value.nil?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
params[:proxyauth] = "#{proxy_auth[:username]}:#{proxy_auth[:password]}" if proxy_auth
|
|
54
|
+
params[:userpwd] = "#{http_auth[:username]}:#{http_auth[:password]}" if http_auth
|
|
55
|
+
|
|
56
|
+
params
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @param [ Hash ] params
|
|
60
|
+
#
|
|
61
|
+
# @return [ Hash ]
|
|
62
|
+
def request_params(params = {})
|
|
63
|
+
default_request_params.merge(params) do |key, oldval, newval|
|
|
64
|
+
key == :headers ? oldval.merge(newval) : newval
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|