arachni 1.2.1 → 1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -0
- data/Gemfile +1 -1
- data/README.md +16 -5
- data/components/checks/active/ldap_injection/errors.txt +1 -0
- data/components/checks/active/source_code_disclosure.rb +1 -1
- data/components/checks/active/unvalidated_redirect.rb +6 -6
- data/components/checks/active/unvalidated_redirect_dom.rb +10 -7
- data/components/checks/passive/grep/captcha.rb +14 -5
- data/components/checks/passive/grep/form_upload.rb +7 -3
- data/components/checks/passive/grep/hsts.rb +3 -3
- data/components/checks/passive/grep/html_objects.rb +2 -3
- data/components/checks/passive/grep/http_only_cookies.rb +2 -3
- data/components/checks/passive/grep/insecure_cookies.rb +1 -1
- data/components/checks/passive/grep/password_autocomplete.rb +2 -2
- data/components/checks/passive/grep/unencrypted_password_forms.rb +7 -7
- data/components/checks/passive/grep/x_frame_options.rb +2 -2
- data/components/checks/passive/http_put.rb +2 -3
- data/components/path_extractors/comments.rb +3 -3
- data/components/path_extractors/scripts.rb +10 -1
- data/components/plugins/defaults/autothrottle.rb +27 -18
- data/components/plugins/defaults/meta/remedies/discovery.rb +30 -33
- data/components/plugins/defaults/meta/remedies/timing_attacks.rb +7 -11
- data/components/plugins/login_script.rb +9 -3
- data/components/plugins/proxy.rb +4 -3
- data/components/reporters/html.rb +11 -14
- data/components/reporters/html/default/issue.erb +13 -38
- data/components/reporters/html/default/issue/info.erb +1 -1
- data/components/reporters/html/default/summary/issues/by_name.erb +3 -3
- data/components/reporters/stdout.rb +62 -71
- data/components/reporters/xml.rb +26 -40
- data/components/reporters/xml/schema.xsd +43 -89
- data/lib/arachni/browser.rb +52 -3
- data/lib/arachni/browser/javascript.rb +3 -3
- data/lib/arachni/browser/javascript/scripts/taint_tracer.js +46 -25
- data/lib/arachni/browser_cluster.rb +61 -0
- data/lib/arachni/browser_cluster/job.rb +21 -1
- data/lib/arachni/browser_cluster/jobs/browser_provider.rb +3 -1
- data/lib/arachni/browser_cluster/jobs/resource_exploration.rb +2 -1
- data/lib/arachni/browser_cluster/jobs/resource_exploration/event_trigger.rb +2 -1
- data/lib/arachni/browser_cluster/jobs/taint_trace.rb +3 -2
- data/lib/arachni/browser_cluster/jobs/taint_trace/event_trigger.rb +1 -1
- data/lib/arachni/browser_cluster/worker.rb +5 -0
- data/lib/arachni/check/auditor.rb +22 -12
- data/lib/arachni/data/framework.rb +13 -1
- data/lib/arachni/data/issues.rb +9 -25
- data/lib/arachni/element/base.rb +9 -3
- data/lib/arachni/element/capabilities/analyzable.rb +2 -6
- data/lib/arachni/element/capabilities/analyzable/differential.rb +24 -7
- data/lib/arachni/element/capabilities/analyzable/{taint.rb → signature.rb} +23 -23
- data/lib/arachni/element/capabilities/auditable.rb +0 -6
- data/lib/arachni/element/capabilities/dom_only.rb +61 -0
- data/lib/arachni/element/capabilities/with_dom.rb +3 -1
- data/lib/arachni/element/cookie.rb +35 -5
- data/lib/arachni/element/cookie/dom.rb +13 -4
- data/lib/arachni/element/{capabilities/auditable/dom.rb → dom.rb} +20 -68
- data/lib/arachni/element/dom/capabilities/auditable.rb +29 -0
- data/lib/arachni/element/dom/capabilities/inputtable.rb +27 -0
- data/lib/arachni/element/dom/capabilities/mutable.rb +21 -0
- data/lib/arachni/element/dom/capabilities/submittable.rb +52 -0
- data/lib/arachni/element/form.rb +12 -1
- data/lib/arachni/element/form/capabilities/mutable.rb +2 -1
- data/lib/arachni/element/form/capabilities/with_dom.rb +0 -1
- data/lib/arachni/element/form/dom.rb +9 -3
- data/lib/arachni/element/header.rb +14 -33
- data/lib/arachni/element/header/capabilities/inputtable.rb +29 -0
- data/lib/arachni/element/header/capabilities/mutable.rb +51 -0
- data/lib/arachni/element/input/dom.rb +71 -0
- data/lib/arachni/element/json.rb +2 -0
- data/lib/arachni/element/link.rb +3 -0
- data/lib/arachni/element/link/capabilities/with_dom.rb +0 -1
- data/lib/arachni/element/link/dom.rb +16 -3
- data/lib/arachni/element/link/dom/capabilities/submittable.rb +29 -0
- data/lib/arachni/element/link_template.rb +3 -5
- data/lib/arachni/element/link_template/capabilities/inputtable.rb +5 -0
- data/lib/arachni/element/link_template/capabilities/with_dom.rb +0 -1
- data/lib/arachni/element/link_template/dom.rb +16 -3
- data/lib/arachni/element/link_template/dom/capabilities/submittable.rb +29 -0
- data/lib/arachni/element/server.rb +3 -5
- data/lib/arachni/element/ui_form.rb +106 -0
- data/lib/arachni/element/ui_form/dom.rb +107 -0
- data/lib/arachni/element/ui_input.rb +62 -0
- data/lib/arachni/element/xml.rb +2 -1
- data/lib/arachni/framework.rb +7 -5
- data/lib/arachni/framework/parts/audit.rb +0 -1
- data/lib/arachni/framework/parts/check.rb +1 -0
- data/lib/arachni/framework/parts/data.rb +4 -0
- data/lib/arachni/framework/parts/state.rb +0 -2
- data/lib/arachni/http/client.rb +17 -6
- data/lib/arachni/http/proxy_server.rb +52 -5
- data/lib/arachni/http/request.rb +1 -1
- data/lib/arachni/issue.rb +34 -179
- data/lib/arachni/issue/severity.rb +2 -0
- data/lib/arachni/option_groups/audit.rb +22 -2
- data/lib/arachni/option_groups/browser_cluster.rb +15 -0
- data/lib/arachni/page.rb +3 -2
- data/lib/arachni/parser.rb +24 -5
- data/lib/arachni/platform/manager.rb +1 -2
- data/lib/arachni/rpc/server/framework.rb +3 -4
- data/lib/arachni/rpc/server/framework/multi_instance.rb +2 -1
- data/lib/arachni/session.rb +1 -1
- data/lib/arachni/trainer.rb +4 -7
- data/lib/arachni/watir/element.rb +12 -1
- data/lib/version +1 -1
- data/spec/arachni/browser/element_locator_spec.rb +43 -43
- data/spec/arachni/browser/javascript/dom_monitor_spec.rb +44 -44
- data/spec/arachni/browser/javascript/proxy/stub_spec.rb +17 -14
- data/spec/arachni/browser/javascript/proxy_spec.rb +24 -24
- data/spec/arachni/browser/javascript/taint_tracer/frame/called_function_spec.rb +11 -11
- data/spec/arachni/browser/javascript/taint_tracer/frame_spec.rb +7 -7
- data/spec/arachni/browser/javascript/taint_tracer/sink/data_flow_spec.rb +13 -13
- data/spec/arachni/browser/javascript/taint_tracer/sink/execution_flow_spec.rb +7 -7
- data/spec/arachni/browser/javascript/taint_tracer_spec.rb +568 -558
- data/spec/arachni/browser/javascript_spec.rb +73 -63
- data/spec/arachni/browser_cluster/job/result_spec.rb +3 -3
- data/spec/arachni/browser_cluster/job_spec.rb +68 -48
- data/spec/arachni/browser_cluster/jobs/resource_exploration/event_trigger/result_spec.rb +2 -2
- data/spec/arachni/browser_cluster/jobs/resource_exploration/event_trigger_spec.rb +5 -4
- data/spec/arachni/browser_cluster/jobs/resource_exploration/result_spec.rb +2 -2
- data/spec/arachni/browser_cluster/jobs/resource_exploration_spec.rb +5 -5
- data/spec/arachni/browser_cluster/worker_spec.rb +87 -70
- data/spec/arachni/browser_cluster_spec.rb +64 -39
- data/spec/arachni/browser_spec.rb +692 -527
- data/spec/arachni/check/auditor_spec.rb +177 -147
- data/spec/arachni/check/base_spec.rb +33 -33
- data/spec/arachni/check/manager_spec.rb +15 -15
- data/spec/arachni/component/base_spec.rb +8 -8
- data/spec/arachni/component/manager_spec.rb +100 -99
- data/spec/arachni/component/options/address_spec.rb +3 -3
- data/spec/arachni/component/options/base_spec.rb +7 -7
- data/spec/arachni/component/options/bool_spec.rb +9 -9
- data/spec/arachni/component/options/float_spec.rb +6 -6
- data/spec/arachni/component/options/int_spec.rb +5 -5
- data/spec/arachni/component/options/multiple_choice_spec.rb +12 -12
- data/spec/arachni/component/options/object_spec.rb +2 -2
- data/spec/arachni/component/options/path_spec.rb +3 -3
- data/spec/arachni/component/options/port_spec.rb +5 -5
- data/spec/arachni/component/options/string_spec.rb +3 -3
- data/spec/arachni/component/options/url_spec.rb +4 -4
- data/spec/arachni/component/utilities_spec.rb +2 -2
- data/spec/arachni/data/framework/rpc_spec.rb +10 -9
- data/spec/arachni/data/framework_spec.rb +65 -46
- data/spec/arachni/data/issues_spec.rb +39 -77
- data/spec/arachni/data/plugins_spec.rb +11 -11
- data/spec/arachni/data/session_spec.rb +6 -6
- data/spec/arachni/data_spec.rb +8 -8
- data/spec/arachni/element/body_spec.rb +10 -10
- data/spec/arachni/element/capabilities/analyzable/differential_spec.rb +39 -21
- data/spec/arachni/element/capabilities/analyzable/{taint_spec.rb → signature_spec.rb} +63 -63
- data/spec/arachni/element/capabilities/analyzable/timeout_spec.rb +51 -51
- data/spec/arachni/element/capabilities/with_scope/scope_spec.rb +5 -5
- data/spec/arachni/element/cookie/dom_spec.rb +37 -18
- data/spec/arachni/element/cookie_spec.rb +206 -139
- data/spec/arachni/element/form/dom_spec.rb +36 -19
- data/spec/arachni/element/form_spec.rb +210 -187
- data/spec/arachni/element/generic_dom_spec.rb +14 -14
- data/spec/arachni/element/header_spec.rb +35 -17
- data/spec/arachni/element/json_spec.rb +53 -31
- data/spec/arachni/element/link/dom_spec.rb +46 -28
- data/spec/arachni/element/link_spec.rb +58 -40
- data/spec/arachni/element/link_template/dom_spec.rb +47 -29
- data/spec/arachni/element/link_template_spec.rb +79 -61
- data/spec/arachni/element/path_spec.rb +1 -1
- data/spec/arachni/element/server_spec.rb +33 -32
- data/spec/arachni/element/ui_form/ui_form_dom_spec.rb +164 -0
- data/spec/arachni/element/ui_form_spec.rb +242 -0
- data/spec/arachni/element/ui_input/dom_spec.rb +157 -0
- data/spec/arachni/element/ui_input_spec.rb +136 -0
- data/spec/arachni/element/xml_spec.rb +42 -24
- data/spec/arachni/element_filter_spec.rb +49 -48
- data/spec/arachni/error_spec.rb +3 -3
- data/spec/arachni/framework/parts/audit_spec.rb +64 -63
- data/spec/arachni/framework/parts/browser_spec.rb +16 -16
- data/spec/arachni/framework/parts/check_spec.rb +3 -3
- data/spec/arachni/framework/parts/data_spec.rb +48 -48
- data/spec/arachni/framework/parts/platform_spec.rb +3 -3
- data/spec/arachni/framework/parts/plugin_spec.rb +7 -6
- data/spec/arachni/framework/parts/report_spec.rb +7 -7
- data/spec/arachni/framework/parts/scope_spec.rb +16 -16
- data/spec/arachni/framework/parts/state_spec.rb +68 -69
- data/spec/arachni/framework_spec.rb +39 -31
- data/spec/arachni/http/client/dynamic_404_handlers_spec.rb +32 -32
- data/spec/arachni/http/client_spec.rb +219 -208
- data/spec/arachni/http/cookie_jar_spec.rb +72 -72
- data/spec/arachni/http/headers_spec.rb +14 -14
- data/spec/arachni/http/proxy_server_spec.rb +43 -42
- data/spec/arachni/http/request_spec.rb +105 -103
- data/spec/arachni/http/response/scope_spec.rb +24 -24
- data/spec/arachni/http/response_spec.rb +50 -49
- data/spec/arachni/issue/severity_spec.rb +10 -9
- data/spec/arachni/issue_spec.rb +71 -369
- data/spec/arachni/option_groups/audit_spec.rb +114 -114
- data/spec/arachni/option_groups/browser_cluster_spec.rb +20 -3
- data/spec/arachni/option_groups/datastore_spec.rb +6 -6
- data/spec/arachni/option_groups/dispatcher_spec.rb +19 -19
- data/spec/arachni/option_groups/http_spec.rb +11 -11
- data/spec/arachni/option_groups/input_spec.rb +31 -27
- data/spec/arachni/option_groups/output_spec.rb +2 -2
- data/spec/arachni/option_groups/paths_spec.rb +17 -17
- data/spec/arachni/option_groups/rpc_spec.rb +2 -2
- data/spec/arachni/option_groups/scope_spec.rb +40 -40
- data/spec/arachni/option_groups/session_spec.rb +6 -5
- data/spec/arachni/option_groups/snapshot_spec.rb +4 -4
- data/spec/arachni/options_spec.rb +46 -45
- data/spec/arachni/page/dom/transition_spec.rb +74 -72
- data/spec/arachni/page/dom_spec.rb +35 -35
- data/spec/arachni/page/scope_spec.rb +15 -15
- data/spec/arachni/page_spec.rb +217 -217
- data/spec/arachni/parser_spec.rb +106 -104
- data/spec/arachni/platform/fingerprinter_spec.rb +17 -14
- data/spec/arachni/platform/list_spec.rb +33 -33
- data/spec/arachni/platform/manager_spec.rb +67 -64
- data/spec/arachni/plugin/base_spec.rb +10 -10
- data/spec/arachni/plugin/manager_spec.rb +38 -37
- data/spec/arachni/report_spec.rb +43 -40
- data/spec/arachni/reporter/base_spec.rb +15 -15
- data/spec/arachni/reporter/manager_spec.rb +4 -4
- data/spec/arachni/reporter/options_spec.rb +6 -6
- data/spec/arachni/rpc/client/base_spec.rb +6 -6
- data/spec/arachni/rpc/client/dispatcher_spec.rb +2 -2
- data/spec/arachni/rpc/client/instance_spec.rb +6 -6
- data/spec/arachni/rpc/server/active_options_spec.rb +11 -8
- data/spec/arachni/rpc/server/base_spec.rb +5 -5
- data/spec/arachni/rpc/server/checks/manager_spec.rb +8 -8
- data/spec/arachni/rpc/server/dispatcher/node_spec.rb +37 -37
- data/spec/arachni/rpc/server/dispatcher/service_spec.rb +15 -14
- data/spec/arachni/rpc/server/dispatcher_spec.rb +36 -35
- data/spec/arachni/rpc/server/framework/distributor_spec.rb +36 -36
- data/spec/arachni/rpc/server/framework_multi_spec.rb +340 -336
- data/spec/arachni/rpc/server/framework_spec.rb +90 -85
- data/spec/arachni/rpc/server/instance_spec.rb +126 -107
- data/spec/arachni/rpc/server/output_spec.rb +1 -1
- data/spec/arachni/rpc/server/plugin/manager_spec.rb +6 -6
- data/spec/arachni/ruby/array_spec.rb +42 -42
- data/spec/arachni/ruby/hash_spec.rb +20 -18
- data/spec/arachni/ruby/io_spec.rb +2 -2
- data/spec/arachni/ruby/object_spec.rb +1 -1
- data/spec/arachni/ruby/set_spec.rb +3 -3
- data/spec/arachni/ruby/string_spec.rb +30 -30
- data/spec/arachni/ruby/webrick_spec.rb +2 -2
- data/spec/arachni/scope_spec.rb +1 -1
- data/spec/arachni/session_spec.rb +67 -64
- data/spec/arachni/snapshot_spec.rb +15 -15
- data/spec/arachni/state/audit_spec.rb +11 -11
- data/spec/arachni/state/element_filter_spec.rb +6 -6
- data/spec/arachni/state/framework/rpc_spec.rb +12 -12
- data/spec/arachni/state/framework_spec.rb +125 -121
- data/spec/arachni/state/http_spec.rb +7 -7
- data/spec/arachni/state/options_spec.rb +7 -7
- data/spec/arachni/state/plugins_spec.rb +8 -8
- data/spec/arachni/state_spec.rb +10 -10
- data/spec/arachni/support/buffer/autoflush_spec.rb +16 -16
- data/spec/arachni/support/buffer/base_spec.rb +39 -39
- data/spec/arachni/support/cache/least_cost_replacement_spec.rb +18 -18
- data/spec/arachni/support/cache/least_recently_pushed_spec.rb +24 -24
- data/spec/arachni/support/cache/least_recently_used_spec.rb +20 -20
- data/spec/arachni/support/cache/preference_spec.rb +4 -4
- data/spec/arachni/support/cache/random_replacement_spec.rb +8 -8
- data/spec/arachni/support/crypto/rsa_aes_cbc_spec.rb +1 -1
- data/spec/arachni/support/database/hash_spec.rb +44 -43
- data/spec/arachni/support/database/queue_spec.rb +27 -27
- data/spec/arachni/support/lookup/hash_set_spec.rb +8 -8
- data/spec/arachni/support/lookup/moolb_spec.rb +3 -3
- data/spec/arachni/support/mixins/observable_spec.rb +6 -6
- data/spec/arachni/support/signature_spec.rb +19 -19
- data/spec/arachni/trainer_spec.rb +39 -39
- data/spec/arachni/typhoeus/hydra_spec.rb +2 -2
- data/spec/arachni/uri/scope_spec.rb +66 -66
- data/spec/arachni/uri_spec.rb +107 -105
- data/spec/arachni/utilities_spec.rb +40 -40
- data/spec/components/checks/active/csrf_spec.rb +8 -8
- data/spec/components/checks/active/no_sql_injection_spec.rb +1 -1
- data/spec/components/checks/active/sql_injection_spec.rb +16 -16
- data/spec/components/checks/active/trainer_spec.rb +4 -4
- data/spec/components/checks/active/unvalidated_redirect_dom_spec.rb +4 -2
- data/spec/components/checks/active/xpath_injection_spec.rb +1 -1
- data/spec/components/checks/active/xss_dom_script_context_spec.rb +51 -21
- data/spec/components/checks/active/xss_dom_spec.rb +46 -24
- data/spec/components/checks/passive/allowed_methods_spec.rb +1 -1
- data/spec/components/checks/passive/grep/cookie_set_for_parent_domain_spec.rb +1 -1
- data/spec/components/checks/passive/grep/hsts_spec.rb +2 -2
- data/spec/components/checks/passive/grep/http_only_cookies_spec.rb +1 -1
- data/spec/components/checks/passive/grep/insecure_cookies_spec.rb +1 -1
- data/spec/components/checks/passive/grep/insecure_cors_policy_spec.rb +2 -2
- data/spec/components/checks/passive/grep/password_autocomplete_spec.rb +1 -1
- data/spec/components/checks/passive/grep/private_ip_spec.rb +3 -3
- data/spec/components/checks/passive/grep/unencrypted_password_forms_spec.rb +1 -1
- data/spec/components/checks/passive/grep/x_frame_options_spec.rb +2 -2
- data/spec/components/checks/passive/interesting_responses_spec.rb +2 -2
- data/spec/components/checks/passive/webdav_spec.rb +1 -1
- data/spec/components/checks/passive/xst_spec.rb +1 -1
- data/spec/components/fingerprinters/servers/apache_spec.rb +2 -2
- data/spec/components/path_extractors/comments_spec.rb +5 -1
- data/spec/components/path_extractors/scripts_spec.rb +5 -2
- data/spec/components/plugins/autologin_spec.rb +22 -22
- data/spec/components/plugins/autothrottle_spec.rb +6 -5
- data/spec/components/plugins/content_types_spec.rb +4 -4
- data/spec/components/plugins/cookie_collector_spec.rb +5 -5
- data/spec/components/plugins/exec_spec.rb +12 -12
- data/spec/components/plugins/form_dicattack_spec.rb +3 -3
- data/spec/components/plugins/headers_collector_spec.rb +8 -8
- data/spec/components/plugins/healthmap_spec.rb +3 -3
- data/spec/components/plugins/http_dicattack_spec.rb +3 -3
- data/spec/components/plugins/login_script_spec.rb +79 -22
- data/spec/components/plugins/meta/remedies/discovery_spec.rb +3 -2
- data/spec/components/plugins/meta/remedies/timing_attacks_spec.rb +3 -3
- data/spec/components/plugins/meta/uniformity_spec.rb +2 -2
- data/spec/components/plugins/restrict_to_dom_state_spec.rb +1 -1
- data/spec/components/plugins/script_spec.rb +1 -1
- data/spec/components/plugins/uncommon_headers_spec.rb +2 -2
- data/spec/components/plugins/vector_collector_spec.rb +2 -2
- data/spec/components/plugins/vector_feed_spec.rb +40 -40
- data/spec/components/plugins/waf_detector_spec.rb +6 -6
- data/spec/components/reporters/json_spec.rb +4 -4
- data/spec/components/reporters/marshal_spec.rb +2 -2
- data/spec/components/reporters/yaml_spec.rb +3 -2
- data/spec/external/wavsep/active/sqli_spec.rb +1 -3
- data/spec/spec_helper.rb +4 -0
- data/spec/support/factories/element/ui_form.rb +14 -0
- data/spec/support/factories/element/ui_input.rb +13 -0
- data/spec/support/factories/issue.rb +0 -13
- data/spec/support/fixtures/report.afr +0 -0
- data/spec/support/fixtures/{taint_check/taint.rb → signature_check/signature.rb} +2 -2
- data/spec/support/helpers/browser_cluster/jobs/taint_tracer.rb +11 -11
- data/spec/support/helpers/framework.rb +1 -1
- data/spec/support/helpers/pages.rb +2 -2
- data/spec/support/servers/arachni/browser.rb +139 -0
- data/spec/support/servers/arachni/browser/javascript/taint_tracer.rb +40 -0
- data/spec/support/servers/arachni/element/capabilities/analyzable/{taint.rb → signature.rb} +0 -0
- data/spec/support/servers/arachni/element/input/input_dom.rb +102 -0
- data/spec/support/servers/arachni/element/ui_form/ui_form_dom.rb +238 -0
- data/spec/support/servers/checks/active/trainer_check.rb +7 -7
- data/spec/support/servers/checks/active/unvalidated_redirect_dom.rb +22 -6
- data/spec/support/servers/checks/active/xss_dom.rb +50 -0
- data/spec/support/servers/checks/active/xss_dom_script_context.rb +53 -0
- data/spec/support/shared/browser/javascript/taint_tracer/sink/base.rb +6 -6
- data/spec/support/shared/check.rb +10 -12
- data/spec/support/shared/component/options/base.rb +24 -24
- data/spec/support/shared/element/base.rb +25 -25
- data/spec/support/shared/element/capabilities/auditable.rb +116 -140
- data/spec/support/shared/element/capabilities/dom_only.rb +65 -0
- data/spec/support/shared/element/capabilities/inputtable.rb +71 -86
- data/spec/support/shared/element/capabilities/mutable.rb +122 -111
- data/spec/support/shared/element/capabilities/refreshable.rb +10 -10
- data/spec/support/shared/element/capabilities/{submitable.rb → submittable.rb} +26 -26
- data/spec/support/shared/element/capabilities/with_auditor.rb +10 -10
- data/spec/support/shared/element/capabilities/with_dom.rb +8 -8
- data/spec/support/shared/element/capabilities/with_node.rb +4 -6
- data/spec/support/shared/element/capabilities/with_scope.rb +2 -2
- data/spec/support/shared/element/capabilities/with_source.rb +6 -8
- data/spec/support/shared/element/dom.rb +144 -0
- data/spec/support/shared/element/dom/auditable.rb +42 -0
- data/spec/support/shared/element/dom/inputtable.rb +5 -0
- data/spec/support/shared/element/dom/mutable.rb +3 -0
- data/spec/support/shared/element/dom/submittable.rb +119 -0
- data/spec/support/shared/external/wavsep.rb +3 -3
- data/spec/support/shared/fingerprinter.rb +2 -2
- data/spec/support/shared/framework.rb +1 -1
- data/spec/support/shared/http/message.rb +9 -9
- data/spec/support/shared/option_group.rb +17 -17
- data/spec/support/shared/path_extractor.rb +1 -1
- data/spec/support/shared/plugin.rb +2 -2
- data/spec/support/shared/support/cache.rb +57 -57
- data/spec/support/shared/support/lookup.rb +25 -25
- data/ui/cli/framework.rb +22 -11
- data/ui/cli/framework/option_parser.rb +15 -0
- data/ui/cli/option_parser.rb +8 -1
- data/ui/cli/output.rb +2 -1
- metadata +54 -20
- data/components/checks/active/xss_dom_inputs.rb +0 -236
- data/spec/components/checks/active/xss_dom_inputs_spec.rb +0 -30
- data/spec/support/servers/checks/active/xss_dom_inputs.rb +0 -59
- data/spec/support/shared/element/capabilities/auditable/dom.rb +0 -322
@@ -1,12 +1,26 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Arachni::Element::Form::DOM do
|
4
|
-
|
4
|
+
inputs = { 'param' => '1' }
|
5
|
+
|
6
|
+
it_should_behave_like 'element_dom'
|
7
|
+
|
8
|
+
it_should_behave_like 'with_node'
|
9
|
+
it_should_behave_like 'with_auditor'
|
10
|
+
|
11
|
+
it_should_behave_like 'submittable_dom'
|
12
|
+
it_should_behave_like 'inputtable_dom', inputs: inputs
|
13
|
+
it_should_behave_like 'mutable_dom', inputs: inputs
|
14
|
+
it_should_behave_like 'auditable_dom'
|
5
15
|
|
6
16
|
def auditable_extract_parameters( page )
|
7
17
|
YAML.load( page.document.css( 'body' ).text )
|
8
18
|
end
|
9
19
|
|
20
|
+
def run
|
21
|
+
auditor.browser_cluster.wait
|
22
|
+
end
|
23
|
+
|
10
24
|
before :each do
|
11
25
|
@framework = Arachni::Framework.new
|
12
26
|
@page = Arachni::Page.from_url( "#{url}/form" )
|
@@ -33,25 +47,25 @@ describe Arachni::Element::Form::DOM do
|
|
33
47
|
|
34
48
|
describe '#type' do
|
35
49
|
it 'returns :form_dom' do
|
36
|
-
subject.type.
|
50
|
+
expect(subject.type).to eq(:form_dom)
|
37
51
|
end
|
38
52
|
end
|
39
53
|
|
40
54
|
describe '.type' do
|
41
55
|
it 'returns :form_dom' do
|
42
|
-
described_class.type.
|
56
|
+
expect(described_class.type).to eq(:form_dom)
|
43
57
|
end
|
44
58
|
end
|
45
59
|
|
46
60
|
describe '#parent' do
|
47
61
|
it 'returns the parent element' do
|
48
|
-
subject.parent.
|
62
|
+
expect(subject.parent).to be_kind_of Arachni::Element::Form
|
49
63
|
end
|
50
64
|
end
|
51
65
|
|
52
66
|
describe '#inputs' do
|
53
67
|
it 'uses the parent\'s inputs' do
|
54
|
-
subject.inputs.
|
68
|
+
expect(subject.inputs).to eq(parent.inputs)
|
55
69
|
end
|
56
70
|
end
|
57
71
|
|
@@ -63,17 +77,17 @@ describe Arachni::Element::Form::DOM do
|
|
63
77
|
browser.load subject.page
|
64
78
|
|
65
79
|
element = subject.locate
|
66
|
-
element.
|
80
|
+
expect(element).to be_kind_of Watir::HTMLElement
|
67
81
|
|
68
|
-
parent.class.from_document(
|
82
|
+
expect(parent.class.from_document(
|
69
83
|
parent.url, Nokogiri::HTML(element.html)
|
70
|
-
).first.
|
84
|
+
).first).to eq(parent)
|
71
85
|
|
72
86
|
called = true
|
73
87
|
end
|
74
88
|
|
75
89
|
subject.auditor.browser_cluster.wait
|
76
|
-
called.
|
90
|
+
expect(called).to be_truthy
|
77
91
|
end
|
78
92
|
end
|
79
93
|
|
@@ -91,46 +105,49 @@ describe Arachni::Element::Form::DOM do
|
|
91
105
|
|
92
106
|
page = browser.to_page
|
93
107
|
|
94
|
-
subject.inputs.
|
108
|
+
expect(subject.inputs).to eq(auditable_extract_parameters( page ))
|
95
109
|
called = true
|
96
110
|
end
|
97
111
|
|
98
112
|
subject.auditor.browser_cluster.wait
|
99
|
-
called.
|
113
|
+
expect(called).to be_truthy
|
100
114
|
end
|
101
115
|
|
102
116
|
it 'returns a playable transition' do
|
103
117
|
inputs = { 'param' => 'The.Dude' }
|
104
118
|
subject.update inputs
|
105
119
|
|
106
|
-
|
120
|
+
transitions = []
|
107
121
|
called = false
|
108
122
|
subject.with_browser do |browser|
|
109
123
|
subject.browser = browser
|
110
124
|
browser.load subject.page
|
111
125
|
|
112
|
-
|
126
|
+
transitions = subject.trigger
|
113
127
|
|
114
128
|
page = browser.to_page
|
115
129
|
|
116
|
-
subject.inputs.
|
130
|
+
expect(subject.inputs).to eq(auditable_extract_parameters( page ))
|
117
131
|
called = true
|
118
132
|
end
|
119
133
|
|
120
134
|
subject.auditor.browser_cluster.wait
|
121
|
-
called.
|
135
|
+
expect(called).to be_truthy
|
122
136
|
|
123
137
|
called = false
|
124
138
|
auditor.with_browser do |browser|
|
125
139
|
browser.load subject.page
|
126
|
-
auditable_extract_parameters( browser.to_page ).
|
140
|
+
expect(auditable_extract_parameters( browser.to_page )).to be_falsey
|
141
|
+
|
142
|
+
transitions.each do |transition|
|
143
|
+
transition.play browser
|
144
|
+
end
|
127
145
|
|
128
|
-
|
129
|
-
auditable_extract_parameters( browser.to_page ).should == inputs
|
146
|
+
expect(auditable_extract_parameters( browser.to_page )).to eq(inputs)
|
130
147
|
called = true
|
131
148
|
end
|
132
149
|
auditor.browser_cluster.wait
|
133
|
-
called.
|
150
|
+
expect(called).to be_truthy
|
134
151
|
end
|
135
152
|
end
|
136
153
|
|
@@ -7,11 +7,29 @@ describe Arachni::Element::Form do
|
|
7
7
|
</form>'
|
8
8
|
|
9
9
|
it_should_behave_like 'element'
|
10
|
-
it_should_behave_like 'with_node'
|
10
|
+
it_should_behave_like 'with_node'
|
11
11
|
it_should_behave_like 'with_dom', html
|
12
12
|
it_should_behave_like 'refreshable'
|
13
|
+
it_should_behave_like 'with_source'
|
14
|
+
it_should_behave_like 'with_auditor'
|
15
|
+
|
16
|
+
it_should_behave_like 'submittable'
|
17
|
+
it_should_behave_like 'inputtable'
|
18
|
+
it_should_behave_like 'mutable'
|
13
19
|
it_should_behave_like 'auditable'
|
14
20
|
|
21
|
+
before :each do
|
22
|
+
@framework ||= Arachni::Framework.new
|
23
|
+
@auditor = Auditor.new( Arachni::Page.from_url( url ), @framework )
|
24
|
+
end
|
25
|
+
|
26
|
+
after :each do
|
27
|
+
@framework.reset
|
28
|
+
reset_options
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:auditor) { @auditor }
|
32
|
+
|
15
33
|
def auditable_extract_parameters( resource )
|
16
34
|
YAML.load( resource.body )
|
17
35
|
end
|
@@ -39,29 +57,29 @@ describe Arachni::Element::Form do
|
|
39
57
|
end
|
40
58
|
|
41
59
|
it 'assigned to Arachni::Form for easy access' do
|
42
|
-
Arachni::Form.
|
60
|
+
expect(Arachni::Form).to eq(described_class)
|
43
61
|
end
|
44
62
|
|
45
63
|
describe '#initialize' do
|
46
64
|
describe :method do
|
47
65
|
it 'defaults to :get' do
|
48
|
-
described_class.new( url: url ).method.
|
66
|
+
expect(described_class.new( url: url ).method).to eq(:get)
|
49
67
|
end
|
50
68
|
end
|
51
69
|
describe :name do
|
52
70
|
it 'sets #name' do
|
53
|
-
described_class.new( url: url, name: 'john' ).name.
|
71
|
+
expect(described_class.new( url: url, name: 'john' ).name).to eq('john')
|
54
72
|
end
|
55
73
|
end
|
56
74
|
describe :action do
|
57
75
|
it 'sets #action' do
|
58
76
|
action = "#{url}stuff"
|
59
|
-
described_class.new( url: url, action: action ).action.
|
77
|
+
expect(described_class.new( url: url, action: action ).action).to eq(action)
|
60
78
|
end
|
61
79
|
|
62
80
|
context 'when nil' do
|
63
81
|
it 'defaults to :url' do
|
64
|
-
described_class.new( url: url ).action.
|
82
|
+
expect(described_class.new( url: url ).action).to eq(url)
|
65
83
|
end
|
66
84
|
end
|
67
85
|
end
|
@@ -69,26 +87,26 @@ describe Arachni::Element::Form do
|
|
69
87
|
|
70
88
|
describe '#mutation_with_original_values?' do
|
71
89
|
it 'returns false' do
|
72
|
-
subject.mutation_with_original_values
|
90
|
+
expect(subject.mutation_with_original_values?).to be_falsey
|
73
91
|
end
|
74
92
|
|
75
93
|
context 'when #mutation_with_original_values' do
|
76
94
|
it 'returns true' do
|
77
95
|
subject.mutation_with_original_values
|
78
|
-
subject.mutation_with_original_values
|
96
|
+
expect(subject.mutation_with_original_values?).to be_truthy
|
79
97
|
end
|
80
98
|
end
|
81
99
|
end
|
82
100
|
|
83
101
|
describe '#mutation_with_sample_values?' do
|
84
102
|
it 'returns false' do
|
85
|
-
subject.mutation_with_sample_values
|
103
|
+
expect(subject.mutation_with_sample_values?).to be_falsey
|
86
104
|
end
|
87
105
|
|
88
106
|
context 'when #mutation_with_sample_values' do
|
89
107
|
it 'returns true' do
|
90
108
|
subject.mutation_with_sample_values
|
91
|
-
subject.mutation_with_sample_values
|
109
|
+
expect(subject.mutation_with_sample_values?).to be_truthy
|
92
110
|
end
|
93
111
|
end
|
94
112
|
end
|
@@ -97,7 +115,7 @@ describe Arachni::Element::Form do
|
|
97
115
|
context 'when #force_train?' do
|
98
116
|
it 'returns #mutation_id' do
|
99
117
|
subject.mutation_with_original_values
|
100
|
-
subject.audit_id( 'stuff' ).
|
118
|
+
expect(subject.audit_id( 'stuff' )).to eq(subject.id)
|
101
119
|
end
|
102
120
|
end
|
103
121
|
end
|
@@ -114,7 +132,7 @@ describe Arachni::Element::Form do
|
|
114
132
|
subject.audit( 'stuff', each_mutation: each_mutation ) {}
|
115
133
|
subject.http.run
|
116
134
|
|
117
|
-
had_mutation_with_original_values.
|
135
|
+
expect(had_mutation_with_original_values).to be_falsey
|
118
136
|
end
|
119
137
|
|
120
138
|
it 'ignores mutation_with_sample_values' do
|
@@ -127,7 +145,7 @@ describe Arachni::Element::Form do
|
|
127
145
|
subject.audit( 'stuff', each_mutation: each_mutation ) {}
|
128
146
|
subject.http.run
|
129
147
|
|
130
|
-
had_mutation_with_sample_values.
|
148
|
+
expect(had_mutation_with_sample_values).to be_falsey
|
131
149
|
end
|
132
150
|
end
|
133
151
|
end
|
@@ -135,8 +153,8 @@ describe Arachni::Element::Form do
|
|
135
153
|
describe '#name_or_id' do
|
136
154
|
context 'when a #name is available' do
|
137
155
|
it 'returns it' do
|
138
|
-
described_class.new( url: url, name: 'john' ).
|
139
|
-
name_or_id.
|
156
|
+
expect(described_class.new( url: url, name: 'john' ).
|
157
|
+
name_or_id).to eq('john')
|
140
158
|
end
|
141
159
|
end
|
142
160
|
|
@@ -144,8 +162,8 @@ describe Arachni::Element::Form do
|
|
144
162
|
subject { described_class.new( url: url, id: 'john' ) }
|
145
163
|
|
146
164
|
it 'returns the configured :id' do
|
147
|
-
subject.name.
|
148
|
-
subject.name_or_id.
|
165
|
+
expect(subject.name).to be_nil
|
166
|
+
expect(subject.name_or_id).to eq('john')
|
149
167
|
end
|
150
168
|
end
|
151
169
|
|
@@ -153,7 +171,7 @@ describe Arachni::Element::Form do
|
|
153
171
|
subject { described_class.new( url: url ) }
|
154
172
|
|
155
173
|
it 'returns nil' do
|
156
|
-
subject.name_or_id.
|
174
|
+
expect(subject.name_or_id).to be_nil
|
157
175
|
end
|
158
176
|
end
|
159
177
|
end
|
@@ -162,33 +180,33 @@ describe Arachni::Element::Form do
|
|
162
180
|
context 'when there are no #inputs' do
|
163
181
|
it 'returns nil' do
|
164
182
|
subject.inputs = {}
|
165
|
-
subject.dom.
|
183
|
+
expect(subject.dom).to be_nil
|
166
184
|
end
|
167
185
|
end
|
168
186
|
|
169
187
|
context 'when there is no #node' do
|
170
188
|
it 'returns nil' do
|
171
189
|
subject.source = nil
|
172
|
-
subject.dom.
|
190
|
+
expect(subject.dom).to be_nil
|
173
191
|
end
|
174
192
|
end
|
175
193
|
end
|
176
194
|
|
177
195
|
describe '#force_train?' do
|
178
196
|
it 'returns false' do
|
179
|
-
subject.force_train
|
197
|
+
expect(subject.force_train?).to be_falsey
|
180
198
|
end
|
181
199
|
|
182
200
|
context 'when #mutation_with_original_values?' do
|
183
201
|
it 'returns true' do
|
184
202
|
subject.mutation_with_original_values
|
185
|
-
subject.force_train
|
203
|
+
expect(subject.force_train?).to be_truthy
|
186
204
|
end
|
187
205
|
end
|
188
206
|
context 'when #mutation_with_sample_values?' do
|
189
207
|
it 'returns true' do
|
190
208
|
subject.mutation_with_sample_values
|
191
|
-
subject.force_train
|
209
|
+
expect(subject.force_train?).to be_truthy
|
192
210
|
end
|
193
211
|
end
|
194
212
|
end
|
@@ -221,11 +239,11 @@ describe Arachni::Element::Form do
|
|
221
239
|
let(:method) { :get }
|
222
240
|
|
223
241
|
it 'removes the URL query' do
|
224
|
-
subject.action.
|
242
|
+
expect(subject.action).to eq(url)
|
225
243
|
end
|
226
244
|
|
227
245
|
it 'merges the URL query parameters with the given :inputs' do
|
228
|
-
subject.inputs.
|
246
|
+
expect(subject.inputs).to eq(query_inputs.merge( option_inputs ))
|
229
247
|
end
|
230
248
|
|
231
249
|
context 'when URL query parameters and :inputs have the same name' do
|
@@ -237,7 +255,7 @@ describe Arachni::Element::Form do
|
|
237
255
|
end
|
238
256
|
|
239
257
|
it 'it gives precedence to the :inputs' do
|
240
|
-
subject.inputs.
|
258
|
+
expect(subject.inputs).to eq(query_inputs.merge( option_inputs ))
|
241
259
|
end
|
242
260
|
end
|
243
261
|
end
|
@@ -246,11 +264,11 @@ describe Arachni::Element::Form do
|
|
246
264
|
let(:method) { :post }
|
247
265
|
|
248
266
|
it 'preserves the URL query' do
|
249
|
-
subject.action.
|
267
|
+
expect(subject.action).to eq(action)
|
250
268
|
end
|
251
269
|
|
252
270
|
it 'ignores the URL query parameters' do
|
253
|
-
subject.inputs.
|
271
|
+
expect(subject.inputs).to eq(option_inputs)
|
254
272
|
end
|
255
273
|
end
|
256
274
|
end
|
@@ -270,13 +288,14 @@ describe Arachni::Element::Form do
|
|
270
288
|
}
|
271
289
|
}
|
272
290
|
|
273
|
-
described_class.new( options ).details_for( :password ).
|
291
|
+
expect(described_class.new( options ).details_for( :password )).to eq(
|
274
292
|
options[:inputs]['password']
|
293
|
+
)
|
275
294
|
end
|
276
295
|
end
|
277
296
|
describe 'when no data is available' do
|
278
297
|
it 'return nil' do
|
279
|
-
described_class.new( options ).details_for( :username ).
|
298
|
+
expect(described_class.new( options ).details_for( :username )).to eq({})
|
280
299
|
end
|
281
300
|
end
|
282
301
|
end
|
@@ -284,12 +303,12 @@ describe Arachni::Element::Form do
|
|
284
303
|
describe '#name' do
|
285
304
|
context 'when there is a form name' do
|
286
305
|
it 'returns it' do
|
287
|
-
described_class.new( options ).name.
|
306
|
+
expect(described_class.new( options ).name).to eq(options[:name])
|
288
307
|
end
|
289
308
|
end
|
290
309
|
describe 'when no data is available' do
|
291
310
|
it 'return nil' do
|
292
|
-
described_class.new( url: options[:url] ).name.
|
311
|
+
expect(described_class.new( url: options[:url] ).name).to be_nil
|
293
312
|
end
|
294
313
|
end
|
295
314
|
end
|
@@ -314,8 +333,8 @@ describe Arachni::Element::Form do
|
|
314
333
|
}
|
315
334
|
|
316
335
|
e = described_class.new( options )
|
317
|
-
e.field_type_for( 'password' ).
|
318
|
-
e.field_type_for( 'hidden_field' ).
|
336
|
+
expect(e.field_type_for( 'password' )).to eq(:password)
|
337
|
+
expect(e.field_type_for( 'hidden_field' )).to eq(:hidden)
|
319
338
|
end
|
320
339
|
end
|
321
340
|
|
@@ -333,8 +352,8 @@ describe Arachni::Element::Form do
|
|
333
352
|
</body>
|
334
353
|
</html>'
|
335
354
|
|
336
|
-
described_class.from_document( url, html ).
|
337
|
-
first.requires_password
|
355
|
+
expect(described_class.from_document( url, html ).
|
356
|
+
first.requires_password?).to be_truthy
|
338
357
|
end
|
339
358
|
end
|
340
359
|
context 'when the form does not have a password field' do
|
@@ -349,8 +368,8 @@ describe Arachni::Element::Form do
|
|
349
368
|
</body>
|
350
369
|
</html>'
|
351
370
|
|
352
|
-
described_class.from_document( url, html ).
|
353
|
-
first.requires_password
|
371
|
+
expect(described_class.from_document( url, html ).
|
372
|
+
first.requires_password?).to be_falsey
|
354
373
|
end
|
355
374
|
end
|
356
375
|
end
|
@@ -370,16 +389,16 @@ describe Arachni::Element::Form do
|
|
370
389
|
has_sample ||= false
|
371
390
|
|
372
391
|
e.mutations( 'seed' ).each do |m|
|
373
|
-
m.url.
|
374
|
-
m.action.
|
392
|
+
expect(m.url).to eq(e.url)
|
393
|
+
expect(m.action).to eq(e.action)
|
375
394
|
|
376
395
|
if m.mutation_with_original_values?
|
377
|
-
m.inputs.
|
396
|
+
expect(m.inputs).to eq(e.inputs)
|
378
397
|
has_original ||= true
|
379
398
|
end
|
380
399
|
end
|
381
400
|
|
382
|
-
has_original.
|
401
|
+
expect(has_original).to be_truthy
|
383
402
|
end
|
384
403
|
end
|
385
404
|
end
|
@@ -399,17 +418,17 @@ describe Arachni::Element::Form do
|
|
399
418
|
has_sample ||= false
|
400
419
|
|
401
420
|
e.mutations( 'seed' ).each do |m|
|
402
|
-
m.url.
|
403
|
-
m.action.
|
421
|
+
expect(m.url).to eq(e.url)
|
422
|
+
expect(m.action).to eq(e.action)
|
404
423
|
|
405
424
|
if m.mutation_with_sample_values?
|
406
|
-
m.affected_input_name.
|
407
|
-
m.inputs.
|
425
|
+
expect(m.affected_input_name).to eq(described_class::SAMPLE_VALUES)
|
426
|
+
expect(m.inputs).to eq(Arachni::Options.input.fill( e.inputs ))
|
408
427
|
has_sample ||= true
|
409
428
|
end
|
410
429
|
end
|
411
430
|
|
412
|
-
has_sample.
|
431
|
+
expect(has_sample).to be_truthy
|
413
432
|
end
|
414
433
|
end
|
415
434
|
end
|
@@ -427,14 +446,14 @@ describe Arachni::Element::Form do
|
|
427
446
|
e.mutations( 'seed' ).each do |m|
|
428
447
|
next if m.mutation_with_original_values? || m.mutation_with_sample_values?
|
429
448
|
|
430
|
-
m.url.
|
431
|
-
m.action.
|
449
|
+
expect(m.url).to eq(e.url)
|
450
|
+
expect(m.action).to eq(e.action)
|
432
451
|
|
433
|
-
m.inputs.
|
452
|
+
expect(m.inputs).not_to eq(e.inputs)
|
434
453
|
checked = true
|
435
454
|
end
|
436
455
|
|
437
|
-
checked.
|
456
|
+
expect(checked).to be_truthy
|
438
457
|
end
|
439
458
|
|
440
459
|
it 'sets #affected_input_name to the name of the fuzzed input' do
|
@@ -448,16 +467,16 @@ describe Arachni::Element::Form do
|
|
448
467
|
e.mutations( 'seed' ).each do |m|
|
449
468
|
next if m.mutation_with_original_values? || m.mutation_with_sample_values?
|
450
469
|
|
451
|
-
m.url.
|
452
|
-
m.action.
|
470
|
+
expect(m.url).to eq(e.url)
|
471
|
+
expect(m.action).to eq(e.action)
|
453
472
|
|
454
|
-
m.affected_input_name.
|
455
|
-
m.inputs[m.affected_input_name].
|
473
|
+
expect(m.affected_input_name).not_to eq(e.affected_input_name)
|
474
|
+
expect(m.inputs[m.affected_input_name]).to include 'seed'
|
456
475
|
|
457
476
|
checked = true
|
458
477
|
end
|
459
478
|
|
460
|
-
checked.
|
479
|
+
expect(checked).to be_truthy
|
461
480
|
end
|
462
481
|
|
463
482
|
context 'when it contains more than 1 password field' do
|
@@ -471,9 +490,9 @@ describe Arachni::Element::Form do
|
|
471
490
|
|
472
491
|
e = described_class.from_document( 'http://test.com', form ).first
|
473
492
|
|
474
|
-
e.mutations( 'seed' ).select do |m|
|
493
|
+
expect(e.mutations( 'seed' ).select do |m|
|
475
494
|
m.inputs['my_pass'] == m.inputs['my_pass_validation']
|
476
|
-
end.
|
495
|
+
end).to be_any
|
477
496
|
end
|
478
497
|
end
|
479
498
|
|
@@ -506,10 +525,10 @@ describe Arachni::Element::Form do
|
|
506
525
|
numbers = mutations.map { |f| f['numbers'] }
|
507
526
|
|
508
527
|
include = %w(volvo Saab mercedes audi)
|
509
|
-
(manufacturers & include).
|
528
|
+
expect(manufacturers & include).to eq(include)
|
510
529
|
|
511
530
|
include = %w(33 22)
|
512
|
-
(numbers & include).
|
531
|
+
expect(numbers & include).to eq(include)
|
513
532
|
end
|
514
533
|
end
|
515
534
|
|
@@ -517,7 +536,7 @@ describe Arachni::Element::Form do
|
|
517
536
|
it 'does not add mutations with original nor default values' do
|
518
537
|
e = described_class.new( options )
|
519
538
|
mutations = e.mutations( @seed, skip_original: true )
|
520
|
-
mutations.select { |m| m.mutation? }.size.
|
539
|
+
expect(mutations.select { |m| m.mutation? }.size).to eq(10)
|
521
540
|
end
|
522
541
|
end
|
523
542
|
end
|
@@ -526,7 +545,7 @@ describe Arachni::Element::Form do
|
|
526
545
|
it 'sets the name of the input holding the nonce' do
|
527
546
|
f = described_class.new( url: url, inputs: { nonce: 'value' } )
|
528
547
|
f.nonce_name = 'nonce'
|
529
|
-
f.nonce_name.
|
548
|
+
expect(f.nonce_name).to eq('nonce')
|
530
549
|
end
|
531
550
|
|
532
551
|
context 'when there is no input called nonce_name' do
|
@@ -548,13 +567,13 @@ describe Arachni::Element::Form do
|
|
548
567
|
it 'returns true' do
|
549
568
|
f = described_class.new( url: url, inputs: { nonce: 'value' } )
|
550
569
|
f.nonce_name = 'nonce'
|
551
|
-
f.has_nonce
|
570
|
+
expect(f.has_nonce?).to be_truthy
|
552
571
|
end
|
553
572
|
end
|
554
573
|
context 'when the form does not have a nonce' do
|
555
574
|
it 'returns false' do
|
556
575
|
f = described_class.new( url: url, inputs: { nonce: 'value' } )
|
557
|
-
f.has_nonce
|
576
|
+
expect(f.has_nonce?).to be_falsey
|
558
577
|
end
|
559
578
|
end
|
560
579
|
end
|
@@ -573,7 +592,7 @@ describe Arachni::Element::Form do
|
|
573
592
|
|
574
593
|
f.submit { |res| body = res.body }
|
575
594
|
http.run
|
576
|
-
body_should.
|
595
|
+
expect(body_should).to eq(body)
|
577
596
|
end
|
578
597
|
end
|
579
598
|
context 'when method is get' do
|
@@ -589,7 +608,7 @@ describe Arachni::Element::Form do
|
|
589
608
|
|
590
609
|
f.submit.on_complete { |res| body = res.body }
|
591
610
|
http.run
|
592
|
-
body_should.
|
611
|
+
expect(body_should).to eq(body)
|
593
612
|
end
|
594
613
|
end
|
595
614
|
context 'when the form has a nonce' do
|
@@ -612,20 +631,20 @@ describe Arachni::Element::Form do
|
|
612
631
|
|
613
632
|
subject.submit { |res| body = res.body }
|
614
633
|
http.run
|
615
|
-
body.
|
616
|
-
body.to_i.
|
634
|
+
expect(body).not_to eq(subject.default_inputs['nonce'])
|
635
|
+
expect(body.to_i).to be > 0
|
617
636
|
end
|
618
637
|
|
619
638
|
context 'and it could not refresh it' do
|
620
639
|
it 'submits it anyway' do
|
621
640
|
body = nil
|
622
641
|
|
623
|
-
subject.
|
642
|
+
allow(subject).to receive(:refresh) { nil }
|
624
643
|
subject.submit { |res| body = res.body }
|
625
644
|
http.run
|
626
645
|
|
627
|
-
body.
|
628
|
-
body.to_i.
|
646
|
+
expect(body).not_to eq(subject.default_inputs['nonce'])
|
647
|
+
expect(body.to_i).to be > 0
|
629
648
|
end
|
630
649
|
end
|
631
650
|
end
|
@@ -635,7 +654,7 @@ describe Arachni::Element::Form do
|
|
635
654
|
it 'returns a simplified version of the form attributes and inputs as a Hash' do
|
636
655
|
f = described_class.new( options )
|
637
656
|
f.update 'user' => 'blah'
|
638
|
-
f.simple.
|
657
|
+
expect(f.simple).to eq({
|
639
658
|
url: options[:url],
|
640
659
|
action: options[:url],
|
641
660
|
name: 'login-form',
|
@@ -645,20 +664,20 @@ describe Arachni::Element::Form do
|
|
645
664
|
'password' => 's3cr3t'
|
646
665
|
},
|
647
666
|
source: html
|
648
|
-
}
|
667
|
+
})
|
649
668
|
end
|
650
669
|
end
|
651
670
|
|
652
671
|
describe '#type' do
|
653
672
|
it 'is "form"' do
|
654
|
-
described_class.new( options ).type.
|
673
|
+
expect(described_class.new( options ).type).to eq(:form)
|
655
674
|
end
|
656
675
|
end
|
657
676
|
|
658
677
|
describe '.from_document' do
|
659
678
|
context 'when the response does not contain any forms' do
|
660
679
|
it 'returns an empty array' do
|
661
|
-
described_class.from_document( '', '' ).
|
680
|
+
expect(described_class.from_document( '', '' )).to be_empty
|
662
681
|
end
|
663
682
|
end
|
664
683
|
|
@@ -682,8 +701,8 @@ EOHTML
|
|
682
701
|
Arachni::Options.scope.exclude_path_patterns = [/exclude/]
|
683
702
|
|
684
703
|
forms = described_class.from_document( url, form_html )
|
685
|
-
forms.size.
|
686
|
-
forms.first.action.
|
704
|
+
expect(forms.size).to eq(1)
|
705
|
+
expect(forms.first.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
687
706
|
end
|
688
707
|
|
689
708
|
context 'when ignore_scope is set' do
|
@@ -691,7 +710,7 @@ EOHTML
|
|
691
710
|
Arachni::Options.scope.exclude_path_patterns = [/exclude/]
|
692
711
|
|
693
712
|
forms = described_class.from_document( url, form_html, true )
|
694
|
-
forms.size.
|
713
|
+
expect(forms.size).to eq(2)
|
695
714
|
end
|
696
715
|
end
|
697
716
|
end
|
@@ -711,16 +730,16 @@ EOHTML
|
|
711
730
|
</html>'
|
712
731
|
|
713
732
|
form = described_class.from_document( url, html ).first
|
714
|
-
form.action.
|
715
|
-
form.name.
|
716
|
-
form.url.
|
717
|
-
form.method.
|
718
|
-
form.inputs.
|
733
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
734
|
+
expect(form.name).to eq('my_form')
|
735
|
+
expect(form.url).to eq(url)
|
736
|
+
expect(form.method).to eq(:get)
|
737
|
+
expect(form.inputs).to eq({
|
719
738
|
'my_first_input' => 'my_first_value',
|
720
739
|
'my_second_input' => 'my_second_value'
|
721
|
-
}
|
740
|
+
})
|
722
741
|
form.inputs.keys.each do |input|
|
723
|
-
form.field_type_for( input ).
|
742
|
+
expect(form.field_type_for( input )).to eq(:text)
|
724
743
|
end
|
725
744
|
end
|
726
745
|
end
|
@@ -739,16 +758,16 @@ EOHTML
|
|
739
758
|
</html>'
|
740
759
|
|
741
760
|
form = described_class.from_document( url, html ).first
|
742
|
-
form.action.
|
743
|
-
form.name.
|
744
|
-
form.url.
|
745
|
-
form.method.
|
746
|
-
form.inputs.
|
761
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
762
|
+
expect(form.name).to eq('my_form')
|
763
|
+
expect(form.url).to eq(url)
|
764
|
+
expect(form.method).to eq(:get)
|
765
|
+
expect(form.inputs).to eq({
|
747
766
|
'vehicle' => 'Bike',
|
748
767
|
'stuff' => 'Car'
|
749
|
-
}
|
768
|
+
})
|
750
769
|
form.inputs.keys.each do |input|
|
751
|
-
form.field_type_for( input ).
|
770
|
+
expect(form.field_type_for( input )).to eq(:checkbox)
|
752
771
|
end
|
753
772
|
end
|
754
773
|
end
|
@@ -767,16 +786,16 @@ EOHTML
|
|
767
786
|
</html>'
|
768
787
|
|
769
788
|
form = described_class.from_document( url, html ).first
|
770
|
-
form.action.
|
771
|
-
form.name.
|
772
|
-
form.url.
|
773
|
-
form.method.
|
774
|
-
form.inputs.
|
789
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
790
|
+
expect(form.name).to eq('my_form')
|
791
|
+
expect(form.url).to eq(url)
|
792
|
+
expect(form.method).to eq(:get)
|
793
|
+
expect(form.inputs).to eq({
|
775
794
|
'my_first_input' => 'my_first_value',
|
776
795
|
'my_second_input' => 'my_second_value'
|
777
|
-
}
|
796
|
+
})
|
778
797
|
form.inputs.keys.each do |input|
|
779
|
-
form.field_type_for( input ).
|
798
|
+
expect(form.field_type_for( input )).to eq(:radio)
|
780
799
|
end
|
781
800
|
end
|
782
801
|
end
|
@@ -794,12 +813,12 @@ EOHTML
|
|
794
813
|
</html>'
|
795
814
|
|
796
815
|
form = described_class.from_document( url, html ).first
|
797
|
-
form.action.
|
798
|
-
form.name.
|
799
|
-
form.url.
|
800
|
-
form.method.
|
801
|
-
form.field_type_for( 'my_button' ).
|
802
|
-
form.inputs.
|
816
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
817
|
+
expect(form.name).to eq('my_form')
|
818
|
+
expect(form.url).to eq(url)
|
819
|
+
expect(form.method).to eq(:get)
|
820
|
+
expect(form.field_type_for( 'my_button' )).to eq(:submit)
|
821
|
+
expect(form.inputs).to eq({ 'my_button' => 'my_button_value' })
|
803
822
|
end
|
804
823
|
end
|
805
824
|
|
@@ -816,23 +835,23 @@ EOHTML
|
|
816
835
|
</html>'
|
817
836
|
|
818
837
|
forms = described_class.from_document( url, html )
|
819
|
-
forms.size.
|
838
|
+
expect(forms.size).to eq(2)
|
820
839
|
|
821
840
|
form = forms.first
|
822
|
-
form.action.
|
823
|
-
form.name.
|
824
|
-
form.url.
|
825
|
-
form.method.
|
826
|
-
form.field_type_for( 'choice' ).
|
827
|
-
form.inputs['choice'].
|
841
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
842
|
+
expect(form.name).to eq('my_form')
|
843
|
+
expect(form.url).to eq(url)
|
844
|
+
expect(form.method).to eq(:get)
|
845
|
+
expect(form.field_type_for( 'choice' )).to eq(:submit)
|
846
|
+
expect(form.inputs['choice']).to eq('value 1')
|
828
847
|
|
829
848
|
form = forms[1]
|
830
|
-
form.action.
|
831
|
-
form.name.
|
832
|
-
form.url.
|
833
|
-
form.method.
|
834
|
-
form.field_type_for( 'choice' ).
|
835
|
-
form.inputs['choice'].
|
849
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
850
|
+
expect(form.name).to eq('my_form')
|
851
|
+
expect(form.url).to eq(url)
|
852
|
+
expect(form.method).to eq(:get)
|
853
|
+
expect(form.field_type_for( 'choice' )).to eq(:submit)
|
854
|
+
expect(form.inputs['choice']).to eq('value 2')
|
836
855
|
end
|
837
856
|
end
|
838
857
|
|
@@ -859,16 +878,16 @@ EOHTML
|
|
859
878
|
</html>'
|
860
879
|
|
861
880
|
form = described_class.from_document( url, html ).first
|
862
|
-
form.action.
|
863
|
-
form.name.
|
864
|
-
form.url.
|
865
|
-
form.method.
|
866
|
-
form.inputs.
|
881
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
882
|
+
expect(form.name).to eq('my_form')
|
883
|
+
expect(form.url).to eq(url)
|
884
|
+
expect(form.method).to eq(:get)
|
885
|
+
expect(form.inputs).to eq({
|
867
886
|
'manufacturer' => 'volvo',
|
868
887
|
'numbers' => '1'
|
869
|
-
}
|
888
|
+
})
|
870
889
|
form.inputs.keys.each do |input|
|
871
|
-
form.field_type_for( input ).
|
890
|
+
expect(form.field_type_for( input )).to eq(:select)
|
872
891
|
end
|
873
892
|
end
|
874
893
|
end
|
@@ -893,16 +912,16 @@ EOHTML
|
|
893
912
|
</html>'
|
894
913
|
|
895
914
|
form = described_class.from_document( url, html ).first
|
896
|
-
form.action.
|
897
|
-
form.name.
|
898
|
-
form.url.
|
899
|
-
form.method.
|
900
|
-
form.inputs.
|
915
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
916
|
+
expect(form.name).to eq('my_form')
|
917
|
+
expect(form.url).to eq(url)
|
918
|
+
expect(form.method).to eq(:get)
|
919
|
+
expect(form.inputs).to eq({
|
901
920
|
'manufacturer' => 'Volvo',
|
902
921
|
'numbers' => 'One'
|
903
|
-
}
|
922
|
+
})
|
904
923
|
form.inputs.keys.each do |input|
|
905
|
-
form.field_type_for( input ).
|
924
|
+
expect(form.field_type_for( input )).to eq(:select)
|
906
925
|
end
|
907
926
|
end
|
908
927
|
end
|
@@ -929,16 +948,16 @@ EOHTML
|
|
929
948
|
</html>'
|
930
949
|
|
931
950
|
form = described_class.from_document( url, html ).first
|
932
|
-
form.action.
|
933
|
-
form.name.
|
934
|
-
form.url.
|
935
|
-
form.method.
|
936
|
-
form.inputs.
|
951
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
952
|
+
expect(form.name).to eq('my_form')
|
953
|
+
expect(form.url).to eq(url)
|
954
|
+
expect(form.method).to eq(:get)
|
955
|
+
expect(form.inputs).to eq({
|
937
956
|
'manufacturer' => 'Saab',
|
938
957
|
'numbers' => 'Two'
|
939
|
-
}
|
958
|
+
})
|
940
959
|
form.inputs.keys.each do |input|
|
941
|
-
form.field_type_for( input ).
|
960
|
+
expect(form.field_type_for( input )).to eq(:select)
|
942
961
|
end
|
943
962
|
end
|
944
963
|
end
|
@@ -956,13 +975,13 @@ EOHTML
|
|
956
975
|
</html>'
|
957
976
|
|
958
977
|
form = described_class.from_document( url, html ).first
|
959
|
-
form.action.
|
960
|
-
form.name.
|
961
|
-
form.url.
|
962
|
-
form.method.
|
963
|
-
form.inputs.
|
978
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
979
|
+
expect(form.name).to eq('my_form')
|
980
|
+
expect(form.url).to eq(url)
|
981
|
+
expect(form.method).to eq(:get)
|
982
|
+
expect(form.inputs).to eq({ 'manufacturer' => '' })
|
964
983
|
form.inputs.keys.each do |input|
|
965
|
-
form.field_type_for( input ).
|
984
|
+
expect(form.field_type_for( input )).to eq(:select)
|
966
985
|
end
|
967
986
|
end
|
968
987
|
end
|
@@ -988,29 +1007,29 @@ EOHTML
|
|
988
1007
|
</html>'
|
989
1008
|
|
990
1009
|
forms = described_class.from_document( url, html )
|
991
|
-
forms.size.
|
1010
|
+
expect(forms.size).to eq(2)
|
992
1011
|
|
993
1012
|
form = forms.shift
|
994
|
-
form.action.
|
995
|
-
form.name.
|
996
|
-
form.url.
|
997
|
-
form.method.
|
998
|
-
form.inputs.
|
1013
|
+
expect(form.action).to eq(utilities.normalize_url( url + base_url + 'form_action/is/here'))
|
1014
|
+
expect(form.name).to eq('my_form!')
|
1015
|
+
expect(form.url).to eq(url)
|
1016
|
+
expect(form.method).to eq(:get)
|
1017
|
+
expect(form.inputs).to eq({
|
999
1018
|
'text_here' => '',
|
1000
1019
|
'ha' => 'hoo'
|
1001
|
-
}
|
1020
|
+
})
|
1002
1021
|
form.inputs.keys.each do |input|
|
1003
|
-
form.field_type_for( input ).
|
1022
|
+
expect(form.field_type_for( input )).to eq(:text)
|
1004
1023
|
end
|
1005
1024
|
|
1006
1025
|
form = forms.shift
|
1007
|
-
form.action.
|
1008
|
-
form.name.
|
1009
|
-
form.url.
|
1010
|
-
form.method.
|
1011
|
-
form.inputs.
|
1026
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_action' ))
|
1027
|
+
expect(form.name).to eq('my_second_form!')
|
1028
|
+
expect(form.url).to eq(url)
|
1029
|
+
expect(form.method).to eq(:post)
|
1030
|
+
expect(form.inputs).to eq({ 'text_here' => "my value" })
|
1012
1031
|
form.inputs.keys.each do |input|
|
1013
|
-
form.field_type_for( input ).
|
1032
|
+
expect(form.field_type_for( input )).to eq(:text)
|
1014
1033
|
end
|
1015
1034
|
end
|
1016
1035
|
end
|
@@ -1046,34 +1065,34 @@ EOHTML
|
|
1046
1065
|
</html>'
|
1047
1066
|
|
1048
1067
|
forms = described_class.from_document( url, html )
|
1049
|
-
forms.size.
|
1068
|
+
expect(forms.size).to eq(3)
|
1050
1069
|
|
1051
1070
|
form = forms.shift
|
1052
|
-
form.action.
|
1053
|
-
form.name.
|
1054
|
-
form.url.
|
1055
|
-
form.method.
|
1056
|
-
form.inputs.
|
1071
|
+
expect(form.action).to eq(utilities.normalize_url( base_url + 'form_2' ))
|
1072
|
+
expect(form.name).to eq('my_form_2')
|
1073
|
+
expect(form.url).to eq(url)
|
1074
|
+
expect(form.method).to eq(:get)
|
1075
|
+
expect(form.inputs).to eq({ 'text_here' => '' })
|
1057
1076
|
|
1058
1077
|
form = forms.shift
|
1059
|
-
form.action.
|
1060
|
-
form.name.
|
1061
|
-
form.url.
|
1062
|
-
form.method.
|
1063
|
-
form.inputs.
|
1078
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form' ))
|
1079
|
+
expect(form.name).to eq('my_form')
|
1080
|
+
expect(form.url).to eq(url)
|
1081
|
+
expect(form.method).to eq(:post)
|
1082
|
+
expect(form.inputs).to eq({
|
1064
1083
|
'form_input_1' => 'form_val_1',
|
1065
1084
|
'form_input_2' => 'form_val_2'
|
1066
|
-
}
|
1085
|
+
})
|
1067
1086
|
|
1068
1087
|
form = forms.shift
|
1069
|
-
form.action.
|
1070
|
-
form.name.
|
1071
|
-
form.url.
|
1072
|
-
form.method.
|
1073
|
-
form.inputs.
|
1088
|
+
expect(form.action).to eq(utilities.normalize_url( url + '/form_3' ))
|
1089
|
+
expect(form.name).to eq('my_form_3')
|
1090
|
+
expect(form.url).to eq(url)
|
1091
|
+
expect(form.method).to eq(:get)
|
1092
|
+
expect(form.inputs).to eq({
|
1074
1093
|
'form_3_input_1' => 'form_3_val_1',
|
1075
1094
|
'manufacturer' => 'volvo'
|
1076
|
-
}
|
1095
|
+
})
|
1077
1096
|
end
|
1078
1097
|
end
|
1079
1098
|
|
@@ -1096,8 +1115,8 @@ EOHTML
|
|
1096
1115
|
let(:size) { described_class::MAX_SIZE }
|
1097
1116
|
|
1098
1117
|
it 'returns empty array' do
|
1099
|
-
form.inputs['input_1'].
|
1100
|
-
form.inputs['input_2'].
|
1118
|
+
expect(form.inputs['input_1']).to be_empty
|
1119
|
+
expect(form.inputs['input_2']).to eq('val_2')
|
1101
1120
|
end
|
1102
1121
|
end
|
1103
1122
|
|
@@ -1105,8 +1124,8 @@ EOHTML
|
|
1105
1124
|
let(:size) { described_class::MAX_SIZE + 1 }
|
1106
1125
|
|
1107
1126
|
it 'sets empty value' do
|
1108
|
-
form.inputs['input_1'].
|
1109
|
-
form.inputs['input_2'].
|
1127
|
+
expect(form.inputs['input_1']).to be_empty
|
1128
|
+
expect(form.inputs['input_2']).to eq('val_2')
|
1110
1129
|
end
|
1111
1130
|
end
|
1112
1131
|
|
@@ -1114,8 +1133,8 @@ EOHTML
|
|
1114
1133
|
let(:size) { described_class::MAX_SIZE - 1 }
|
1115
1134
|
|
1116
1135
|
it 'leaves the values alone' do
|
1117
|
-
form.inputs['input_1'].
|
1118
|
-
form.inputs['input_2'].
|
1136
|
+
expect(form.inputs['input_1']).to eq(value)
|
1137
|
+
expect(form.inputs['input_2']).to eq('val_2')
|
1119
1138
|
end
|
1120
1139
|
end
|
1121
1140
|
end
|
@@ -1124,25 +1143,29 @@ EOHTML
|
|
1124
1143
|
|
1125
1144
|
describe '.encode' do
|
1126
1145
|
it 'form-encodes the passed string' do
|
1127
|
-
described_class.encode( '% value\ +=&;' ).
|
1146
|
+
expect(described_class.encode( '% value\ +=&;' )).to eq('%25%20value%5C%20%2B%3D%26%3B')
|
1128
1147
|
end
|
1129
1148
|
end
|
1130
1149
|
describe '#encode' do
|
1131
1150
|
it 'form-encodes the passed string' do
|
1132
1151
|
v = '% value\ +=&;'
|
1133
|
-
subject.encode( v ).
|
1152
|
+
expect(subject.encode( v )).to eq(described_class.encode( v ))
|
1134
1153
|
end
|
1135
1154
|
end
|
1136
1155
|
|
1137
1156
|
describe '.decode' do
|
1138
1157
|
it 'form-decodes the passed string' do
|
1139
|
-
described_class.decode( '%25%20value%5C%20%2B%3D%26%3B' ).
|
1158
|
+
expect(described_class.decode( '%25%20value%5C%20%2B%3D%26%3B' )).to eq('% value\ +=&;')
|
1159
|
+
end
|
1160
|
+
|
1161
|
+
it 'handles broken encodings' do
|
1162
|
+
expect(described_class.decode( '%g' )).to eq('%g')
|
1140
1163
|
end
|
1141
1164
|
end
|
1142
1165
|
describe '#decode' do
|
1143
1166
|
it 'form-decodes the passed string' do
|
1144
1167
|
v = '%25%20value%5C%20%2B%3D%26%3B'
|
1145
|
-
subject.decode( v ).
|
1168
|
+
expect(subject.decode( v )).to eq(described_class.decode( v ))
|
1146
1169
|
end
|
1147
1170
|
end
|
1148
1171
|
|