arachni 1.1 → 1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -60,6 +60,15 @@ module Analyzable
|
|
60
60
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
61
61
|
module Timeout
|
62
62
|
|
63
|
+
# Override user audit options that don't play nice with this technique.
|
64
|
+
TIMEOUT_OPTIONS = {
|
65
|
+
skip_original: true,
|
66
|
+
with_both_http_methods: false,
|
67
|
+
parameter_names: false,
|
68
|
+
with_extra_parameter: false,
|
69
|
+
extensively: false
|
70
|
+
}
|
71
|
+
|
63
72
|
class <<self
|
64
73
|
def reset
|
65
74
|
|
@@ -322,34 +331,24 @@ module Timeout
|
|
322
331
|
def timing_attack_probe( payloads, options, &block )
|
323
332
|
fail ArgumentError, 'Missing block' if !block_given?
|
324
333
|
|
325
|
-
options = options.
|
334
|
+
options = options.merge( TIMEOUT_OPTIONS )
|
326
335
|
options[:delay] = options.delete(:timeout)
|
327
336
|
options[:timeout_divider] ||= 1
|
328
337
|
options[:add] ||= 0
|
329
338
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
# Disable {Arachni::OptionGroups::Audit#cookies_extensively},
|
336
|
-
# there's little to be gained in this case and just causes interference.
|
337
|
-
extensively: false,
|
339
|
+
# Intercept each element mutation prior to it being submitted and
|
340
|
+
# replace the '__TIME__' stub with the actual delay value.
|
341
|
+
options[:each_mutation] = proc do |mutation|
|
342
|
+
injected = mutation.affected_input_value
|
338
343
|
|
339
|
-
#
|
340
|
-
#
|
341
|
-
|
342
|
-
injected = mutation.affected_input_value
|
344
|
+
# Preserve the placeholder (__TIME__) payload because it's going to
|
345
|
+
# be needed for the verification phases...
|
346
|
+
mutation.audit_options[:timing_string] = injected
|
343
347
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
# ...but update it to use a real payload for this audit.
|
349
|
-
mutation.affected_input_value = injected.
|
350
|
-
gsub( '__TIME__', payload_delay_from_options( options ) )
|
351
|
-
end
|
352
|
-
)
|
348
|
+
# ...but update it to use a real payload for this audit.
|
349
|
+
mutation.affected_input_value = injected.
|
350
|
+
gsub( '__TIME__', payload_delay_from_options( options ) )
|
351
|
+
end
|
353
352
|
|
354
353
|
# Ignore response bodies to preserve bandwidth since we don't care
|
355
354
|
# about them anyways.
|
@@ -441,7 +440,12 @@ module Timeout
|
|
441
440
|
e = super
|
442
441
|
return e if !@timing_attack_remark_data
|
443
442
|
|
444
|
-
|
443
|
+
dupped_remark_data = {}
|
444
|
+
@timing_attack_remark_data.each do |k, v|
|
445
|
+
dupped_remark_data[k] = v.dup
|
446
|
+
end
|
447
|
+
|
448
|
+
e.timing_attack_remark_data = dupped_remark_data
|
445
449
|
e
|
446
450
|
end
|
447
451
|
|
@@ -35,6 +35,20 @@ module DOM
|
|
35
35
|
# @!method with_browser( &block )
|
36
36
|
def_delegator :auditor, :with_browser
|
37
37
|
|
38
|
+
def self.included( parent )
|
39
|
+
parent.extend ClassMethods
|
40
|
+
end
|
41
|
+
|
42
|
+
module ClassMethods
|
43
|
+
def encode( string )
|
44
|
+
string
|
45
|
+
end
|
46
|
+
|
47
|
+
def decode( string )
|
48
|
+
string
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
38
52
|
def initialize( options )
|
39
53
|
options = options.dup
|
40
54
|
@parent = options.delete(:parent)
|
@@ -139,6 +153,14 @@ module DOM
|
|
139
153
|
options
|
140
154
|
end
|
141
155
|
|
156
|
+
def encode( string )
|
157
|
+
self.class.encode( string )
|
158
|
+
end
|
159
|
+
|
160
|
+
def decode( string )
|
161
|
+
self.class.decode( string )
|
162
|
+
end
|
163
|
+
|
142
164
|
private
|
143
165
|
|
144
166
|
def prepare_browser( browser, options )
|
@@ -37,6 +37,10 @@ module Capabilities::Inputtable
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
+
INPUTTABLE_CACHE = {
|
41
|
+
inputtable_id: Support::Cache::LeastRecentlyPushed.new( 1_000 )
|
42
|
+
}
|
43
|
+
|
40
44
|
# Frozen version of {#inputs}, has all the original names and values.
|
41
45
|
#
|
42
46
|
# @return [Hash]
|
@@ -223,7 +227,8 @@ module Capabilities::Inputtable
|
|
223
227
|
# @return [String]
|
224
228
|
# Uniquely identifies the {#inputs}.
|
225
229
|
def inputtable_id
|
226
|
-
inputs
|
230
|
+
INPUTTABLE_CACHE[:inputtable_id][@inputs] ||=
|
231
|
+
@inputs ? @inputs.sort_by { |k, _| k }.hash.to_s : ''
|
227
232
|
end
|
228
233
|
|
229
234
|
def to_h
|
@@ -255,7 +260,6 @@ module Capabilities::Inputtable
|
|
255
260
|
fail Error::InvalidData::Value,
|
256
261
|
"Invalid value for #{self.class}: #{value.inspect}"
|
257
262
|
end
|
258
|
-
|
259
263
|
end
|
260
264
|
|
261
265
|
def copy_inputtable( other )
|
@@ -26,6 +26,7 @@ class Cookie < Base
|
|
26
26
|
|
27
27
|
# Generic element capabilities.
|
28
28
|
include Arachni::Element::Capabilities::Analyzable
|
29
|
+
include Arachni::Element::Capabilities::WithSource
|
29
30
|
|
30
31
|
# Cookie-specific overrides.
|
31
32
|
include Capabilities::WithDOM
|
@@ -49,9 +50,6 @@ class Cookie < Base
|
|
49
50
|
httponly: false
|
50
51
|
}
|
51
52
|
|
52
|
-
ENCODE_CHARACTERS = ['+', ';', '%', "\0", "'", '&', '=', ' ', '"']
|
53
|
-
ENCODE_CHARACTERS_LIST = ENCODE_CHARACTERS.join
|
54
|
-
|
55
53
|
attr_reader :data
|
56
54
|
|
57
55
|
# @param [Hash] options
|
@@ -78,7 +76,7 @@ class Cookie < Base
|
|
78
76
|
end
|
79
77
|
|
80
78
|
@data.merge!( DEFAULT.merge( @data ) )
|
81
|
-
@data[:value] = decode( @data[:value].to_s )
|
79
|
+
@data[:value] = decode( @data[:value].to_s ) rescue @data[:value].to_s
|
82
80
|
|
83
81
|
parsed_uri = uri_parse( action )
|
84
82
|
if !@data[:path]
|
@@ -287,8 +285,8 @@ class Cookie < Base
|
|
287
285
|
# @see .from_document
|
288
286
|
# @see .from_headers
|
289
287
|
def from_response( response )
|
290
|
-
|
291
|
-
from_headers( response.url, response.headers )
|
288
|
+
from_document( response.url, response.body ) |
|
289
|
+
from_headers( response.url, response.headers )
|
292
290
|
end
|
293
291
|
|
294
292
|
# Extracts cookies from a document based on `Set-Cookie` `http-equiv`
|
@@ -302,21 +300,18 @@ class Cookie < Base
|
|
302
300
|
#
|
303
301
|
# @see .parse_set_cookie
|
304
302
|
def from_document( url, document )
|
305
|
-
# optimizations in case there are no cookies in the doc,
|
306
|
-
# avoid parsing unless absolutely necessary!
|
307
303
|
if !document.is_a?( Nokogiri::HTML::Document )
|
308
|
-
|
309
|
-
head = document.to_s.match( /<head(.*)<\/head>/imx )
|
304
|
+
document = document.to_s
|
310
305
|
|
311
|
-
|
312
|
-
return [] if !head || !head.to_s.downcase.include?( 'set-cookie' )
|
306
|
+
return [] if !(document =~ /set-cookie/i )
|
313
307
|
|
314
|
-
document = Nokogiri::HTML(
|
308
|
+
document = Nokogiri::HTML( document )
|
315
309
|
end
|
316
310
|
|
317
311
|
Arachni::Utilities.exception_jail {
|
318
|
-
document.search(
|
312
|
+
document.search( '//meta[@http-equiv]' ).map do |elem|
|
319
313
|
next if elem['http-equiv'].downcase != 'set-cookie'
|
314
|
+
|
320
315
|
from_set_cookie( url, elem['content'] )
|
321
316
|
end.flatten.compact
|
322
317
|
} rescue []
|
@@ -358,9 +353,14 @@ class Cookie < Base
|
|
358
353
|
|
359
354
|
cookie_hash['path'] ||= '/'
|
360
355
|
cookie_hash['name'] = decode( cookie.name )
|
361
|
-
cookie_hash['value'] = decode( cookie.value )
|
362
356
|
|
363
|
-
|
357
|
+
if too_big?( cookie.value )
|
358
|
+
cookie_hash['value'] = ''
|
359
|
+
else
|
360
|
+
cookie_hash['value'] = decode( cookie.value )
|
361
|
+
end
|
362
|
+
|
363
|
+
new( { url: url, source: str }.merge( cookie_hash.my_symbolize_keys ) )
|
364
364
|
end.flatten.compact
|
365
365
|
end
|
366
366
|
alias :parse_set_cookie :from_set_cookie
|
@@ -376,27 +376,41 @@ class Cookie < Base
|
|
376
376
|
# @return [Array<Cookie>]
|
377
377
|
def from_string( url, string )
|
378
378
|
return [] if string.empty?
|
379
|
+
|
379
380
|
string.split( ';' ).map do |cookie_pair|
|
381
|
+
cookie_pair.strip!
|
382
|
+
|
380
383
|
k, v = *cookie_pair.split( '=', 2 )
|
381
|
-
|
384
|
+
|
385
|
+
v = '' if too_big?( v )
|
386
|
+
|
387
|
+
new(
|
388
|
+
url: url,
|
389
|
+
source: cookie_pair,
|
390
|
+
inputs: { decode( k ) => value_to_v0( v ) }
|
391
|
+
)
|
382
392
|
end.flatten.compact
|
383
393
|
end
|
384
394
|
|
395
|
+
def value_to_v0( value )
|
396
|
+
return '' if !value
|
397
|
+
|
398
|
+
value.start_with?( '"' ) && value.end_with?( '"' ) ?
|
399
|
+
value[1...-1] : decode( value )
|
400
|
+
end
|
401
|
+
|
385
402
|
# Encodes a {String}'s reserved characters in order to prepare it for
|
386
403
|
# the `Cookie` header field.
|
387
404
|
#
|
388
405
|
# @example
|
389
406
|
# p Cookie.encode "+;%=\0 "
|
390
|
-
# #=> "%2B%3B%25%3D%00
|
407
|
+
# #=> "%2B%3B%25%3D%00%20"
|
391
408
|
#
|
392
409
|
# @param [String] str
|
393
410
|
#
|
394
411
|
# @return [String]
|
395
412
|
def encode( str )
|
396
|
-
str
|
397
|
-
return str if !ENCODE_CHARACTERS.find { |c| str.include? c }
|
398
|
-
|
399
|
-
::URI.encode( str, ENCODE_CHARACTERS_LIST )
|
413
|
+
Arachni::HTTP::Request.encode( str )
|
400
414
|
end
|
401
415
|
|
402
416
|
# Decodes a {String} encoded for the `Cookie` header field.
|
@@ -409,7 +423,7 @@ class Cookie < Base
|
|
409
423
|
#
|
410
424
|
# @return [String]
|
411
425
|
def decode( str )
|
412
|
-
::URI.
|
426
|
+
::URI.decode_www_form_component str.to_s
|
413
427
|
end
|
414
428
|
|
415
429
|
def keep_for_set_cookie
|
@@ -17,15 +17,15 @@ module Capabilities
|
|
17
17
|
module Mutable
|
18
18
|
include Arachni::Element::Capabilities::Mutable
|
19
19
|
|
20
|
-
# Overrides {Capabilities::Mutable#each_mutation} to handle cookie-specific
|
20
|
+
# Overrides {Arachni::Element::Capabilities::Mutable#each_mutation} to handle cookie-specific
|
21
21
|
# limitations and the {Arachni::OptionGroups::Audit#cookies_extensively} option.
|
22
22
|
#
|
23
|
-
# @param (see Capabilities::Mutable#each_mutation)
|
24
|
-
# @return (see Capabilities::Mutable#each_mutation)
|
25
|
-
# @yield (see Capabilities::Mutable#each_mutation)
|
26
|
-
# @yieldparam (see Capabilities::Mutable#each_mutation)
|
23
|
+
# @param (see Arachni::Element::Capabilities::Mutable#each_mutation)
|
24
|
+
# @return (see Arachni::Element::Capabilities::Mutable#each_mutation)
|
25
|
+
# @yield (see Arachni::Element::Capabilities::Mutable#each_mutation)
|
26
|
+
# @yieldparam (see Arachni::Element::Capabilities::Mutable#each_mutation)
|
27
27
|
#
|
28
|
-
# @see Capabilities::Mutable#each_mutation
|
28
|
+
# @see Arachni::Element::Capabilities::Mutable#each_mutation
|
29
29
|
def each_mutation( payload, options = {}, &block )
|
30
30
|
options = prepare_mutation_options( options )
|
31
31
|
parameter_names = options.delete( :parameter_names )
|
data/lib/arachni/element/form.rb
CHANGED
@@ -262,7 +262,14 @@ class Form < Base
|
|
262
262
|
#
|
263
263
|
# @return [Array<Form>]
|
264
264
|
def from_document( url, document, ignore_scope = false )
|
265
|
-
|
265
|
+
if !document.is_a?( Nokogiri::HTML::Document )
|
266
|
+
document = document.to_s
|
267
|
+
|
268
|
+
return [] if !(document =~ /<\s*form/i)
|
269
|
+
|
270
|
+
document = Nokogiri::HTML( document )
|
271
|
+
end
|
272
|
+
|
266
273
|
base_url = (document.search( '//base[@href]' )[0]['href'] rescue url)
|
267
274
|
base_url = to_absolute( base_url, url )
|
268
275
|
|
@@ -305,16 +312,20 @@ class Form < Base
|
|
305
312
|
|
306
313
|
# Handle the easy stuff first...
|
307
314
|
if elem.name != 'select'
|
308
|
-
options[:inputs][name]
|
315
|
+
options[:inputs][name] = elem_attrs
|
309
316
|
|
310
317
|
if elem_attrs[:type] == :submit
|
311
318
|
multiple_choice_submits[name] ||= Set.new
|
312
|
-
multiple_choice_submits[name] <<
|
313
|
-
elem_attrs[:value]
|
319
|
+
multiple_choice_submits[name] << elem_attrs[:value]
|
314
320
|
end
|
315
321
|
|
316
322
|
options[:inputs][name][:type] ||= :text
|
317
323
|
options[:inputs][name][:value] ||= ''
|
324
|
+
|
325
|
+
if too_big?( options[:inputs][name][:value] )
|
326
|
+
options[:inputs][name][:value] = ''
|
327
|
+
end
|
328
|
+
|
318
329
|
next
|
319
330
|
end
|
320
331
|
|
@@ -322,19 +333,22 @@ class Form < Base
|
|
322
333
|
if elem.children.css('option').any?
|
323
334
|
elem.children.css('option').each do |child|
|
324
335
|
h = attributes_to_hash( child.attributes )
|
325
|
-
h[:type]
|
336
|
+
h[:type] = :select
|
337
|
+
h[:value] ||= child.text
|
338
|
+
|
339
|
+
if too_big?( h[:value] )
|
340
|
+
h[:value] = ''
|
341
|
+
end
|
326
342
|
|
327
343
|
# Prefer the selected or first option.
|
328
344
|
if h[:selected]
|
329
|
-
h[:value] ||= child.text
|
330
345
|
options[:inputs][name] = h
|
331
346
|
else
|
332
|
-
h[:value] ||= child.text
|
333
347
|
options[:inputs][name] ||= h
|
334
348
|
end
|
335
349
|
end
|
336
350
|
|
337
|
-
|
351
|
+
# The select has no options, use an empty string.
|
338
352
|
else
|
339
353
|
options[:inputs][name] = {
|
340
354
|
type: :select,
|
@@ -376,20 +390,20 @@ class Form < Base
|
|
376
390
|
# Encodes a {String}'s reserved characters in order to prepare it
|
377
391
|
# to be included in a request body.
|
378
392
|
#
|
379
|
-
# @param [String]
|
393
|
+
# @param [String] string
|
380
394
|
#
|
381
395
|
# @return [String]
|
382
|
-
def encode(
|
383
|
-
::
|
396
|
+
def encode( string )
|
397
|
+
Arachni::HTTP::Request.encode string
|
384
398
|
end
|
385
399
|
|
386
400
|
# Decodes a {String} encoded for an HTTP request's body.
|
387
401
|
#
|
388
|
-
# @param [String]
|
402
|
+
# @param [String] string
|
389
403
|
#
|
390
404
|
# @return [String]
|
391
|
-
def decode(
|
392
|
-
::URI.decode_www_form_component
|
405
|
+
def decode( string )
|
406
|
+
::URI.decode_www_form_component string.to_s
|
393
407
|
end
|
394
408
|
|
395
409
|
end
|
@@ -33,8 +33,8 @@ module Auditable
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
# @param (see Capabilities::Auditable#audit_id)
|
37
|
-
# @return (see Capabilities::Auditable#audit_id)
|
36
|
+
# @param (see Arachni::Element::Capabilities::Auditable#audit_id)
|
37
|
+
# @return (see Arachni::Element::Capabilities::Auditable#audit_id)
|
38
38
|
def audit_id( payload = nil )
|
39
39
|
force_train? ? id : super( payload )
|
40
40
|
end
|
@@ -56,12 +56,12 @@ module Mutable
|
|
56
56
|
# Whether or not to skip adding a mutation holding original values and
|
57
57
|
# sample values.
|
58
58
|
#
|
59
|
-
# @param (see Capabilities::Mutable#each_mutation)
|
60
|
-
# @return (see Capabilities::Mutable#each_mutation)
|
61
|
-
# @yield (see Capabilities::Mutable#each_mutation)
|
62
|
-
# @yieldparam (see Capabilities::Mutable#each_mutation)
|
59
|
+
# @param (see Arachni::Element::Capabilities::Mutable#each_mutation)
|
60
|
+
# @return (see Arachni::Element::Capabilities::Mutable#each_mutation)
|
61
|
+
# @yield (see Arachni::Element::Capabilities::Mutable#each_mutation)
|
62
|
+
# @yieldparam (see Arachni::Element::Capabilities::Mutable#each_mutation)
|
63
63
|
#
|
64
|
-
# @see Capabilities::Mutable#each_mutation
|
64
|
+
# @see Arachni::Element::Capabilities::Mutable#each_mutation
|
65
65
|
# @see Arachni::OptionGroups::Input.fill
|
66
66
|
def each_mutation( payload, opts = {} )
|
67
67
|
opts = MUTATION_OPTIONS.merge( opts )
|