cms_scanner 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f568051a37f6bcd75abe28d026dea5e2ff8a1372
|
4
|
+
data.tar.gz: d9399f063d4bc5b3929f566e2a018788dc708615
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 60523f8ef6495c41045f34e16bf18287f677b0c8749678d8cc9e4bfd4620b21ec357e06a9e230b6b83f3604d0cdfb24f159796a902939d1b9c239c7a5051fe7a
|
7
|
+
data.tar.gz: 38d4c48bf4e4b682732ce4f37b7eba45cca00c19b5edffbf89abd3a362bc8e782c10d842948a3fd657fa16737c09ceb7eb3461ed1551ebc795e2be5d0d3e8861
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# CMSScanner
|
2
|
+
|
3
|
+
[![Build Status](https://img.shields.io/travis/wpscanteam/CMSScanner.svg)](https://travis-ci.org/wpscanteam/CMSScanner)
|
4
|
+
[![Coverage Status](https://img.shields.io/coveralls/wpscanteam/CMSScanner.svg)](https://coveralls.io/r/wpscanteam/CMSScanner)
|
5
|
+
[![Code Climate](https://img.shields.io/codeclimate/github/wpscanteam/CMSScanner.svg)](https://codeclimate.com/github/wpscanteam/CMSScanner)
|
6
|
+
[![Dependency Status](https://img.shields.io/gemnasium/wpscanteam/CMSScanner.svg)](https://gemnasium.com/wpscanteam/CMSScanner)
|
7
|
+
|
8
|
+
The goal of this gem is to provide a quick and easy way to create a CMS/WebSite Scanner by acting like a Framework and providing classes, formatters etc.
|
9
|
+
|
10
|
+
## /!\ This gem is currently Experimental /!\
|
11
|
+
|
12
|
+
Install Dependencies: ```bundle install```
|
13
|
+
|
14
|
+
## Contributing
|
15
|
+
|
16
|
+
1. Fork it ( https://github.com/wpscanteam/CMSScanner/fork )
|
17
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
18
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
19
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
20
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/app/app.rb
ADDED
data/app/controllers.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'core/cli_options'
|
2
|
+
|
3
|
+
module CMSScanner
|
4
|
+
module Controller
|
5
|
+
# Core Controller
|
6
|
+
class Core < Base
|
7
|
+
def setup_cache
|
8
|
+
return unless parsed_options[:cache_dir]
|
9
|
+
|
10
|
+
storage_path = File.join(parsed_options[:cache_dir], Digest::MD5.hexdigest(target.url))
|
11
|
+
|
12
|
+
Typhoeus::Config.cache = Cache::Typhoeus.new(storage_path)
|
13
|
+
Typhoeus::Config.cache.clean if parsed_options[:clear_cache]
|
14
|
+
end
|
15
|
+
|
16
|
+
def before_scan
|
17
|
+
setup_cache
|
18
|
+
|
19
|
+
fail "The url supplied '#{target.url}' seems to be down" unless target.online?
|
20
|
+
|
21
|
+
fail HTTPAuthRequiredError if target.http_auth?
|
22
|
+
fail ProxyAuthRequiredError if target.proxy_auth?
|
23
|
+
|
24
|
+
# TODO: ask if the redirection should be followed
|
25
|
+
# if user_interaction? is allowed (if followed, the Cache#storage_path should be updated)
|
26
|
+
redirection = target.redirection
|
27
|
+
fail "The url supplied redirects to #{redirection}" if redirection
|
28
|
+
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
@start_time = Time.now
|
32
|
+
@start_memory = memory_usage
|
33
|
+
|
34
|
+
output('started', url: target.url)
|
35
|
+
end
|
36
|
+
|
37
|
+
def after_scan
|
38
|
+
@stop_time = Time.now
|
39
|
+
@elapsed = @stop_time - @start_time
|
40
|
+
@used_memory = memory_usage - @start_memory
|
41
|
+
|
42
|
+
output('finished')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
module Controller
|
3
|
+
# CLI Options for the Core Controller
|
4
|
+
class Core < Base
|
5
|
+
def cli_options
|
6
|
+
formats = NS::Formatter.availables
|
7
|
+
|
8
|
+
[
|
9
|
+
OptURL.new(['-u', '--url URL'], required: true),
|
10
|
+
OptBoolean.new(%w(-v --verbose)),
|
11
|
+
OptFilePath.new(['-o', '--output FILE', 'Output to FILE'], writable: true, exists: false),
|
12
|
+
OptChoice.new(['-f', '--format FORMAT',
|
13
|
+
"Available formats: #{formats.join(', ')}"], choices: formats),
|
14
|
+
OptChoice.new(['--detection-mode MODE', 'Modes: mixed (default), passive, aggressive'],
|
15
|
+
choices: %w(mixed passive aggressive),
|
16
|
+
normalize: :to_sym,
|
17
|
+
default: :mixed)
|
18
|
+
] + cli_browser_options
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [ Array<OptParseValidator::OptBase> ]
|
22
|
+
def cli_browser_options
|
23
|
+
[
|
24
|
+
OptString.new(['--user-agent VALUE', '--ua']),
|
25
|
+
OptCredentials.new(['--http-auth login:password']),
|
26
|
+
OptPositiveInteger.new(['--max-threads VALUE', '-t', 'The max threads to use']),
|
27
|
+
OptPositiveInteger.new(['--request-timeout SECONDS', 'The request timeout in seconds']),
|
28
|
+
OptPositiveInteger.new(['--connect-timeout SECONDS',
|
29
|
+
'The connection timeout in seconds'])
|
30
|
+
] + cli_browser_proxy_options + cli_browser_cookies_options + cli_browser_cache_options
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [ Array<OptParseValidator::OptBase> ]
|
34
|
+
def cli_browser_proxy_options
|
35
|
+
[
|
36
|
+
OptProxy.new(['--proxy protocol://IP:port',
|
37
|
+
'Supported protocols depend on the cURL installed']),
|
38
|
+
OptCredentials.new(['--proxy-auth login:password'])
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [ Array<OptParseValidator::OptBase> ]
|
43
|
+
def cli_browser_cookies_options
|
44
|
+
[
|
45
|
+
OptString.new(['--cookie-string COOKIE',
|
46
|
+
'Cookie string to use in requests, ' \
|
47
|
+
'format: cookie1=value1[; cookie2=value2]']),
|
48
|
+
OptFilePath.new(['--cookie-jar FILE-PATH', 'File to read and write cookies'],
|
49
|
+
writable: true,
|
50
|
+
exists: false,
|
51
|
+
default: '/tmp/cms_scanner/cookie_jar.txt')
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [ Array<OptParseValidator::OptBase> ]
|
56
|
+
def cli_browser_cache_options
|
57
|
+
[
|
58
|
+
OptInteger.new(['--cache-ttl TIME_TO_LIVE'], default: 600),
|
59
|
+
OptBoolean.new(['--clear-cache', 'Clear the cache before the scan']),
|
60
|
+
OptDirectoryPath.new(['--cache-dir PATH'],
|
61
|
+
readable: true,
|
62
|
+
writable: true,
|
63
|
+
default: '/tmp/cms_scanner/cache/')
|
64
|
+
]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
module Controller
|
3
|
+
# InterestingFiles Controller
|
4
|
+
class InterestingFiles < Base
|
5
|
+
def run
|
6
|
+
findings = target.interesting_files(mode: parsed_options[:detection_mode])
|
7
|
+
|
8
|
+
output('findings', findings: findings) unless findings.empty?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/app/finders.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'finders/interesting_files'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'interesting_files/headers'
|
2
|
+
require_relative 'interesting_files/robots_txt'
|
3
|
+
require_relative 'interesting_files/fantastico_fileslist'
|
4
|
+
require_relative 'interesting_files/search_replace_db_2'
|
5
|
+
require_relative 'interesting_files/xml_rpc'
|
6
|
+
|
7
|
+
module CMSScanner
|
8
|
+
module Finders
|
9
|
+
# Interesting Files Finder
|
10
|
+
class InterestingFiles
|
11
|
+
include IndependentFinder
|
12
|
+
|
13
|
+
# @param [ CMSScanner::Target ] target
|
14
|
+
def initialize(target)
|
15
|
+
%w(Headers RobotsTxt FantasticoFileslist SearchReplaceDB2 XMLRPC).each do |f|
|
16
|
+
finders << NS.const_get("Finders::InterestingFile::#{f}").new(target)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
module Finders
|
3
|
+
module InterestingFile
|
4
|
+
# FantasticoFileslist finder
|
5
|
+
class FantasticoFileslist < Finder
|
6
|
+
# @return [ String ] The url of the fantastico_fileslist.txt file
|
7
|
+
def url
|
8
|
+
target.url('fantastico_fileslist.txt')
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [ InterestingFile ]
|
12
|
+
def aggressive(_opts = {})
|
13
|
+
res = NS::Browser.get(url)
|
14
|
+
|
15
|
+
return unless res && res.code == 200 && res.body.length > 0
|
16
|
+
return unless res.headers && res.headers['Content-Type'] =~ /\Atext\/plain/
|
17
|
+
|
18
|
+
NS::FantasticoFileslist.new(url, confidence: 100, found_by: found_by)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
module Finders
|
3
|
+
module InterestingFile
|
4
|
+
# Interesting Headers finder
|
5
|
+
class Headers < Finder
|
6
|
+
# @return [ InterestingFile ]
|
7
|
+
def passive(_opts = {})
|
8
|
+
r = NS::Headers.new(target.url, confidence: 100, found_by: found_by)
|
9
|
+
|
10
|
+
r.interesting_entries.empty? ? nil : r
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
module Finders
|
3
|
+
module InterestingFile
|
4
|
+
# Robots.txt finder
|
5
|
+
class RobotsTxt < Finder
|
6
|
+
# @return [ String ] The url of the robots.txt file
|
7
|
+
def url
|
8
|
+
target.url('robots.txt')
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [ InterestingFile ]
|
12
|
+
def aggressive(_opts = {})
|
13
|
+
res = NS::Browser.get(url)
|
14
|
+
|
15
|
+
return unless res && res.code == 200 && res.body =~ /(?:user-agent|(?:dis)?allow):/i
|
16
|
+
|
17
|
+
NS::RobotsTxt.new(url, confidence: 100, found_by: found_by)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
module Finders
|
3
|
+
module InterestingFile
|
4
|
+
# SearchReplaceDB2 finder
|
5
|
+
class SearchReplaceDB2 < Finder
|
6
|
+
# @return [ String ] The url to the searchreplacedb2 PHP file
|
7
|
+
def url
|
8
|
+
target.url('searchreplacedb2.php')
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [ InterestingFile ]
|
12
|
+
def aggressive(_opts = {})
|
13
|
+
res = NS::Browser.get(url)
|
14
|
+
|
15
|
+
return unless res && res.code == 200 && res.body =~ /by interconnect/i
|
16
|
+
|
17
|
+
NS::InterestingFile.new(url, confidence: 100,
|
18
|
+
found_by: found_by,
|
19
|
+
references: references)
|
20
|
+
end
|
21
|
+
|
22
|
+
def references
|
23
|
+
%w(https://interconnectit.com/products/search-and-replace-for-wordpress-databases/)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
module Finders
|
3
|
+
module InterestingFile
|
4
|
+
# XML RPC finder
|
5
|
+
class XMLRPC < Finder
|
6
|
+
# @return [ Array<String> ] The potential urls to the XMl RPC file
|
7
|
+
def potential_urls
|
8
|
+
@potential_urls ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [ Array<XMLRPC> ]
|
12
|
+
def passive(opts = {})
|
13
|
+
[passive_headers(opts), passive_body(opts)].compact
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [ XMLRPC ]
|
17
|
+
def passive_headers(_opts = {})
|
18
|
+
url = NS::Browser.get(target.url).headers['X-Pingback']
|
19
|
+
|
20
|
+
return unless target.in_scope?(url)
|
21
|
+
potential_urls << url
|
22
|
+
|
23
|
+
NS::XMLRPC.new(url, confidence: 30, found_by: 'Headers (passive detection)')
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [ XMLRPC ]
|
27
|
+
def passive_body(_opts = {})
|
28
|
+
page = Nokogiri::HTML(NS::Browser.get(target.url).body)
|
29
|
+
|
30
|
+
page.css('link[rel="pingback"]').each do |tag|
|
31
|
+
url = tag.attribute('href').to_s
|
32
|
+
|
33
|
+
next unless target.in_scope?(url)
|
34
|
+
potential_urls << url
|
35
|
+
|
36
|
+
return NS::XMLRPC.new(url, confidence: 30,
|
37
|
+
found_by: 'Link Tag (passive detection)')
|
38
|
+
end
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [ XMLRPC ]
|
43
|
+
def aggressive(_opts = {})
|
44
|
+
potential_urls << target.url('xmlrpc.php')
|
45
|
+
|
46
|
+
potential_urls.uniq.each do |potential_url|
|
47
|
+
next unless target.in_scope?(potential_url)
|
48
|
+
|
49
|
+
res = NS::Browser.get(potential_url)
|
50
|
+
|
51
|
+
next unless res && res.body =~ /XML-RPC server accepts POST requests only/i
|
52
|
+
|
53
|
+
return NS::XMLRPC.new(potential_url,
|
54
|
+
confidence: 100,
|
55
|
+
found_by: DIRECT_FILE_ACCESS)
|
56
|
+
end
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/app/formatters.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module CMSScanner
|
2
|
+
module Formatter
|
3
|
+
# CLI Formatter
|
4
|
+
class Cli < Base
|
5
|
+
def red(text)
|
6
|
+
colorize(text, 31)
|
7
|
+
end
|
8
|
+
|
9
|
+
def green(text)
|
10
|
+
colorize(text, 32)
|
11
|
+
end
|
12
|
+
|
13
|
+
def colorize(text, color_code)
|
14
|
+
"\e[#{color_code}m#{text}\e[0m"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|