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,301 @@
|
|
|
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
|
+
# Cross-Site Request Forgery audit module.
|
|
17
|
+
#
|
|
18
|
+
# It uses 4-pass reverse-diff analysis to determine which forms affect business logic
|
|
19
|
+
# and audits them for CSRF.
|
|
20
|
+
#
|
|
21
|
+
# Using this technique noise/false-positives should be kept to a minimum,
|
|
22
|
+
# however we do need to jump through some hoops.
|
|
23
|
+
#
|
|
24
|
+
# The technique used to identify which forms are CSRF worthy is described bellow.
|
|
25
|
+
#
|
|
26
|
+
# === 4-pass rDiff CSRF detection:
|
|
27
|
+
#
|
|
28
|
+
# * Request each page *without* cookies
|
|
29
|
+
# * Extract forms.
|
|
30
|
+
# * Request each page *with* cookies
|
|
31
|
+
# * Extract forms.
|
|
32
|
+
# * Check forms that appear *only* when logged-in for CSRF.
|
|
33
|
+
#
|
|
34
|
+
# In order for the module to give meaningful results a valid cookie-jar of a logged-in
|
|
35
|
+
# user must be supplied to the framework.
|
|
36
|
+
#
|
|
37
|
+
# However, as Arachni goes through the system it will gather
|
|
38
|
+
# cookies just like a user would, so if there are forms that only appear
|
|
39
|
+
# after a guest has performed a previous event it will check these too.
|
|
40
|
+
#
|
|
41
|
+
# @author: Tasos "Zapotek" Laskos
|
|
42
|
+
# <tasos.laskos@gmail.com>
|
|
43
|
+
# <zapotek@segfault.gr>
|
|
44
|
+
# @version: 0.2
|
|
45
|
+
#
|
|
46
|
+
# @see http://en.wikipedia.org/wiki/Cross-site_request_forgery
|
|
47
|
+
# @see http://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
|
|
48
|
+
# @see http://www.cgisecurity.com/csrf-faq.html
|
|
49
|
+
# @see http://cwe.mitre.org/data/definitions/352.html
|
|
50
|
+
#
|
|
51
|
+
class CSRF < Arachni::Module::Base
|
|
52
|
+
|
|
53
|
+
def initialize( page )
|
|
54
|
+
super( page )
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def prepare( )
|
|
58
|
+
|
|
59
|
+
# the Trainer can provide modules access to the HTML parser
|
|
60
|
+
# and other cool stuff for element comparison
|
|
61
|
+
@__trainer = @http.trainer
|
|
62
|
+
|
|
63
|
+
# since we bypass the Auditor we must also do our own audit tracking
|
|
64
|
+
@@__audited ||= Set.new
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def run( )
|
|
68
|
+
|
|
69
|
+
print_status( 'Looking for CSRF candidates...' )
|
|
70
|
+
|
|
71
|
+
print_status( 'Simulating logged-out user.' )
|
|
72
|
+
|
|
73
|
+
# setup opts with empty cookies
|
|
74
|
+
opts = {
|
|
75
|
+
:headers => {
|
|
76
|
+
'cookie' => ''
|
|
77
|
+
},
|
|
78
|
+
:remove_id => true
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# request page without cookies, simulating a logged-out user
|
|
82
|
+
@http.get( @page.url, opts ).on_complete {
|
|
83
|
+
|res|
|
|
84
|
+
|
|
85
|
+
# set-up the parser with the proper url so that it
|
|
86
|
+
# can fix broken 'action' attrs and the like
|
|
87
|
+
@parser = Arachni::Parser.new( Arachni::Options.instance, res )
|
|
88
|
+
|
|
89
|
+
# extract forms from the body of the response
|
|
90
|
+
forms_logged_out = @parser.forms( res.body ).reject {
|
|
91
|
+
|form|
|
|
92
|
+
form.auditable.empty?
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
print_status( "Found #{forms_logged_out.size.to_s} context irrelevant forms." )
|
|
96
|
+
|
|
97
|
+
# get forms that are worthy of testing for CSRF
|
|
98
|
+
# i.e. apper only when the user is logged-in
|
|
99
|
+
csrf_forms = logged_in_only( forms_logged_out )
|
|
100
|
+
|
|
101
|
+
print_status( "Found #{csrf_forms.size.to_s} CSRF candidates." )
|
|
102
|
+
|
|
103
|
+
csrf_forms.each {
|
|
104
|
+
|form|
|
|
105
|
+
__log( form ) if unsafe?( form )
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
#
|
|
113
|
+
# Tries to detect if a form is protected using an anti-CSRF token.
|
|
114
|
+
#
|
|
115
|
+
# @param [Hash] form
|
|
116
|
+
#
|
|
117
|
+
# @return [Bool] true if the form if vulnerable, false otherwise
|
|
118
|
+
#
|
|
119
|
+
def unsafe?( form )
|
|
120
|
+
|
|
121
|
+
found_token = false
|
|
122
|
+
|
|
123
|
+
# nobody says that tokens must be in a 'value' attribute,
|
|
124
|
+
# they can just as well be in 'name'.
|
|
125
|
+
# so we check them both...
|
|
126
|
+
form.simple['auditable'].to_a.flatten.each_with_index {
|
|
127
|
+
|str, i|
|
|
128
|
+
next if !str
|
|
129
|
+
next if !form.raw['auditable'][i]
|
|
130
|
+
next if !form.raw['auditable'][i]['type']
|
|
131
|
+
next if form.raw['auditable'][i]['type'].downcase != 'hidden'
|
|
132
|
+
|
|
133
|
+
found_token = true if( csrf_token?( str ) )
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
link_vars = @parser.link_vars( form.action )
|
|
137
|
+
if( !link_vars.empty? )
|
|
138
|
+
# and we also need to check for a token in the form action
|
|
139
|
+
link_vars.values.each {
|
|
140
|
+
|val|
|
|
141
|
+
next if !val
|
|
142
|
+
found_token = true if( csrf_token?( val ) )
|
|
143
|
+
}
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
return !found_token
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
#
|
|
150
|
+
# Returns forms that only appear when the user is logged-in.
|
|
151
|
+
#
|
|
152
|
+
# These are the forms that will most likely affect business logic.
|
|
153
|
+
#
|
|
154
|
+
# @param [Array] forms_logged_out forms that appear while logged-out
|
|
155
|
+
# in order to eliminate them.
|
|
156
|
+
#
|
|
157
|
+
# @return [Array] forms to be checked for CSRF
|
|
158
|
+
#
|
|
159
|
+
def logged_in_only( logged_out )
|
|
160
|
+
csrf_forms = []
|
|
161
|
+
|
|
162
|
+
@page.forms.each {
|
|
163
|
+
|form|
|
|
164
|
+
|
|
165
|
+
next if form.auditable.size == 0
|
|
166
|
+
|
|
167
|
+
if !( forms_include?( logged_out, form ) )
|
|
168
|
+
csrf_forms << form
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return csrf_forms
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def forms_include?( forms, form )
|
|
177
|
+
|
|
178
|
+
forms.each {
|
|
179
|
+
|i_form|
|
|
180
|
+
|
|
181
|
+
if( form.id == i_form.id )
|
|
182
|
+
return true
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return false
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
#
|
|
191
|
+
# Checks if the str is an anti-CSRF token of base10/16/32/64.
|
|
192
|
+
#
|
|
193
|
+
# @param [String] str
|
|
194
|
+
#
|
|
195
|
+
def csrf_token?( str )
|
|
196
|
+
|
|
197
|
+
# we could use regexps but i kinda like lcamtuf's (Michal's) way
|
|
198
|
+
base16_len_min = 8
|
|
199
|
+
base16_len_max = 45
|
|
200
|
+
base16_digit_num = 2
|
|
201
|
+
|
|
202
|
+
base64_len_min = 6
|
|
203
|
+
base64_len_max = 32
|
|
204
|
+
base64_digit_num = 1
|
|
205
|
+
base64_case = 2
|
|
206
|
+
base64_digit_num2 = 3
|
|
207
|
+
base64_slash_cnt = 2
|
|
208
|
+
|
|
209
|
+
len = str.size
|
|
210
|
+
digit_cnt = str.scan(/[0-9]+/).join( '' ).size
|
|
211
|
+
|
|
212
|
+
if( len >= base16_len_min &&
|
|
213
|
+
len <= base16_len_max &&
|
|
214
|
+
digit_cnt >= base16_digit_num
|
|
215
|
+
)
|
|
216
|
+
return true
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
upper_cnt = str.scan(/[A-Z]+/).join( '' ).size
|
|
220
|
+
slash_cnt = str.scan(/\/+/).join( '' ).size
|
|
221
|
+
|
|
222
|
+
if( len >= base64_len_min && len <= base64_len_max &&
|
|
223
|
+
( ( digit_cnt >= base64_digit_num && upper_cnt >= base64_case ) ||
|
|
224
|
+
digit_cnt >= base64_digit_num2 ) &&
|
|
225
|
+
slash_cnt <= base64_slash_cnt
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
return true
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
return false
|
|
232
|
+
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def __log( form )
|
|
237
|
+
|
|
238
|
+
url = form.action
|
|
239
|
+
name = form.raw['attrs']['name'] || form.raw['attrs']['id']
|
|
240
|
+
|
|
241
|
+
if @@__audited.include?( "#{url}::#{name.to_s}" )
|
|
242
|
+
print_info( 'Skipping already audited form with name \'' +
|
|
243
|
+
name.to_s + '\' of url: ' + url )
|
|
244
|
+
return
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
@@__audited << "#{url}::#{name}"
|
|
248
|
+
|
|
249
|
+
# append the result to the results array
|
|
250
|
+
issue = Issue.new( {
|
|
251
|
+
:var => name,
|
|
252
|
+
:url => url,
|
|
253
|
+
:elem => Issue::Element::FORM,
|
|
254
|
+
:response => @page.html,
|
|
255
|
+
}.merge( self.class.info ) )
|
|
256
|
+
|
|
257
|
+
print_ok( "Found unprotected form with name '#{name}' at '#{url}'" )
|
|
258
|
+
register_results( [ issue ] )
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def self.info
|
|
262
|
+
{
|
|
263
|
+
:name => 'CSRF',
|
|
264
|
+
:description => %q{It uses 2-pass rDiff analysis to determine
|
|
265
|
+
which forms affect business logic and audits them for CSRF.
|
|
266
|
+
It requires a logged-in user's cookie-jar.},
|
|
267
|
+
:elements => [
|
|
268
|
+
Issue::Element::FORM
|
|
269
|
+
],
|
|
270
|
+
:author => 'Tasos "Zapotek" Laskos <tasos.laskos@gmail.com> ',
|
|
271
|
+
:version => '0.2',
|
|
272
|
+
:references => {
|
|
273
|
+
'Wikipedia' => 'http://en.wikipedia.org/wiki/Cross-site_request_forgery',
|
|
274
|
+
'OWASP' => 'http://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)',
|
|
275
|
+
'CGI Security' => 'http://www.cgisecurity.com/csrf-faq.html'
|
|
276
|
+
},
|
|
277
|
+
:targets => { 'Generic' => 'all' },
|
|
278
|
+
|
|
279
|
+
:issue => {
|
|
280
|
+
:name => %q{Cross-Site Request Forgery},
|
|
281
|
+
:description => %q{The web application does not, or can not,
|
|
282
|
+
sufficiently verify whether a well-formed, valid, consistent
|
|
283
|
+
request was intentionally provided by the user who submitted the request.
|
|
284
|
+
This is due to a lack of secure anti-CSRF tokens to verify
|
|
285
|
+
the freshness of the submitted data.},
|
|
286
|
+
:tags => [ 'csrf', 'rdiff', 'form', 'token' ],
|
|
287
|
+
:cwe => '352',
|
|
288
|
+
:severity => Issue::Severity::HIGH,
|
|
289
|
+
:cvssv2 => '',
|
|
290
|
+
:remedy_guidance => %q{A unique token that guaranties freshness of submitted
|
|
291
|
+
data must be added to all web application elements that can affect
|
|
292
|
+
business logic.},
|
|
293
|
+
:remedy_code => '',
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
}
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
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
|
+
# LDAP injection audit module.
|
|
19
|
+
#
|
|
20
|
+
# @author: Tasos "Zapotek" Laskos
|
|
21
|
+
# <tasos.laskos@gmail.com>
|
|
22
|
+
# <zapotek@segfault.gr>
|
|
23
|
+
# @version: 0.1
|
|
24
|
+
#
|
|
25
|
+
# @see http://cwe.mitre.org/data/definitions/90.html
|
|
26
|
+
# @see http://projects.webappsec.org/w/page/13246947/LDAP-Injection
|
|
27
|
+
# @see http://www.owasp.org/index.php/LDAP_injection
|
|
28
|
+
#
|
|
29
|
+
class LDAPInjection < Arachni::Module::Base
|
|
30
|
+
|
|
31
|
+
include Arachni::Module::Utilities
|
|
32
|
+
|
|
33
|
+
def initialize( page )
|
|
34
|
+
super( page )
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def prepare( )
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# we make this a class variable and populate it only once
|
|
41
|
+
# to reduce file IO
|
|
42
|
+
#
|
|
43
|
+
@@__errors ||= []
|
|
44
|
+
|
|
45
|
+
if @@__errors.empty?
|
|
46
|
+
read_file( 'errors.txt' ) { |error| @@__errors << error }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# prepare the strings that will hopefully cause the webapp
|
|
51
|
+
# to output LDAP error messages
|
|
52
|
+
@__injection_str = "#^($!@$)(()))******"
|
|
53
|
+
|
|
54
|
+
@__opts = {
|
|
55
|
+
:format => [ Format::APPEND ],
|
|
56
|
+
:substring => @@__errors
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def run( )
|
|
62
|
+
audit( @__injection_str, @__opts )
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def self.info
|
|
67
|
+
{
|
|
68
|
+
:name => 'LDAPInjection',
|
|
69
|
+
:description => %q{It tries to force the web application to
|
|
70
|
+
return LDAP error messages in order to discover failures
|
|
71
|
+
in user input validation.},
|
|
72
|
+
:elements => [
|
|
73
|
+
Issue::Element::FORM,
|
|
74
|
+
Issue::Element::LINK,
|
|
75
|
+
Issue::Element::COOKIE,
|
|
76
|
+
Issue::Element::HEADER
|
|
77
|
+
],
|
|
78
|
+
:author => 'Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>',
|
|
79
|
+
:version => '0.1',
|
|
80
|
+
:references => {
|
|
81
|
+
'WASC' => 'http://projects.webappsec.org/w/page/13246947/LDAP-Injection',
|
|
82
|
+
'OWASP' => 'http://www.owasp.org/index.php/LDAP_injection'
|
|
83
|
+
},
|
|
84
|
+
:targets => { 'Generic' => 'all' },
|
|
85
|
+
:issue => {
|
|
86
|
+
:name => %q{LDAP Injection},
|
|
87
|
+
:description => %q{LDAP queries can be injected into the web application
|
|
88
|
+
which can be used to disclose sensitive data of affect the execution flow.},
|
|
89
|
+
:tags => [ 'ldap', 'injection', 'regexp' ],
|
|
90
|
+
:cwe => '90',
|
|
91
|
+
:severity => Issue::Severity::HIGH,
|
|
92
|
+
:cvssv2 => '',
|
|
93
|
+
:remedy_guidance => %q{User inputs must be validated and filtered
|
|
94
|
+
before being used in an LDAP query.},
|
|
95
|
+
:remedy_code => ''
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
supplied argument is not a valid ldap
|
|
2
|
+
javax.naming.NameNotFoundException
|
|
3
|
+
LDAPException
|
|
4
|
+
com.sun.jndi.ldap
|
|
5
|
+
Search: Bad search filter
|
|
6
|
+
Protocol error occurred
|
|
7
|
+
Size limit has exceeded
|
|
8
|
+
An inappropriate matching occurred
|
|
9
|
+
A constraint violation occurred
|
|
10
|
+
The syntax is invalid
|
|
11
|
+
Object does not exist
|
|
12
|
+
The alias is invalid
|
|
13
|
+
The distinguished name has an invalid syntax
|
|
14
|
+
The server does not handle directory requests
|
|
15
|
+
There was a naming violation
|
|
16
|
+
There was an object class violation
|
|
17
|
+
Results returned are too large
|
|
18
|
+
Unknown error occurred
|
|
19
|
+
Local error occurred
|
|
20
|
+
The search filter is incorrect
|
|
21
|
+
The search filter is invalid
|
|
22
|
+
The search filter cannot be recognized
|
|
23
|
+
Invalid DN syntax
|
|
24
|
+
No Such Object
|
|
25
|
+
IPWorksASP.LDAP
|
|
26
|
+
Module Products.LDAPMultiPlugins
|
|
@@ -0,0 +1,103 @@
|
|
|
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
|
+
# Simple OS command injection module.
|
|
17
|
+
#
|
|
18
|
+
# @author: Tasos "Zapotek" Laskos
|
|
19
|
+
# <tasos.laskos@gmail.com>
|
|
20
|
+
# <zapotek@segfault.gr>
|
|
21
|
+
# @version: 0.1.3
|
|
22
|
+
#
|
|
23
|
+
# @see http://cwe.mitre.org/data/definitions/78.html
|
|
24
|
+
# @see http://www.owasp.org/index.php/OS_Command_Injection
|
|
25
|
+
#
|
|
26
|
+
class OSCmdInjection < Arachni::Module::Base
|
|
27
|
+
|
|
28
|
+
include Arachni::Module::Utilities
|
|
29
|
+
|
|
30
|
+
def initialize( page )
|
|
31
|
+
super( page )
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def prepare
|
|
35
|
+
|
|
36
|
+
@__opts = {}
|
|
37
|
+
@__opts[:regexp] = [
|
|
38
|
+
/\w+:.+:[0-9]+:[0-9]+:.+:[0-9a-zA-Z\/]+/i,
|
|
39
|
+
/\[boot loader\](.*)\[operating systems\]/i
|
|
40
|
+
]
|
|
41
|
+
@__opts[:format] = [ Format::STRAIGHT ]
|
|
42
|
+
|
|
43
|
+
@@__injection_str ||= []
|
|
44
|
+
|
|
45
|
+
if @@__injection_str.empty?
|
|
46
|
+
read_file( 'payloads.txt' ) {
|
|
47
|
+
|str|
|
|
48
|
+
|
|
49
|
+
[ '', '&&', '|', ';' ].each {
|
|
50
|
+
|sep|
|
|
51
|
+
@@__injection_str << sep + " " + str
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@@__injection_str << "`" + " " + str + "`"
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def run( )
|
|
61
|
+
@@__injection_str.each {
|
|
62
|
+
|str|
|
|
63
|
+
audit( str, @__opts )
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def self.info
|
|
69
|
+
{
|
|
70
|
+
:name => 'OS command injection',
|
|
71
|
+
:description => %q{Tries to find operating system command injections.},
|
|
72
|
+
:elements => [
|
|
73
|
+
Issue::Element::FORM,
|
|
74
|
+
Issue::Element::LINK,
|
|
75
|
+
Issue::Element::COOKIE,
|
|
76
|
+
Issue::Element::HEADER
|
|
77
|
+
],
|
|
78
|
+
:author => 'Tasos "Zapotek" Laskos <tasos.laskos@gmail.com> ',
|
|
79
|
+
:version => '0.1.3',
|
|
80
|
+
:references => {
|
|
81
|
+
'OWASP' => 'http://www.owasp.org/index.php/OS_Command_Injection'
|
|
82
|
+
},
|
|
83
|
+
:targets => { 'Generic' => 'all' },
|
|
84
|
+
:issue => {
|
|
85
|
+
:name => %q{Operating system command injection},
|
|
86
|
+
:description => %q{The web application allows an attacker to
|
|
87
|
+
execute arbitrary OS commands.},
|
|
88
|
+
:tags => [ 'os', 'command', 'code', 'injection', 'regexp' ],
|
|
89
|
+
:cwe => '78',
|
|
90
|
+
:severity => Issue::Severity::HIGH,
|
|
91
|
+
:cvssv2 => '9.0',
|
|
92
|
+
:remedy_guidance => %q{User inputs must be validated and filtered
|
|
93
|
+
before being evaluated as OS level commands.},
|
|
94
|
+
:remedy_code => '',
|
|
95
|
+
:metasploitable => 'unix/webapp/arachni_exec'
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|