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,120 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
$Id$
|
|
3
|
+
|
|
4
|
+
Arachni
|
|
5
|
+
Copyright (c) 2010-2011 Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
|
|
6
|
+
|
|
7
|
+
This is free software; you can copy and distribute and modify
|
|
8
|
+
this program under the term of the GPL v2.0 License
|
|
9
|
+
(See LICENSE file for details)
|
|
10
|
+
|
|
11
|
+
=end
|
|
12
|
+
|
|
13
|
+
module Arachni
|
|
14
|
+
|
|
15
|
+
module Modules
|
|
16
|
+
|
|
17
|
+
#
|
|
18
|
+
# SQL Injection audit module.<br/>
|
|
19
|
+
# It audits links, forms and cookies.
|
|
20
|
+
#
|
|
21
|
+
#
|
|
22
|
+
# @author: Tasos "Zapotek" Laskos
|
|
23
|
+
# <tasos.laskos@gmail.com>
|
|
24
|
+
# <zapotek@segfault.gr>
|
|
25
|
+
# @version: 0.1.4
|
|
26
|
+
#
|
|
27
|
+
# @see http://cwe.mitre.org/data/definitions/89.html
|
|
28
|
+
# @see http://unixwiz.net/techtips/sql-injection.html
|
|
29
|
+
# @see http://en.wikipedia.org/wiki/SQL_injection
|
|
30
|
+
# @see http://www.securiteam.com/securityreviews/5DP0N1P76E.html
|
|
31
|
+
# @see http://www.owasp.org/index.php/SQL_Injection
|
|
32
|
+
#
|
|
33
|
+
class SQLInjection < Arachni::Module::Base
|
|
34
|
+
|
|
35
|
+
include Arachni::Module::Utilities
|
|
36
|
+
|
|
37
|
+
def initialize( page )
|
|
38
|
+
super( page )
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def prepare( )
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# it's better to save big arrays to a file
|
|
45
|
+
# a big array is ugly, messy and can't be updated as easily
|
|
46
|
+
#
|
|
47
|
+
# but don't open the file yourself, use get_data_file( filename )
|
|
48
|
+
# with a block and read each line
|
|
49
|
+
#
|
|
50
|
+
# keep your files under modules/<modtype>/<modname>/
|
|
51
|
+
#
|
|
52
|
+
|
|
53
|
+
#
|
|
54
|
+
# we make this a class variable and populate it only once
|
|
55
|
+
# to reduce file IO
|
|
56
|
+
#
|
|
57
|
+
@@__regexps ||= []
|
|
58
|
+
|
|
59
|
+
if @@__regexps.empty?
|
|
60
|
+
read_file( 'regexp_ids.txt' ) { |regexp| @@__regexps << regexp }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# prepare the string that will hopefully cause the webapp
|
|
64
|
+
# to output SQL error messages
|
|
65
|
+
@__injection_str = [
|
|
66
|
+
'\'`--',
|
|
67
|
+
')'
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
@__opts = {
|
|
71
|
+
:format => [ Format::APPEND ],
|
|
72
|
+
:regexp => @@__regexps,
|
|
73
|
+
:param_flip => true
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def run( )
|
|
79
|
+
@__injection_str.each { |str| audit( str, @__opts ) }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def self.info
|
|
84
|
+
{
|
|
85
|
+
:name => 'SQLInjection',
|
|
86
|
+
:description => %q{SQL injection recon module},
|
|
87
|
+
:elements => [
|
|
88
|
+
Issue::Element::FORM,
|
|
89
|
+
Issue::Element::LINK,
|
|
90
|
+
Issue::Element::COOKIE,
|
|
91
|
+
Issue::Element::HEADER
|
|
92
|
+
],
|
|
93
|
+
:author => 'Tasos "Zapotek" Laskos <tasos.laskos@gmail.com> ',
|
|
94
|
+
:version => '0.1.4',
|
|
95
|
+
:references => {
|
|
96
|
+
'UnixWiz' => 'http://unixwiz.net/techtips/sql-injection.html',
|
|
97
|
+
'Wikipedia' => 'http://en.wikipedia.org/wiki/SQL_injection',
|
|
98
|
+
'SecuriTeam' => 'http://www.securiteam.com/securityreviews/5DP0N1P76E.html',
|
|
99
|
+
'OWASP' => 'http://www.owasp.org/index.php/SQL_Injection'
|
|
100
|
+
},
|
|
101
|
+
:targets => { 'Generic' => 'all' },
|
|
102
|
+
:issue => {
|
|
103
|
+
:name => %q{SQL Injection},
|
|
104
|
+
:description => %q{SQL code can be injected into the web application.},
|
|
105
|
+
:tags => [ 'sql','injection', 'regexp', 'database', 'error' ],
|
|
106
|
+
:cwe => '89',
|
|
107
|
+
:severity => Issue::Severity::HIGH,
|
|
108
|
+
:cvssv2 => '9.0',
|
|
109
|
+
:remedy_guidance => 'User inputs must be validated and filtered
|
|
110
|
+
before being included in database queries.',
|
|
111
|
+
:remedy_code => '',
|
|
112
|
+
:metasploitable => 'unix/webapp/arachni_sqlmap'
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
}
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
System\.Data\.OleDb\.OleDbException
|
|
2
|
+
\[SQL Server\]
|
|
3
|
+
\[Microsoft\]\[ODBC SQL Server Driver\]
|
|
4
|
+
\[SQLServer JDBC Driver\]
|
|
5
|
+
\[SqlException
|
|
6
|
+
System\.Data\.SqlClient\.SqlException
|
|
7
|
+
Unclosed quotation mark after the character string
|
|
8
|
+
'80040e14'
|
|
9
|
+
mssql_query\(\)
|
|
10
|
+
odbc_exec\(\)
|
|
11
|
+
Microsoft OLE DB Provider for ODBC Drivers
|
|
12
|
+
Microsoft OLE DB Provider for SQL Server
|
|
13
|
+
Incorrect syntax near
|
|
14
|
+
Sintaxis incorrecta cerca de
|
|
15
|
+
Syntax error in string in query expression
|
|
16
|
+
ADODB\.Field \(0x800A0BCD\)<br>
|
|
17
|
+
Procedure '[^']+' requires parameter '[^']+'
|
|
18
|
+
ADODB\.Recordset\'
|
|
19
|
+
Unclosed quotation mark before the character string
|
|
20
|
+
SQLCODE
|
|
21
|
+
DB2 SQL error:
|
|
22
|
+
SQLSTATE
|
|
23
|
+
\[IBM\]\[CLI Driver\]\[DB26000\]
|
|
24
|
+
\[CLI Driver\]
|
|
25
|
+
\[DB26000\]
|
|
26
|
+
Sybase message:
|
|
27
|
+
Syntax error in query expression
|
|
28
|
+
Data type mismatch in criteria expression\.
|
|
29
|
+
Microsoft JET Database Engine
|
|
30
|
+
\[Microsoft\]\[ODBC Microsoft Access Driver\]
|
|
31
|
+
(PLS|ORA)-[0-9][0-9][0-9][0-9]
|
|
32
|
+
PostgreSQL query failed:
|
|
33
|
+
supplied argument is not a valid PostgreSQL result
|
|
34
|
+
pg_query\(\) \[:
|
|
35
|
+
pg_exec\(\) \[:
|
|
36
|
+
supplied argument is not a valid MySQL
|
|
37
|
+
Column count doesn't match value count at row
|
|
38
|
+
mysql_fetch_array\(\)
|
|
39
|
+
on MySQL result index
|
|
40
|
+
You have an error in your SQL syntax;
|
|
41
|
+
You have an error in your SQL syntax near
|
|
42
|
+
MySQL server version for the right syntax to use
|
|
43
|
+
\[MySQL\]\[ODBC
|
|
44
|
+
Column count doesn't match
|
|
45
|
+
the used select statements have different number of columns
|
|
46
|
+
Table '[^']+' doesn't exist
|
|
47
|
+
com\.informix\.jdbc
|
|
48
|
+
Dynamic Page Generation Error:
|
|
49
|
+
An illegal character has been found in the statement
|
|
50
|
+
<b>Warning<b>: ibase_
|
|
51
|
+
Dynamic SQL Error
|
|
52
|
+
\[DM_QUERY_E_SYNTAX\]
|
|
53
|
+
has occurred in the vicinity of:
|
|
54
|
+
A Parser Error \(syntax error\)
|
|
55
|
+
java\.sql\.SQLException
|
|
56
|
+
Unexpected end of command in statement
|
|
57
|
+
\[Macromedia\]\[SQLServer JDBC Driver\]
|
|
58
|
+
SELECT .*? FROM .*?
|
|
59
|
+
UPDATE .*? SET .*?
|
|
60
|
+
INSERT INTO .*?
|
|
61
|
+
Unknown column
|
|
62
|
+
where clause
|
|
63
|
+
SQL syntax.*MySQL
|
|
64
|
+
Warning.*mysql_.*
|
|
65
|
+
valid MySQL result
|
|
66
|
+
PostgreSQL.*ERROR
|
|
67
|
+
Warning.*pg_.*
|
|
68
|
+
valid PostgreSQL result
|
|
69
|
+
Driver.*SQL[\-\_\ ]*Server
|
|
70
|
+
OLE DB.*SQL Server
|
|
71
|
+
SQL Server.*Driver
|
|
72
|
+
Warning.*mssql_.*
|
|
73
|
+
Access.*Driver
|
|
74
|
+
Driver.*Access
|
|
75
|
+
JET Database Engine
|
|
76
|
+
Access Database Engine
|
|
77
|
+
ORA-[0-9][0-9][0-9][0-9]
|
|
78
|
+
Oracle error
|
|
79
|
+
Oracle.*Driver
|
|
80
|
+
Warning.*oci_.*
|
|
81
|
+
Warning.*ora_.*
|
|
82
|
+
CLI Driver.*DB2
|
|
83
|
+
DB2 SQL error
|
|
84
|
+
Exception.*Informix
|
|
85
|
+
Sybase message
|
|
86
|
+
Dynamic SQL Error
|
|
87
|
+
Warning.*sqlite_.*
|
|
88
|
+
SQLite/JDBCDriver
|
|
89
|
+
SQLite\.Exception
|
|
90
|
+
System\.Data\.SQLite\.SQLiteException
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Arachni
|
|
3
|
+
Copyright (c) 2010-2011 Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
|
|
4
|
+
|
|
5
|
+
This is free software; you can copy and distribute and modify
|
|
6
|
+
this program under the term of the GPL v2.0 License
|
|
7
|
+
(See LICENSE file for details)
|
|
8
|
+
|
|
9
|
+
=end
|
|
10
|
+
|
|
11
|
+
module Arachni
|
|
12
|
+
|
|
13
|
+
module Modules
|
|
14
|
+
|
|
15
|
+
#
|
|
16
|
+
# Blind SQL injection audit module
|
|
17
|
+
#
|
|
18
|
+
# It uses reverse-diff analysis of HTML code in order to determine successful
|
|
19
|
+
# blind SQL injections.
|
|
20
|
+
#
|
|
21
|
+
# @author: Tasos "Zapotek" Laskos
|
|
22
|
+
# <tasos.laskos@gmail.com>
|
|
23
|
+
# <zapotek@segfault.gr>
|
|
24
|
+
# @version: 0.3
|
|
25
|
+
#
|
|
26
|
+
# @see http://cwe.mitre.org/data/definitions/89.html
|
|
27
|
+
# @see http://capec.mitre.org/data/definitions/7.html
|
|
28
|
+
# @see http://www.owasp.org/index.php/Blind_SQL_Injection
|
|
29
|
+
#
|
|
30
|
+
class BlindrDiffSQLInjection < Arachni::Module::Base
|
|
31
|
+
|
|
32
|
+
include Arachni::Module::Utilities
|
|
33
|
+
|
|
34
|
+
def initialize( page )
|
|
35
|
+
super( page )
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def prepare( )
|
|
39
|
+
|
|
40
|
+
# possible quote characters used in SQL statements
|
|
41
|
+
@__quotes = [
|
|
42
|
+
'\'',
|
|
43
|
+
'"',
|
|
44
|
+
''
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
# this will cause a silent error if there's a blind SQL injection
|
|
48
|
+
@__bad_chars =[
|
|
49
|
+
'\'"`',
|
|
50
|
+
# we need 2 requests thus we change the second one a little bit to
|
|
51
|
+
# fool the Auditor's redundancy filter
|
|
52
|
+
'\'"``'
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
# %q% will be replaced by a character in @__quotes
|
|
56
|
+
@__injection = '%q% and %q%1'
|
|
57
|
+
|
|
58
|
+
@__opts = {
|
|
59
|
+
:format => [ Format::APPEND ],
|
|
60
|
+
# we need to do our own redundancy checks
|
|
61
|
+
:redundant => true
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# used for redundancy checks
|
|
65
|
+
@@__audited ||= Set.new
|
|
66
|
+
|
|
67
|
+
# this is the structure of the responses
|
|
68
|
+
@responses = {
|
|
69
|
+
:orig => '',
|
|
70
|
+
|
|
71
|
+
:good => {
|
|
72
|
+
|
|
73
|
+
},
|
|
74
|
+
:bad => {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def run( )
|
|
81
|
+
|
|
82
|
+
return if( __audited? )
|
|
83
|
+
|
|
84
|
+
if( !@page.query_vars || @page.query_vars.empty? )
|
|
85
|
+
print_status( 'Nothing to audit on current page, skipping...' )
|
|
86
|
+
return
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# get the link object that fits the URL of the page
|
|
90
|
+
# this will be the one to audit
|
|
91
|
+
@page.links.each {
|
|
92
|
+
|link|
|
|
93
|
+
@__candidate = link if link.action == @page.url
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return if !@__candidate
|
|
97
|
+
|
|
98
|
+
# let's get a fresh rendering of the page to assist us with
|
|
99
|
+
# irrelevant dynamic content elimination (banners, ads, etc...)
|
|
100
|
+
@http.get( @page.url, :params => @page.query_vars ).on_complete {
|
|
101
|
+
|res|
|
|
102
|
+
|
|
103
|
+
# eliminate dynamic content that's context-irrelevant
|
|
104
|
+
# ie. changing with every refresh
|
|
105
|
+
@responses[:orig] = @page.html.rdiff( res.body )
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
# force the webapp to return an error page
|
|
109
|
+
prep_bad_responses( )
|
|
110
|
+
|
|
111
|
+
# start injecting 'good' SQL queries
|
|
112
|
+
prep_good_responses( )
|
|
113
|
+
|
|
114
|
+
@http.after_run {
|
|
115
|
+
# analyze the HTML code of the responses in order to determine
|
|
116
|
+
# which injections were succesfull
|
|
117
|
+
analyze( )
|
|
118
|
+
}
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Audits page with 'bad' SQL characters and gathers error pages
|
|
122
|
+
def prep_bad_responses( )
|
|
123
|
+
|
|
124
|
+
@__bad_chars.each {
|
|
125
|
+
|str|
|
|
126
|
+
|
|
127
|
+
# get injection variations that will hopefully cause an internal/silent
|
|
128
|
+
# SQL error
|
|
129
|
+
variations = @__candidate.injection_sets( str, @__opts )
|
|
130
|
+
|
|
131
|
+
@responses[:bad_total] = variations.size
|
|
132
|
+
|
|
133
|
+
variations.each {
|
|
134
|
+
|link|
|
|
135
|
+
|
|
136
|
+
# the altered link variable
|
|
137
|
+
altered = link.altered
|
|
138
|
+
|
|
139
|
+
print_status( @__candidate.get_status_str( altered ) )
|
|
140
|
+
|
|
141
|
+
# register us as the auditor
|
|
142
|
+
link.auditor( self )
|
|
143
|
+
# submit the link and get the response
|
|
144
|
+
link.submit( @__opts ).on_complete {
|
|
145
|
+
|res|
|
|
146
|
+
|
|
147
|
+
@responses[:bad][altered] ||= res.body.clone
|
|
148
|
+
|
|
149
|
+
# remove context-irrelevant dynamic content like banners and such
|
|
150
|
+
# from the error page
|
|
151
|
+
@responses[:bad][altered] = @responses[:bad][altered].rdiff( res.body.clone )
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Injects SQL code that doesn't affect the flow of execution nor presentation
|
|
158
|
+
def prep_good_responses( )
|
|
159
|
+
|
|
160
|
+
@__quotes.each {
|
|
161
|
+
|quote|
|
|
162
|
+
|
|
163
|
+
# prepare the statement with combinations of quote characters
|
|
164
|
+
str = @__injection.gsub( '%q%', quote )
|
|
165
|
+
|
|
166
|
+
variations = @__candidate.injection_sets( str, @__opts )
|
|
167
|
+
|
|
168
|
+
@responses[:good_total] = variations.size
|
|
169
|
+
|
|
170
|
+
variations.each {
|
|
171
|
+
|link|
|
|
172
|
+
|
|
173
|
+
# the altered link variable
|
|
174
|
+
altered = link.altered
|
|
175
|
+
|
|
176
|
+
# register us as the auditor
|
|
177
|
+
link.auditor( self )
|
|
178
|
+
|
|
179
|
+
# submit the link and get the response
|
|
180
|
+
link.submit( @__opts ).on_complete {
|
|
181
|
+
|res|
|
|
182
|
+
|
|
183
|
+
@responses[:good][altered] ||= []
|
|
184
|
+
|
|
185
|
+
# save the response for later analysis
|
|
186
|
+
@responses[:good][altered] << {
|
|
187
|
+
'str' => str,
|
|
188
|
+
'res' => res
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Goes through the responses induced by {#prep_good_responses} and {#__check} their code
|
|
198
|
+
def analyze( )
|
|
199
|
+
@responses[:good].keys.each {
|
|
200
|
+
|key|
|
|
201
|
+
@responses[:good][key].each {
|
|
202
|
+
|res|
|
|
203
|
+
__check( res['str'], res['res'], key )
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
#
|
|
209
|
+
# Compares HTML responses in order to identify successful blind sql injections
|
|
210
|
+
#
|
|
211
|
+
# @param [String] str the string that unveiled the vulnerability
|
|
212
|
+
# @param [Typhoeus::Response]
|
|
213
|
+
# @param [String] var the vulnerable variable
|
|
214
|
+
#
|
|
215
|
+
def __check( str, res, var )
|
|
216
|
+
|
|
217
|
+
# if one of the injections gives the same results as the
|
|
218
|
+
# original page then a blind SQL injection exists
|
|
219
|
+
check = res.body.rdiff( @page.html )
|
|
220
|
+
|
|
221
|
+
if( check == @responses[:orig] && @responses[:bad][var] != check &&
|
|
222
|
+
!@http.custom_404?( res ) && res.code == 200 )
|
|
223
|
+
__log_results( var, res, str )
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def clean_up
|
|
229
|
+
@@__audited << __audit_id( )
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def __audit_id
|
|
233
|
+
"#{URI( normalize_url( @page.url ) ).path}::#{@page.query_vars.keys}"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def __audited?
|
|
237
|
+
@@__audited.include?( __audit_id( ) )
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def self.info
|
|
242
|
+
{
|
|
243
|
+
:name => 'Blind (rDiff) SQL Injection',
|
|
244
|
+
:description => %q{It uses rDiff analysis to decide how different inputs affect
|
|
245
|
+
the behavior of the the web pages.
|
|
246
|
+
Using that as a basis it extrapolates about what inputs are vulnerable to blind SQL injection.
|
|
247
|
+
(Note: This module may get confused by certain types of XSS vulnerabilities.
|
|
248
|
+
If this module returns a positive result you should investigate nonetheless.)},
|
|
249
|
+
:elements => [
|
|
250
|
+
Issue::Element::LINK
|
|
251
|
+
],
|
|
252
|
+
:author => 'Tasos "Zapotek" Laskos <tasos.laskos@gmail.com> ',
|
|
253
|
+
:version => '0.2.2',
|
|
254
|
+
:references => {
|
|
255
|
+
'OWASP' => 'http://www.owasp.org/index.php/Blind_SQL_Injection',
|
|
256
|
+
'MITRE - CAPEC' => 'http://capec.mitre.org/data/definitions/7.html'
|
|
257
|
+
},
|
|
258
|
+
:targets => { 'Generic' => 'all' },
|
|
259
|
+
|
|
260
|
+
:issue => {
|
|
261
|
+
:name => %q{Blind SQL Injection},
|
|
262
|
+
:description => %q{SQL code can be injected into the web application
|
|
263
|
+
even though it may not be obvious due to suppression of error messages.},
|
|
264
|
+
:tags => [ 'sql', 'blind', 'rdiff', 'injection', 'database' ],
|
|
265
|
+
:cwe => '89',
|
|
266
|
+
:severity => Issue::Severity::HIGH,
|
|
267
|
+
:cvssv2 => '9.0',
|
|
268
|
+
:remedy_guidance => %q{Suppression of error messages leads to
|
|
269
|
+
security through obscurity which is not a good practise.
|
|
270
|
+
The web application needs to enforce stronger validation
|
|
271
|
+
on user inputs.},
|
|
272
|
+
:remedy_code => '',
|
|
273
|
+
:metasploitable => 'unix/webapp/arachni_sqlmap'
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
}
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
private
|
|
280
|
+
|
|
281
|
+
def __log_results( var, res, str )
|
|
282
|
+
|
|
283
|
+
url = res.effective_url
|
|
284
|
+
|
|
285
|
+
# since we bypassed the auditor completely we need to create
|
|
286
|
+
# our own opts hash and pass it to the Vulnerability class.
|
|
287
|
+
#
|
|
288
|
+
# this is only required for Metasploitable vulnerabilities
|
|
289
|
+
opts = {
|
|
290
|
+
:injected_orig => URI( @page.url ).query,
|
|
291
|
+
:combo => @__candidate.auditable
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
issue = Issue.new( {
|
|
295
|
+
:var => var,
|
|
296
|
+
:url => url,
|
|
297
|
+
:method => res.request.method.to_s,
|
|
298
|
+
:opts => opts,
|
|
299
|
+
:injected => str,
|
|
300
|
+
:id => str,
|
|
301
|
+
:regexp => 'n/a',
|
|
302
|
+
:regexp_match => 'n/a',
|
|
303
|
+
:elem => Issue::Element::LINK,
|
|
304
|
+
:response => res.body,
|
|
305
|
+
:verification => true,
|
|
306
|
+
:headers => {
|
|
307
|
+
:request => res.request.headers,
|
|
308
|
+
:response => res.headers,
|
|
309
|
+
}
|
|
310
|
+
}.merge( self.class.info )
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
print_ok( "In #{Issue::Element::LINK} var '#{var}' ( #{url} )" )
|
|
314
|
+
|
|
315
|
+
# register our results with the system
|
|
316
|
+
register_results( [ issue ] )
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|