arachni 1.1 → 1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +159 -0
- data/LICENSE.md +126 -196
- data/README.md +32 -24
- data/arachni.gemspec +7 -7
- data/components/checks/active/code_injection_timing.rb +3 -3
- data/components/checks/active/csrf.rb +2 -2
- data/components/checks/active/file_inclusion.rb +6 -7
- data/components/checks/active/os_cmd_injection.rb +3 -3
- data/components/checks/active/path_traversal.rb +7 -7
- data/components/checks/active/response_splitting.rb +9 -4
- data/components/checks/active/session_fixation.rb +7 -3
- data/components/checks/active/source_code_disclosure.rb +5 -5
- data/components/checks/active/unvalidated_redirect.rb +12 -3
- data/components/checks/active/unvalidated_redirect_dom.rb +3 -3
- data/components/checks/active/xss.rb +23 -10
- data/components/checks/active/xss_dom_inputs.rb +113 -11
- data/components/checks/active/xxe.rb +3 -3
- data/components/checks/passive/backdoors.rb +6 -5
- data/components/checks/passive/backup_directories.rb +6 -6
- data/components/checks/passive/backup_files.rb +6 -6
- data/components/checks/passive/common_admin_interfaces.rb +58 -0
- data/components/checks/passive/common_admin_interfaces/admin-panels.txt +49 -0
- data/components/checks/passive/common_directories/directories.txt +0 -16
- data/components/checks/passive/common_files.rb +6 -5
- data/components/checks/passive/common_files/filenames.txt +0 -2
- data/components/checks/passive/directory_listing.rb +6 -6
- data/components/checks/passive/grep/cookie_set_for_parent_domain.rb +3 -3
- data/components/checks/passive/grep/hsts.rb +6 -3
- data/components/checks/passive/grep/http_only_cookies.rb +3 -3
- data/components/checks/passive/grep/insecure_cookies.rb +2 -2
- data/components/checks/passive/grep/insecure_cors_policy.rb +6 -4
- data/components/checks/passive/grep/x_frame_options.rb +6 -4
- data/components/checks/passive/htaccess_limit.rb +6 -2
- data/components/checks/passive/http_put.rb +8 -4
- data/components/checks/passive/interesting_responses.rb +3 -2
- data/components/checks/passive/localstart_asp.rb +6 -2
- data/components/checks/passive/origin_spoof_access_restriction_bypass.rb +5 -1
- data/components/checks/passive/xst.rb +6 -2
- data/components/fingerprinters/frameworks/aspx_mvc.rb +43 -0
- data/components/fingerprinters/frameworks/cakephp.rb +28 -0
- data/components/fingerprinters/frameworks/cherrypy.rb +31 -0
- data/components/fingerprinters/frameworks/django.rb +33 -0
- data/components/fingerprinters/frameworks/jsf.rb +30 -0
- data/components/fingerprinters/frameworks/rack.rb +5 -7
- data/components/fingerprinters/frameworks/rails.rb +43 -0
- data/components/fingerprinters/languages/aspx.rb +11 -11
- data/components/fingerprinters/languages/{jsp.rb → java.rb} +11 -7
- data/components/fingerprinters/languages/php.rb +6 -6
- data/components/fingerprinters/languages/python.rb +14 -6
- data/components/fingerprinters/languages/ruby.rb +3 -5
- data/components/fingerprinters/servers/apache.rb +5 -4
- data/components/fingerprinters/servers/gunicorn.rb +33 -0
- data/components/fingerprinters/servers/jetty.rb +1 -1
- data/components/fingerprinters/servers/tomcat.rb +11 -4
- data/components/path_extractors/anchors.rb +5 -12
- data/components/path_extractors/areas.rb +5 -13
- data/components/path_extractors/comments.rb +5 -3
- data/components/path_extractors/data_url.rb +21 -0
- data/components/path_extractors/forms.rb +5 -13
- data/components/path_extractors/frames.rb +6 -13
- data/components/path_extractors/generic.rb +3 -12
- data/components/path_extractors/links.rb +5 -13
- data/components/path_extractors/meta_refresh.rb +5 -13
- data/components/path_extractors/scripts.rb +8 -14
- data/components/plugins/autologin.rb +17 -5
- data/components/plugins/defaults/meta/remedies/discovery.rb +11 -29
- data/components/plugins/login_script.rb +40 -10
- data/components/plugins/metrics.rb +235 -0
- data/components/plugins/proxy.rb +21 -4
- data/components/plugins/proxy/panel/page_accordion.html.erb +34 -2
- data/components/plugins/restrict_to_dom_state.rb +70 -0
- data/components/plugins/vector_feed.rb +38 -9
- data/components/reporters/plugin_formatters/html/metrics.rb +290 -0
- data/components/reporters/plugin_formatters/stdout/metrics.rb +80 -0
- data/components/reporters/plugin_formatters/xml/metrics.rb +29 -0
- data/components/reporters/stdout.rb +4 -2
- data/components/reporters/xml.rb +4 -4
- data/components/reporters/xml/schema.xsd +95 -0
- data/lib/arachni.rb +2 -0
- data/lib/arachni/browser.rb +132 -77
- data/lib/arachni/browser/javascript.rb +173 -45
- data/lib/arachni/browser/javascript/scripts/dom_monitor.js +81 -6
- data/lib/arachni/browser/javascript/scripts/taint_tracer.js +31 -3
- data/lib/arachni/browser_cluster.rb +41 -15
- data/lib/arachni/browser_cluster/job.rb +4 -0
- data/lib/arachni/browser_cluster/jobs/resource_exploration.rb +0 -9
- data/lib/arachni/browser_cluster/worker.rb +8 -5
- data/lib/arachni/check/auditor.rb +20 -8
- data/lib/arachni/check/base.rb +38 -6
- data/lib/arachni/element/base.rb +18 -1
- data/lib/arachni/element/capabilities/analyzable/differential.rb +0 -1
- data/lib/arachni/element/capabilities/analyzable/taint.rb +40 -10
- data/lib/arachni/element/capabilities/analyzable/timeout.rb +27 -23
- data/lib/arachni/element/capabilities/auditable/dom.rb +22 -0
- data/lib/arachni/element/capabilities/inputtable.rb +6 -2
- data/lib/arachni/element/capabilities/submittable.rb +1 -1
- data/lib/arachni/element/cookie.rb +37 -23
- data/lib/arachni/element/cookie/capabilities/mutable.rb +6 -6
- data/lib/arachni/element/cookie/dom.rb +0 -8
- data/lib/arachni/element/form.rb +28 -14
- data/lib/arachni/element/form/capabilities/auditable.rb +2 -2
- data/lib/arachni/element/form/capabilities/mutable.rb +5 -5
- data/lib/arachni/element/form/dom.rb +0 -8
- data/lib/arachni/element/generic_dom.rb +1 -1
- data/lib/arachni/element/json.rb +2 -1
- data/lib/arachni/element/json/capabilities/inputtable.rb +6 -6
- data/lib/arachni/element/json/capabilities/mutable.rb +1 -1
- data/lib/arachni/element/link.rb +13 -16
- data/lib/arachni/element/link/dom.rb +1 -14
- data/lib/arachni/element/link_template.rb +3 -2
- data/lib/arachni/element/link_template/dom.rb +0 -16
- data/lib/arachni/element/server.rb +51 -9
- data/lib/arachni/element/xml.rb +1 -0
- data/lib/arachni/ethon/easy.rb +4 -1
- data/lib/arachni/framework/parts/audit.rb +26 -77
- data/lib/arachni/framework/parts/browser.rb +50 -55
- data/lib/arachni/framework/parts/check.rb +4 -3
- data/lib/arachni/framework/parts/data.rb +41 -6
- data/lib/arachni/framework/parts/state.rb +16 -7
- data/lib/arachni/http/client.rb +66 -38
- data/lib/arachni/http/client/dynamic_404_handler.rb +46 -14
- data/lib/arachni/http/headers.rb +22 -10
- data/lib/arachni/http/proxy_server.rb +67 -22
- data/lib/arachni/http/proxy_server/ssl-interceptor-cacert.pem +34 -0
- data/lib/arachni/http/proxy_server/ssl-interceptor-cakey.pem +51 -0
- data/lib/arachni/http/request.rb +71 -18
- data/lib/arachni/issue.rb +17 -3
- data/lib/arachni/option_groups/browser_cluster.rb +34 -1
- data/lib/arachni/option_groups/http.rb +1 -1
- data/lib/arachni/page.rb +26 -13
- data/lib/arachni/page/dom/transition.rb +2 -2
- data/lib/arachni/parser.rb +28 -11
- data/lib/arachni/platform/fingerprinter.rb +5 -0
- data/lib/arachni/platform/manager.rb +65 -32
- data/lib/arachni/plugin/base.rb +8 -0
- data/lib/arachni/processes/instances.rb +25 -11
- data/lib/arachni/reporter/manager.rb +2 -2
- data/lib/arachni/rpc/client/instance.rb +4 -0
- data/lib/arachni/rpc/server/framework/master.rb +3 -3
- data/lib/arachni/rpc/server/framework/multi_instance.rb +0 -8
- data/lib/arachni/rpc/server/instance.rb +2 -1
- data/lib/arachni/ruby/array.rb +5 -0
- data/lib/arachni/ruby/hash.rb +5 -0
- data/lib/arachni/ruby/string.rb +2 -3
- data/lib/arachni/session.rb +32 -6
- data/lib/arachni/state/framework.rb +6 -2
- data/lib/arachni/support/cache.rb +1 -0
- data/lib/arachni/support/cache/base.rb +12 -8
- data/lib/arachni/support/cache/least_recently_pushed.rb +29 -0
- data/lib/arachni/support/cache/least_recently_used.rb +5 -8
- data/lib/arachni/support/cache/preference.rb +1 -1
- data/lib/arachni/support/cache/random_replacement.rb +1 -25
- data/lib/arachni/support/database/queue.rb +21 -8
- data/lib/arachni/support/lookup/base.rb +7 -1
- data/lib/arachni/support/mixins/observable.rb +3 -1
- data/lib/arachni/support/profiler.rb +51 -10
- data/lib/arachni/support/signature.rb +11 -2
- data/lib/arachni/trainer.rb +8 -2
- data/lib/arachni/uri.rb +28 -25
- data/lib/arachni/uri/scope.rb +1 -1
- data/lib/arachni/utilities.rb +8 -0
- data/lib/arachni/watir/element.rb +1 -1
- data/lib/version +1 -1
- data/spec/arachni/browser/javascript/dom_monitor_spec.rb +388 -53
- data/spec/arachni/browser/javascript/taint_tracer_spec.rb +41 -0
- data/spec/arachni/browser/javascript_spec.rb +235 -61
- data/spec/arachni/browser_cluster/jobs/resource_exploration_spec.rb +0 -9
- data/spec/arachni/browser_cluster_spec.rb +58 -10
- data/spec/arachni/browser_spec.rb +170 -26
- data/spec/arachni/check/auditor_spec.rb +22 -3
- data/spec/arachni/check/base_spec.rb +84 -0
- data/spec/arachni/element/body_spec.rb +1 -1
- data/spec/arachni/element/capabilities/analyzable/taint_spec.rb +3 -3
- data/spec/arachni/element/capabilities/analyzable/timeout_spec.rb +1 -1
- data/spec/arachni/element/cookie/dom_spec.rb +0 -9
- data/spec/arachni/element/cookie_spec.rb +85 -0
- data/spec/arachni/element/form/dom_spec.rb +0 -9
- data/spec/arachni/element/form_spec.rb +46 -3
- data/spec/arachni/element/json_spec.rb +20 -0
- data/spec/arachni/element/link/dom_spec.rb +0 -9
- data/spec/arachni/element/link_spec.rb +40 -15
- data/spec/arachni/element/link_template/dom_spec.rb +0 -8
- data/spec/arachni/element/link_template_spec.rb +2 -6
- data/spec/arachni/element/server_spec.rb +94 -8
- data/spec/arachni/element/xml_spec.rb +20 -0
- data/spec/arachni/framework/parts/audit_spec.rb +12 -14
- data/spec/arachni/framework/parts/browser_spec.rb +0 -171
- data/spec/arachni/framework/parts/platform_spec.rb +14 -8
- data/spec/arachni/framework/parts/report_spec.rb +1 -1
- data/spec/arachni/framework/parts/state_spec.rb +0 -9
- data/spec/arachni/http/client/dynamic_404_handlers_spec.rb +19 -0
- data/spec/arachni/http/client_spec.rb +169 -42
- data/spec/arachni/http/headers_spec.rb +18 -0
- data/spec/arachni/http/request_spec.rb +23 -0
- data/spec/arachni/issue_spec.rb +17 -6
- data/spec/arachni/page_spec.rb +22 -2
- data/spec/arachni/parser_spec.rb +5 -0
- data/spec/arachni/platform/manager_spec.rb +57 -25
- data/spec/arachni/reporter/manager_spec.rb +26 -0
- data/spec/arachni/rpc/server/active_options_spec.rb +9 -4
- data/spec/arachni/state/framework_spec.rb +2 -8
- data/spec/arachni/support/cache/least_recently_pushed_spec.rb +90 -0
- data/spec/arachni/support/cache/least_recently_used_spec.rb +5 -13
- data/spec/arachni/support/database/queue_spec.rb +7 -0
- data/spec/arachni/support/mixins/observable_spec.rb +15 -1
- data/spec/arachni/trainer_spec.rb +2 -2
- data/spec/components/checks/active/code_injection_timing_spec.rb +1 -1
- data/spec/components/checks/active/file_inclusion_spec.rb +6 -6
- data/spec/components/checks/active/path_traversal_spec.rb +2 -2
- data/spec/components/checks/active/source_code_disclosure_spec.rb +2 -2
- data/spec/components/checks/active/unvalidated_redirect_spec.rb +6 -6
- data/spec/components/checks/active/xss_dom_inputs_spec.rb +3 -5
- data/spec/components/checks/active/xss_dom_script_context_spec.rb +1 -1
- data/spec/components/checks/active/xss_spec.rb +5 -5
- data/spec/components/checks/passive/common_admin_interfaces_spec.rb +15 -0
- data/spec/components/checks/passive/interesting_responses_spec.rb +14 -1
- data/spec/components/fingerprinters/frameworks/aspx_mvc_spec.rb +31 -0
- data/spec/components/fingerprinters/frameworks/cakephp_spec.rb +22 -0
- data/spec/components/fingerprinters/frameworks/cherrypy_spec.rb +28 -0
- data/spec/components/fingerprinters/frameworks/django_spec.rb +37 -0
- data/spec/components/fingerprinters/frameworks/jsf_spec.rb +27 -0
- data/spec/components/fingerprinters/frameworks/rack_spec.rb +11 -14
- data/spec/components/fingerprinters/frameworks/rails_spec.rb +53 -0
- data/spec/components/fingerprinters/languages/asp_spec.rb +7 -9
- data/spec/components/fingerprinters/languages/aspx_spec.rb +10 -24
- data/spec/components/fingerprinters/languages/java_spec.rb +88 -0
- data/spec/components/fingerprinters/languages/php_spec.rb +19 -12
- data/spec/components/fingerprinters/languages/python_spec.rb +22 -9
- data/spec/components/fingerprinters/languages/ruby.rb +6 -4
- data/spec/components/fingerprinters/os/bsd_spec.rb +6 -4
- data/spec/components/fingerprinters/os/linux_spec.rb +6 -4
- data/spec/components/fingerprinters/os/solaris_spec.rb +6 -4
- data/spec/components/fingerprinters/os/unix_spec.rb +6 -4
- data/spec/components/fingerprinters/os/windows_spec.rb +6 -4
- data/spec/components/fingerprinters/servers/apache_spec.rb +15 -4
- data/spec/components/fingerprinters/servers/gunicorn_spec.rb +28 -0
- data/spec/components/fingerprinters/servers/iis_spec.rb +6 -6
- data/spec/components/fingerprinters/servers/jetty_spec.rb +6 -6
- data/spec/components/fingerprinters/servers/nginx_spec.rb +6 -4
- data/spec/components/fingerprinters/servers/tomcat_spec.rb +15 -6
- data/spec/components/path_extractors/data_url_spec.rb +19 -0
- data/spec/components/plugins/autologin_spec.rb +23 -0
- data/spec/components/plugins/login_script_spec.rb +112 -24
- data/spec/components/plugins/restrict_to_dom_state_spec.rb +16 -0
- data/spec/components/plugins/vector_feed_spec.rb +39 -1
- data/spec/support/factories/page/dom.rb +9 -4
- data/spec/support/factories/page/dom/transition.rb +31 -9
- data/spec/support/factories/scan_report.rb +8 -6
- data/spec/support/fixtures/empty/placeholder +0 -0
- data/spec/support/fixtures/report.afr +0 -0
- data/spec/support/fixtures/reporters/manager_spec/error.rb +18 -0
- data/spec/support/servers/arachni/browser.rb +117 -11
- data/spec/support/servers/arachni/browser/javascript/dom_monitor.rb +148 -4
- data/spec/support/servers/arachni/check/auditor.rb +4 -0
- data/spec/support/servers/arachni/element/cookie/cookie_dom.rb +1 -1
- data/spec/support/servers/arachni/http/client.rb +5 -0
- data/spec/support/servers/arachni/http/client/dynamic_404_handler.rb +13 -0
- data/spec/support/servers/checks/active/code_injection_timing.rb +1 -1
- data/spec/support/servers/checks/active/file_inclusion.rb +2 -2
- data/spec/support/servers/checks/active/path_traversal.rb +2 -2
- data/spec/support/servers/checks/active/source_code_disclosure.rb +40 -33
- data/spec/support/servers/checks/active/trainer_check.rb +9 -10
- data/spec/support/servers/checks/active/unvalidated_redirect_dom.rb +7 -4
- data/spec/support/servers/checks/active/xss.rb +35 -0
- data/spec/support/servers/checks/active/xss_dom.rb +1 -1
- data/spec/support/servers/checks/active/xss_dom_inputs.rb +24 -0
- data/spec/support/servers/checks/active/xss_dom_script_context.rb +1 -1
- data/spec/support/servers/checks/passive/common_admin_interfaces.rb +6 -0
- data/spec/support/servers/plugins/autologin.rb +9 -0
- data/spec/support/servers/plugins/restrict_to_dom_state.rb +4 -0
- data/spec/support/shared/element/base.rb +42 -0
- data/spec/support/shared/element/capabilities/auditable.rb +4 -4
- data/spec/support/shared/element/capabilities/auditable/dom.rb +26 -0
- data/spec/support/shared/element/capabilities/inputtable.rb +16 -11
- data/spec/support/shared/element/capabilities/submitable.rb +7 -2
- data/spec/support/shared/fingerprinter.rb +8 -0
- data/spec/support/shared/path_extractor.rb +1 -1
- data/ui/cli/framework.rb +3 -3
- data/ui/cli/framework/option_parser.rb +9 -0
- data/ui/cli/output.rb +9 -0
- data/ui/cli/reporter.rb +5 -2
- data/ui/cli/utilities.rb +4 -2
- metadata +76 -17
- data/lib/arachni/http/proxy_server/ssl-interceptor-cert.pem +0 -34
- data/lib/arachni/http/proxy_server/ssl-interceptor-pkey.pem +0 -51
- data/spec/components/fingerprinters/languages/jsp_spec.rb +0 -56
|
@@ -12,18 +12,31 @@
|
|
|
12
12
|
class Arachni::Plugins::LoginScript < Arachni::Plugin::Base
|
|
13
13
|
|
|
14
14
|
STATUSES = {
|
|
15
|
-
success:
|
|
16
|
-
failure:
|
|
17
|
-
error:
|
|
18
|
-
|
|
15
|
+
success: 'Login was successful.',
|
|
16
|
+
failure: 'The script was executed successfully, but the login check failed.',
|
|
17
|
+
error: 'A runtime error was encountered while executing the login script.',
|
|
18
|
+
missing_browser: 'A browser is required for this operation but is not available.',
|
|
19
|
+
missing_check: 'No session check was provided, either via interface options or the script.'
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
def prepare
|
|
22
|
-
script
|
|
23
|
-
@script
|
|
23
|
+
script = IO.read( @options[:script] )
|
|
24
|
+
@script = proc do |browser|
|
|
25
|
+
if javascript?
|
|
26
|
+
browser.goto @framework.options.url
|
|
27
|
+
browser.execute_script script
|
|
28
|
+
else
|
|
29
|
+
eval script
|
|
30
|
+
end
|
|
31
|
+
end
|
|
24
32
|
end
|
|
25
33
|
|
|
26
34
|
def run
|
|
35
|
+
if javascript? && !session.has_browser?
|
|
36
|
+
set_status :missing_browser, :error
|
|
37
|
+
return
|
|
38
|
+
end
|
|
39
|
+
|
|
27
40
|
framework_pause
|
|
28
41
|
print_info 'System paused.'
|
|
29
42
|
|
|
@@ -71,6 +84,10 @@ class Arachni::Plugins::LoginScript < Arachni::Plugin::Base
|
|
|
71
84
|
framework_resume
|
|
72
85
|
end
|
|
73
86
|
|
|
87
|
+
def javascript?
|
|
88
|
+
@options[:script].split( '.' ).last == 'js'
|
|
89
|
+
end
|
|
90
|
+
|
|
74
91
|
def set_status( status, type = nil, extra = {} )
|
|
75
92
|
type ||= status
|
|
76
93
|
|
|
@@ -96,7 +113,9 @@ The script needn't necessarily perform an actual login operation. If another
|
|
|
96
113
|
process is used to manage sessions, the script can be used to communicate with
|
|
97
114
|
that process and, for example, load and set cookies from a shared cookie-jar.
|
|
98
115
|
|
|
99
|
-
|
|
116
|
+
# Ruby
|
|
117
|
+
|
|
118
|
+
## With browser (slow)
|
|
100
119
|
|
|
101
120
|
If a [browser](http://watirwebdriver.com/) is available, it will be exposed to
|
|
102
121
|
the script via the `browser` variable. Otherwise, that variable will have a
|
|
@@ -115,7 +134,7 @@ value of `nil`.
|
|
|
115
134
|
framework.options.session.check_url = browser.url
|
|
116
135
|
framework.options.session.check_pattern = /Sign Off|MY ACCOUNT/
|
|
117
136
|
|
|
118
|
-
|
|
137
|
+
## Without browser (fast)
|
|
119
138
|
|
|
120
139
|
If a real browser environment is not required for the login operation, then
|
|
121
140
|
using the system-wide HTTP interface is preferable, as it will be much faster
|
|
@@ -133,15 +152,26 @@ and consume much less resources.
|
|
|
133
152
|
framework.options.session.check_url = to_absolute( response.headers.location, response.url )
|
|
134
153
|
framework.options.session.check_pattern = /Sign Off|MY ACCOUNT/
|
|
135
154
|
|
|
136
|
-
|
|
155
|
+
## From cookie-jar
|
|
137
156
|
|
|
138
157
|
If an external process is used to manage sessions, you can keep Arachni in sync
|
|
139
158
|
by loading cookies from a shared Netscape-style cookie-jar file.
|
|
140
159
|
|
|
141
160
|
http.cookie_jar.load 'cookies.txt'
|
|
161
|
+
|
|
162
|
+
# Javascript
|
|
163
|
+
|
|
164
|
+
When the given script has a `.js` file extension, it will be loaded and executed
|
|
165
|
+
in the browser, within the page of the target URL.
|
|
166
|
+
|
|
167
|
+
document.getElementById( 'uid' ).value = 'jsmith';
|
|
168
|
+
document.getElementById( 'passw' ).value = 'Demo1234';
|
|
169
|
+
|
|
170
|
+
document.getElementById( 'login' ).submit();
|
|
171
|
+
|
|
142
172
|
},
|
|
143
173
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
|
|
144
|
-
version: '0.
|
|
174
|
+
version: '0.2',
|
|
145
175
|
options: [
|
|
146
176
|
Options::Path.new( :script,
|
|
147
177
|
required: true,
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2010-2015 Tasos Laskos <tasos.laskos@arachni-scanner.com>
|
|
3
|
+
|
|
4
|
+
This file is part of the Arachni Framework project and is subject to
|
|
5
|
+
redistribution and commercial restrictions. Please see the Arachni Framework
|
|
6
|
+
web site for more information on licensing and terms of use.
|
|
7
|
+
=end
|
|
8
|
+
|
|
9
|
+
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
|
10
|
+
# @version 0.1
|
|
11
|
+
class Arachni::Plugins::Metrics < Arachni::Plugin::Base
|
|
12
|
+
|
|
13
|
+
def prepare
|
|
14
|
+
@metrics = {
|
|
15
|
+
'general' => {
|
|
16
|
+
'egress_traffic' => 0,
|
|
17
|
+
# Approximation, may differ from the real value depending on
|
|
18
|
+
# compression and other factors.
|
|
19
|
+
'ingress_traffic' => 0,
|
|
20
|
+
'uses_http' => false,
|
|
21
|
+
'uses_https' => false
|
|
22
|
+
},
|
|
23
|
+
'scan' => {
|
|
24
|
+
'duration' => 0,
|
|
25
|
+
'authenticated' => false
|
|
26
|
+
},
|
|
27
|
+
'http' => {
|
|
28
|
+
'requests' => 0,
|
|
29
|
+
'response_time_min' => 0,
|
|
30
|
+
'response_time_max' => 0,
|
|
31
|
+
'response_time_average' => 0,
|
|
32
|
+
'request_size_min' => 0,
|
|
33
|
+
'request_size_max' => 0,
|
|
34
|
+
'request_size_average' => 0,
|
|
35
|
+
'response_size_min' => 0,
|
|
36
|
+
'response_size_max' => 0,
|
|
37
|
+
'response_size_average' => 0
|
|
38
|
+
},
|
|
39
|
+
'resource' => {
|
|
40
|
+
'binary' => Arachni::Support::LookUp::HashSet.new,
|
|
41
|
+
'without_parameters' => Arachni::Support::LookUp::HashSet.new,
|
|
42
|
+
'with_parameters' => Arachni::Support::LookUp::HashSet.new
|
|
43
|
+
},
|
|
44
|
+
'element' => {
|
|
45
|
+
'links' => 0,
|
|
46
|
+
'forms' => 0,
|
|
47
|
+
'cookies' => 0,
|
|
48
|
+
'jsons' => 0,
|
|
49
|
+
'xmls' => 0,
|
|
50
|
+
'headers' => 0,
|
|
51
|
+
'has_forms_with_nonces' => false,
|
|
52
|
+
'has_forms_with_passwords' => false,
|
|
53
|
+
'input_names_total' => 0,
|
|
54
|
+
'input_names_unique' => Arachni::Support::LookUp::HashSet.new
|
|
55
|
+
},
|
|
56
|
+
'dom' => {
|
|
57
|
+
'event_listeners' => Arachni::Support::LookUp::HashSet.new,
|
|
58
|
+
'swf_objects' => Arachni::Support::LookUp::HashSet.new
|
|
59
|
+
},
|
|
60
|
+
'platforms' => Arachni::Platform::Manager::TYPES.keys.
|
|
61
|
+
inject({}) { |h, t| h[t.to_s] = Set.new; h }
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def run
|
|
66
|
+
http_response_time_total = 0
|
|
67
|
+
|
|
68
|
+
http.on_complete do |response|
|
|
69
|
+
response.platforms.to_a.each do |platform|
|
|
70
|
+
@metrics['platforms'][Arachni::Platform::Manager.find_type( platform ).to_s] << platform.to_s
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
@metrics['general']['egress_traffic'] += response.request.to_s.size
|
|
74
|
+
@metrics['general']['ingress_traffic'] += response.to_s.size
|
|
75
|
+
|
|
76
|
+
if @metrics['http']['response_time_min'].is_a?( Integer ) ||
|
|
77
|
+
response.time < @metrics['http']['response_time_min']
|
|
78
|
+
|
|
79
|
+
@metrics['http']['response_time_min'] = response.time
|
|
80
|
+
end
|
|
81
|
+
if response.time > @metrics['http']['response_time_max']
|
|
82
|
+
@metrics['http']['response_time_max'] = response.time
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
response_size = response.to_s.size
|
|
86
|
+
if @metrics['http']['response_size_min'].is_a?( Integer ) ||
|
|
87
|
+
response_size < @metrics['http']['response_size_min']
|
|
88
|
+
|
|
89
|
+
@metrics['http']['response_size_min'] = response_size
|
|
90
|
+
end
|
|
91
|
+
if response_size > @metrics['http']['response_size_max']
|
|
92
|
+
@metrics['http']['response_size_max'] = response_size
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
request_size = response.request.to_s.size
|
|
96
|
+
if @metrics['http']['request_size_min'].is_a?( Integer ) ||
|
|
97
|
+
request_size < @metrics['http']['request_size_min']
|
|
98
|
+
|
|
99
|
+
@metrics['http']['request_size_min'] = request_size
|
|
100
|
+
end
|
|
101
|
+
if request_size > @metrics['http']['request_size_max']
|
|
102
|
+
@metrics['http']['request_size_max'] = request_size
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Only track OK codes, otherwise discovery checks will muck with the
|
|
106
|
+
# data.
|
|
107
|
+
if response.code == 200
|
|
108
|
+
if response.request.body.is_a?( Hash ) ||
|
|
109
|
+
response.request.parameters.any? ||
|
|
110
|
+
response.request.url.include?( '?' )
|
|
111
|
+
|
|
112
|
+
if response.request.body.is_a? Hash
|
|
113
|
+
body = response.request.body.keys.sort
|
|
114
|
+
else
|
|
115
|
+
body = nil
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
@metrics['resource']['with_parameters'] <<
|
|
119
|
+
"#{response.parsed_url.up_to_path}#{response.request.parameters.keys.sort}:#{body}"
|
|
120
|
+
else
|
|
121
|
+
@metrics['resource']['without_parameters'] << response.url
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
@metrics['general']['uses_http'] ||=
|
|
126
|
+
(response.parsed_url.scheme == 'http')
|
|
127
|
+
@metrics['general']['uses_https'] ||=
|
|
128
|
+
(response.parsed_url.scheme == 'https')
|
|
129
|
+
|
|
130
|
+
if !response.text?
|
|
131
|
+
@metrics['resource']['binary'] << response.url
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
http_response_time_total += response.time
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
framework.on_page_audit do |page|
|
|
138
|
+
%w(links forms cookies headers jsons xmls).each do |type|
|
|
139
|
+
page.send( type ).each do |e|
|
|
140
|
+
next if e.inputs.empty?
|
|
141
|
+
|
|
142
|
+
@metrics['element'][type] += 1
|
|
143
|
+
@metrics['element']['input_names_total'] += e.inputs.size
|
|
144
|
+
|
|
145
|
+
e.inputs.keys.each do |name|
|
|
146
|
+
@metrics['element']['input_names_unique'] << name
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
if e.is_a? Arachni::Element::Form
|
|
150
|
+
# Probably not a real form, just a request with inputs
|
|
151
|
+
# captured by the browsers and fed back to the system.
|
|
152
|
+
if !e.source
|
|
153
|
+
@metrics['element'][type] -= 1
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
@metrics['element']['has_forms_with_nonces'] ||= !!e.has_nonce?
|
|
157
|
+
@metrics['element']['has_forms_with_passwords'] ||= !!e.requires_password?
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
if (swf = find_swf( page ))
|
|
163
|
+
@metrics['dom']['swf_objects'] << swf
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
if Arachni::Options.scope.dom_depth_limit.to_i < page.dom.depth + 1 &&
|
|
167
|
+
browser_cluster && page.has_script?
|
|
168
|
+
|
|
169
|
+
with_browser do |browser|
|
|
170
|
+
browser.load( page ).each_element_with_events do |locator, event_data|
|
|
171
|
+
event_data.each do |data|
|
|
172
|
+
@metrics['dom']['event_listeners'] << "#{locator}:#{data}"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
wait_while_framework_running
|
|
180
|
+
|
|
181
|
+
@metrics = process( @metrics )
|
|
182
|
+
|
|
183
|
+
@metrics['http']['requests'] = framework.statistics[:http][:response_count]
|
|
184
|
+
|
|
185
|
+
@metrics['http']['response_time_average'] =
|
|
186
|
+
http_response_time_total / @metrics['http']['requests']
|
|
187
|
+
|
|
188
|
+
@metrics['http']['response_size_average'] =
|
|
189
|
+
@metrics['general']['ingress_traffic'] / @metrics['http']['requests']
|
|
190
|
+
|
|
191
|
+
@metrics['http']['request_size_average'] =
|
|
192
|
+
@metrics['general']['egress_traffic'] / @metrics['http']['requests']
|
|
193
|
+
|
|
194
|
+
@metrics['scan']['duration'] = framework.statistics[:runtime]
|
|
195
|
+
@metrics['scan']['authenticated'] = !!Arachni::Options.session.check_url
|
|
196
|
+
|
|
197
|
+
register_results @metrics
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def find_swf( page )
|
|
201
|
+
page.body.scan( /(?:data|src)=['"]?(.*)\.swf['"]?>/ )[0]
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def process( hash )
|
|
205
|
+
h = {}
|
|
206
|
+
hash.each do |k, v|
|
|
207
|
+
case v
|
|
208
|
+
when Hash
|
|
209
|
+
v = process( v )
|
|
210
|
+
|
|
211
|
+
when Set
|
|
212
|
+
v = v.to_a
|
|
213
|
+
|
|
214
|
+
when Arachni::Support::LookUp::HashSet
|
|
215
|
+
v = v.size
|
|
216
|
+
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
h[k] = v
|
|
220
|
+
end
|
|
221
|
+
h
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def self.info
|
|
225
|
+
{
|
|
226
|
+
name: 'Metrics',
|
|
227
|
+
description: %q{
|
|
228
|
+
Captures metrics about multiple aspects of the scan and the web application.
|
|
229
|
+
},
|
|
230
|
+
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
|
|
231
|
+
version: '0.1'
|
|
232
|
+
}
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
end
|
data/components/plugins/proxy.rb
CHANGED
|
@@ -60,7 +60,13 @@ class Arachni::Plugins::Proxy < Arachni::Plugin::Base
|
|
|
60
60
|
print_info "Control panel URL: #{url_for( :panel )}"
|
|
61
61
|
print_info "Shutdown URL: #{url_for( :shutdown )}"
|
|
62
62
|
print_info 'The scan will resume once you visit the shutdown URL.'
|
|
63
|
-
|
|
63
|
+
print_info
|
|
64
|
+
print_info 'When browsing HTTPS sites, please accept the Arachni SSL certificate' +
|
|
65
|
+
' or install the CA certificate manually from:'
|
|
66
|
+
print_info " #{Arachni::HTTP::ProxyServer::INTERCEPTOR_CA_CERTIFICATE}"
|
|
67
|
+
print_info
|
|
68
|
+
print_bad '**DO NOT** forget to revoke it after using the proxy, as it' +
|
|
69
|
+
' can be used by anyone to impersonate 3rd party servers.'
|
|
64
70
|
print_info
|
|
65
71
|
print_info '*' * 82
|
|
66
72
|
print_info '* You need to clear your browser\'s cookies for this site before using the proxy! *'
|
|
@@ -77,7 +83,12 @@ class Arachni::Plugins::Proxy < Arachni::Plugin::Base
|
|
|
77
83
|
end
|
|
78
84
|
|
|
79
85
|
def prepare_pages_for_inspection
|
|
80
|
-
@pages.select
|
|
86
|
+
(@pages.select do |p|
|
|
87
|
+
next if !p.text?
|
|
88
|
+
|
|
89
|
+
p.forms.any? || p.links.any? || p.cookies.any? || p.jsons.any? ||
|
|
90
|
+
p.xmls.any?
|
|
91
|
+
end).to_a
|
|
81
92
|
end
|
|
82
93
|
|
|
83
94
|
def vectors_yaml
|
|
@@ -86,12 +97,18 @@ class Arachni::Plugins::Proxy < Arachni::Plugin::Base
|
|
|
86
97
|
page.elements.each do |element|
|
|
87
98
|
next if element.inputs.empty?
|
|
88
99
|
|
|
89
|
-
|
|
100
|
+
data = {
|
|
90
101
|
type: element.type,
|
|
91
102
|
method: element.method,
|
|
92
103
|
action: element.action,
|
|
93
104
|
inputs: element.inputs
|
|
94
105
|
}
|
|
106
|
+
|
|
107
|
+
if element.respond_to? :source
|
|
108
|
+
data[:source] = element.source
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
vectors << data
|
|
95
112
|
end
|
|
96
113
|
end
|
|
97
114
|
vectors.to_yaml
|
|
@@ -476,7 +493,7 @@ a way to restrict usage enough to avoid users unwittingly interfering with each
|
|
|
476
493
|
others' sessions.
|
|
477
494
|
},
|
|
478
495
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
|
|
479
|
-
version: '0.3.
|
|
496
|
+
version: '0.3.3',
|
|
480
497
|
options: [
|
|
481
498
|
Options::Port.new( :port,
|
|
482
499
|
description: 'Port to bind to.',
|
|
@@ -7,9 +7,13 @@
|
|
|
7
7
|
<%= html_encode page.title %>
|
|
8
8
|
-
|
|
9
9
|
<%= page.forms.size %> forms,
|
|
10
|
-
<%= page.links.size %> links
|
|
11
|
-
<%= page.cookies.size %> cookies
|
|
10
|
+
<%= page.links.size %> links,
|
|
11
|
+
<%= page.cookies.size %> cookies,
|
|
12
|
+
<%= page.jsons.size %> JSONs and
|
|
13
|
+
<%= page.xmls.size %> XMLs.
|
|
14
|
+
|
|
12
15
|
<br/>
|
|
16
|
+
|
|
13
17
|
(<%= page.url %>)
|
|
14
18
|
</p>
|
|
15
19
|
</div>
|
|
@@ -60,6 +64,34 @@
|
|
|
60
64
|
<hr />
|
|
61
65
|
<% end %>
|
|
62
66
|
</div>
|
|
67
|
+
<div class="well links">
|
|
68
|
+
<h2>JSONs</h2>
|
|
69
|
+
<% page.jsons.each do |json| %>
|
|
70
|
+
<p>
|
|
71
|
+
<b>Action: <%= html_encode json.action %></b>
|
|
72
|
+
<ul>
|
|
73
|
+
<% json.inputs.each do |k, v| %>
|
|
74
|
+
<li><%= k.inspect %> = <%= v.inspect %></li>
|
|
75
|
+
<% end %>
|
|
76
|
+
</ul>
|
|
77
|
+
</p>
|
|
78
|
+
<hr />
|
|
79
|
+
<% end %>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="well links">
|
|
82
|
+
<h2>XMLs</h2>
|
|
83
|
+
<% page.xmls.each do |xml| %>
|
|
84
|
+
<p>
|
|
85
|
+
<b>Action: <%= html_encode xml.action %></b>
|
|
86
|
+
<ul>
|
|
87
|
+
<% xml.inputs.each do |k, v| %>
|
|
88
|
+
<li><%= k.inspect %> = <%= v.inspect %></li>
|
|
89
|
+
<% end %>
|
|
90
|
+
</ul>
|
|
91
|
+
</p>
|
|
92
|
+
<hr />
|
|
93
|
+
<% end %>
|
|
94
|
+
</div>
|
|
63
95
|
</div>
|
|
64
96
|
</div>
|
|
65
97
|
</div>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Copyright 2010-2015 Tasos Laskos <tasos.laskos@arachni-scanner.com>
|
|
3
|
+
|
|
4
|
+
This file is part of the Arachni Framework project and is subject to
|
|
5
|
+
redistribution and commercial restrictions. Please see the Arachni Framework
|
|
6
|
+
web site for more information on licensing and terms of use.
|
|
7
|
+
=end
|
|
8
|
+
|
|
9
|
+
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
|
10
|
+
# @version 0.1
|
|
11
|
+
class Arachni::Plugins::RestrictToDOMState < Arachni::Plugin::Base
|
|
12
|
+
|
|
13
|
+
def prepare
|
|
14
|
+
print_status 'Sending pause signal...'
|
|
15
|
+
@pause_id = framework.pause( false )
|
|
16
|
+
print_status '...done.'
|
|
17
|
+
|
|
18
|
+
# Disable any operations that can lead to a crawl, we only want the
|
|
19
|
+
# system to audit the page snapshot we give it.
|
|
20
|
+
framework.options.scope.do_not_crawl
|
|
21
|
+
|
|
22
|
+
@fragment = options[:fragment]
|
|
23
|
+
@url = "#{framework.options.url}##{@fragment}"
|
|
24
|
+
|
|
25
|
+
print_info "Full URL set to: #{@url}"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def run
|
|
29
|
+
print_status 'Initialising browser...'
|
|
30
|
+
browser = Arachni::Browser.new( store_pages: false )
|
|
31
|
+
print_status '...done.'
|
|
32
|
+
|
|
33
|
+
print_status 'Loading page...'
|
|
34
|
+
page = browser.load( @url ).to_page
|
|
35
|
+
print_info ' Transitions:'
|
|
36
|
+
page.dom.print_transitions( method(:print_info), ' ' )
|
|
37
|
+
|
|
38
|
+
framework.push_to_page_queue page, true
|
|
39
|
+
print_status 'Pushed to page queue.'
|
|
40
|
+
ensure
|
|
41
|
+
return if !browser
|
|
42
|
+
|
|
43
|
+
print_status 'Shutting down browser...'
|
|
44
|
+
browser.shutdown
|
|
45
|
+
print_status '...done.'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def clean_up
|
|
49
|
+
print_status 'Resuming scan...'
|
|
50
|
+
framework.resume @pause_id
|
|
51
|
+
print_status '...done.'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.info
|
|
55
|
+
{
|
|
56
|
+
name: 'Restrict to DOM state',
|
|
57
|
+
description: %q{Restricts the scan to a single page's DOM state.},
|
|
58
|
+
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
|
|
59
|
+
version: '0.1',
|
|
60
|
+
options: [
|
|
61
|
+
Options::String.new( :fragment,
|
|
62
|
+
required: true,
|
|
63
|
+
description: 'URL fragment for the desired state.'
|
|
64
|
+
)
|
|
65
|
+
],
|
|
66
|
+
priority: 0 # run before any other plugin
|
|
67
|
+
}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|