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
|
@@ -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 )
|