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
data/lib/arachni/element/json.rb
CHANGED
|
@@ -44,7 +44,7 @@ class JSON < Base
|
|
|
44
44
|
self.inputs = (self.inputs || {}).merge( options[:inputs] || {} )
|
|
45
45
|
|
|
46
46
|
if @source && self.inputs.empty?
|
|
47
|
-
self.inputs = JSON.load( self.source )
|
|
47
|
+
self.inputs = ::JSON.load( self.source )
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
@default_inputs = self.inputs.dup.freeze
|
|
@@ -104,6 +104,7 @@ class JSON < Base
|
|
|
104
104
|
# @return [JSON, nil]
|
|
105
105
|
def from_request( url, request )
|
|
106
106
|
return if !request.body.is_a?( String ) || request.body.empty?
|
|
107
|
+
return if too_big?( request.body )
|
|
107
108
|
|
|
108
109
|
data = begin
|
|
109
110
|
::JSON.load( request.body )
|
|
@@ -45,7 +45,7 @@ module Inputtable
|
|
|
45
45
|
#
|
|
46
46
|
# @return [Object]
|
|
47
47
|
#
|
|
48
|
-
# @see Capabilities::Inputtable#[]
|
|
48
|
+
# @see Arachni::Element::Capabilities::Inputtable#[]
|
|
49
49
|
def []( name )
|
|
50
50
|
key, data = find( name )
|
|
51
51
|
data[key]
|
|
@@ -65,7 +65,7 @@ module Inputtable
|
|
|
65
65
|
# @return [Object]
|
|
66
66
|
# `value`
|
|
67
67
|
#
|
|
68
|
-
# @see Capabilities::Inputtable#[]=
|
|
68
|
+
# @see Arachni::Element::Capabilities::Inputtable#[]=
|
|
69
69
|
def []=( name, value )
|
|
70
70
|
@inputs = @inputs.dup
|
|
71
71
|
key, data = find( name )
|
|
@@ -80,11 +80,11 @@ module Inputtable
|
|
|
80
80
|
# Overrides {Capabilities::Inputtable#update} to allow for non-string data
|
|
81
81
|
# of variable depth.
|
|
82
82
|
#
|
|
83
|
-
# @param (see Capabilities::Inputtable#update)
|
|
84
|
-
# @return (see Capabilities::Inputtable#update)
|
|
85
|
-
# @raise (see Capabilities::Inputtable#update)
|
|
83
|
+
# @param (see Arachni::Element::Capabilities::Inputtable#update)
|
|
84
|
+
# @return (see Arachni::Element::Capabilities::Inputtable#update)
|
|
85
|
+
# @raise (see Arachni::Element::Capabilities::Inputtable#update)
|
|
86
86
|
#
|
|
87
|
-
# @see Capabilities::Inputtable#update
|
|
87
|
+
# @see Arachni::Element::Capabilities::Inputtable#update
|
|
88
88
|
def update( hash )
|
|
89
89
|
traverse_data hash do |path, value|
|
|
90
90
|
self[path] = value
|
|
@@ -26,7 +26,7 @@ module Mutable
|
|
|
26
26
|
# If the `name` is an `Array`, it will be treated as a path to the location
|
|
27
27
|
# of the input.
|
|
28
28
|
#
|
|
29
|
-
# @see Capabilities::Mutable#affected_input_name=
|
|
29
|
+
# @see Arachni::Element::Capabilities::Mutable#affected_input_name=
|
|
30
30
|
def affected_input_name=( name )
|
|
31
31
|
if name.is_a?( Array ) && name.size == 1
|
|
32
32
|
name = name.first
|
data/lib/arachni/element/link.rb
CHANGED
|
@@ -55,19 +55,11 @@ class Link < Base
|
|
|
55
55
|
def to_s
|
|
56
56
|
uri = uri_parse( self.action ).dup
|
|
57
57
|
uri.query = self.inputs.
|
|
58
|
-
map { |k, v| "#{
|
|
58
|
+
map { |k, v| "#{encode(k)}=#{encode(v)}" }.
|
|
59
59
|
join( '&' )
|
|
60
60
|
uri.to_s
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
# @param (see .encode_query_params)
|
|
64
|
-
# @return (see .encode_query_params)
|
|
65
|
-
#
|
|
66
|
-
# @see .encode_query_params
|
|
67
|
-
def encode_query_params( *args )
|
|
68
|
-
self.class.encode_query_params( *args )
|
|
69
|
-
end
|
|
70
|
-
|
|
71
63
|
# @param (see .encode)
|
|
72
64
|
# @return (see .encode)
|
|
73
65
|
#
|
|
@@ -114,7 +106,14 @@ class Link < Base
|
|
|
114
106
|
#
|
|
115
107
|
# @return [Array<Link>]
|
|
116
108
|
def from_document( url, document )
|
|
117
|
-
|
|
109
|
+
if !document.is_a?( Nokogiri::HTML::Document )
|
|
110
|
+
document = document.to_s
|
|
111
|
+
|
|
112
|
+
return [] if !(document =~ /\?.*=/)
|
|
113
|
+
|
|
114
|
+
document = Nokogiri::HTML( document )
|
|
115
|
+
end
|
|
116
|
+
|
|
118
117
|
base_url = begin
|
|
119
118
|
document.search( '//base[@href]' )[0]['href']
|
|
120
119
|
rescue
|
|
@@ -122,6 +121,8 @@ class Link < Base
|
|
|
122
121
|
end
|
|
123
122
|
|
|
124
123
|
document.search( '//a' ).map do |link|
|
|
124
|
+
next if too_big?( link['href'] )
|
|
125
|
+
|
|
125
126
|
href = to_absolute( link['href'], base_url )
|
|
126
127
|
next if !href
|
|
127
128
|
|
|
@@ -137,12 +138,8 @@ class Link < Base
|
|
|
137
138
|
end.compact
|
|
138
139
|
end
|
|
139
140
|
|
|
140
|
-
def
|
|
141
|
-
encode
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
def encode( *args )
|
|
145
|
-
::URI.encode( *args )
|
|
141
|
+
def encode( string )
|
|
142
|
+
Arachni::HTTP::Request.encode string
|
|
146
143
|
end
|
|
147
144
|
|
|
148
145
|
def decode( *args )
|
|
@@ -57,7 +57,7 @@ class DOM < Base
|
|
|
57
57
|
# URL including the DOM {#inputs}.
|
|
58
58
|
def to_s
|
|
59
59
|
"#{@action}##{fragment_path}?" << inputs.
|
|
60
|
-
map { |k, v| "#{
|
|
60
|
+
map { |k, v| "#{encode(k)}=#{encode(v)}" }.
|
|
61
61
|
join( '&' )
|
|
62
62
|
end
|
|
63
63
|
|
|
@@ -65,22 +65,9 @@ class DOM < Base
|
|
|
65
65
|
"#{@action}##{fragment}"
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
def encode_query_params( *args )
|
|
69
|
-
Link.encode_query_params( *args )
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def encode( *args )
|
|
73
|
-
Link.encode( *args )
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def decode( *args )
|
|
77
|
-
Link.decode( *args )
|
|
78
|
-
end
|
|
79
|
-
|
|
80
68
|
def type
|
|
81
69
|
self.class.type
|
|
82
70
|
end
|
|
83
|
-
|
|
84
71
|
def self.type
|
|
85
72
|
:link_dom
|
|
86
73
|
end
|
|
@@ -170,6 +170,7 @@ class LinkTemplate < Base
|
|
|
170
170
|
end
|
|
171
171
|
|
|
172
172
|
document.search( '//a' ).map do |link|
|
|
173
|
+
next if too_big?( link['href'] )
|
|
173
174
|
next if !(href = to_absolute( link['href'], base_url ))
|
|
174
175
|
|
|
175
176
|
template, inputs = extract_inputs( href, templates )
|
|
@@ -212,11 +213,11 @@ class LinkTemplate < Base
|
|
|
212
213
|
end
|
|
213
214
|
|
|
214
215
|
def encode( string )
|
|
215
|
-
|
|
216
|
+
Link.encode string
|
|
216
217
|
end
|
|
217
218
|
|
|
218
219
|
def decode( *args )
|
|
219
|
-
|
|
220
|
+
Link.decode( *args )
|
|
220
221
|
end
|
|
221
222
|
|
|
222
223
|
def type
|
|
@@ -68,22 +68,6 @@ class DOM < Base
|
|
|
68
68
|
LinkTemplate.extract_inputs( url, templates )
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
def encode( string )
|
|
72
|
-
self.class.encode( string )
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def self.encode( string )
|
|
76
|
-
string
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def decode( *args )
|
|
80
|
-
self.class.decode( *args )
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def self.decode( *args )
|
|
84
|
-
Link.decode( *args )
|
|
85
|
-
end
|
|
86
|
-
|
|
87
71
|
def type
|
|
88
72
|
self.class.type
|
|
89
73
|
end
|
|
@@ -16,14 +16,27 @@ module Arachni::Element
|
|
|
16
16
|
class Server < Base
|
|
17
17
|
include Capabilities::WithAuditor
|
|
18
18
|
|
|
19
|
-
#
|
|
20
|
-
#
|
|
19
|
+
# Valid responses to discovery checks should vary *wildly*, especially when
|
|
20
|
+
# considering the types of directories and files that these checks look for.
|
|
21
21
|
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
22
|
+
# On the other hand, custom-404 or such responses will have many things in
|
|
23
|
+
# common which makes it possible to spot them without much bother.
|
|
24
|
+
#
|
|
25
|
+
# Ideally, custom-404s will be identified properly by the
|
|
26
|
+
# {HTTP::Client::Dynamic404Handler} but this is here to save our ass in case
|
|
27
|
+
# there's a bug or an unforeseen edge-case or something.
|
|
28
|
+
#
|
|
29
|
+
# Also, identified resources should be analyzed by the {Trainer} but there
|
|
30
|
+
# can be cases where unreliable custom-404 signatures lead to FPs and feeding
|
|
31
|
+
# FPs to the system can create an infinite loop.
|
|
25
32
|
SIMILARITY_TOLERANCE = 0.25
|
|
26
33
|
|
|
34
|
+
# Remark in case of an untrusted issue.
|
|
35
|
+
REMARK = 'This issue was logged by a discovery check but ' +
|
|
36
|
+
'the response for the resource it identified is very similar to responses ' +
|
|
37
|
+
'for other resources of similar type. This is a strong indication that ' +
|
|
38
|
+
'the logged issue is a false positive.'
|
|
39
|
+
|
|
27
40
|
def initialize( url )
|
|
28
41
|
super url: url
|
|
29
42
|
@initialization_options = url
|
|
@@ -86,7 +99,13 @@ class Server < Base
|
|
|
86
99
|
return false if !full_and_absolute_url?( url )
|
|
87
100
|
|
|
88
101
|
if http.dynamic_404_handler.needs_check?( url )
|
|
89
|
-
|
|
102
|
+
|
|
103
|
+
# Don't enable fingerprinting if there's a dynamic handler, we don't
|
|
104
|
+
# want to keep analyzing non existent resources.
|
|
105
|
+
#
|
|
106
|
+
# If a resource does exist though it will be fingerprinted down the
|
|
107
|
+
# line.
|
|
108
|
+
http.get( url, performer: self, fingerprint: false ) do |r|
|
|
90
109
|
if r.code == 200
|
|
91
110
|
http.dynamic_404_handler._404?( r ) { |bool| block.call( !bool, r ) }
|
|
92
111
|
else
|
|
@@ -118,6 +137,23 @@ class Server < Base
|
|
|
118
137
|
s << '>'
|
|
119
138
|
end
|
|
120
139
|
|
|
140
|
+
def self.flag_issues_as_untrusted( issue_digests )
|
|
141
|
+
issue_digests.uniq.each do |digest|
|
|
142
|
+
next if !Arachni::Data.issues[digest]
|
|
143
|
+
|
|
144
|
+
Arachni::Data.issues[digest].variations.each do |issue|
|
|
145
|
+
issue.add_remark :meta_analysis, REMARK
|
|
146
|
+
issue.trusted = false
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def self.flag_issues_if_untrusted( similarity, issue_digests )
|
|
152
|
+
return if similarity < SIMILARITY_TOLERANCE
|
|
153
|
+
|
|
154
|
+
flag_issues_as_untrusted( issue_digests )
|
|
155
|
+
end
|
|
156
|
+
|
|
121
157
|
private
|
|
122
158
|
|
|
123
159
|
def analyze
|
|
@@ -153,10 +189,14 @@ class Server < Base
|
|
|
153
189
|
# framework custom-404s and get into an infinite loop.
|
|
154
190
|
train = similarity < SIMILARITY_TOLERANCE
|
|
155
191
|
|
|
192
|
+
issue_digests = []
|
|
156
193
|
@candidates.each do |response, block|
|
|
157
|
-
log response, train, &block
|
|
194
|
+
issue_digests << log( response, train, &block ).digest
|
|
158
195
|
end
|
|
159
196
|
|
|
197
|
+
return if train
|
|
198
|
+
|
|
199
|
+
self.class.flag_issues_as_untrusted( issue_digests )
|
|
160
200
|
ensure
|
|
161
201
|
@candidates.clear
|
|
162
202
|
end
|
|
@@ -164,12 +204,14 @@ class Server < Base
|
|
|
164
204
|
def log( response, train = true, &block )
|
|
165
205
|
block.call( response ) if block_given?
|
|
166
206
|
|
|
167
|
-
auditor.log_remote_file( response )
|
|
207
|
+
issue = auditor.log_remote_file( response )
|
|
168
208
|
|
|
169
|
-
return if !train
|
|
209
|
+
return issue if !train
|
|
170
210
|
|
|
171
211
|
# Use the newly identified resource to increase the scan scope.
|
|
172
212
|
auditor.framework.trainer.push( response )
|
|
213
|
+
|
|
214
|
+
issue
|
|
173
215
|
end
|
|
174
216
|
|
|
175
217
|
end
|
data/lib/arachni/element/xml.rb
CHANGED
|
@@ -137,6 +137,7 @@ class XML < Base
|
|
|
137
137
|
# @return [XML, nil]
|
|
138
138
|
def from_request( url, request )
|
|
139
139
|
return if !request.body.is_a?( String ) || request.body.empty?
|
|
140
|
+
return if too_big?( request.body )
|
|
140
141
|
|
|
141
142
|
data = parse_inputs( request.body )
|
|
142
143
|
return if data.empty?
|
data/lib/arachni/ethon/easy.rb
CHANGED
|
@@ -11,9 +11,12 @@ class Easy
|
|
|
11
11
|
module Callbacks
|
|
12
12
|
def debug_callback
|
|
13
13
|
@debug_callback ||= proc do |handle, type, data, size, udata|
|
|
14
|
+
# We only care about these so that we can have access to raw
|
|
15
|
+
# HTTP request traffic for reporting/debugging purposes.
|
|
16
|
+
next if type != :header_out && type != :data_out
|
|
17
|
+
|
|
14
18
|
message = data.read_string( size )
|
|
15
19
|
@debug_info.add type, message
|
|
16
|
-
# print message unless [:data_in, :data_out].include?(type)
|
|
17
20
|
0
|
|
18
21
|
end
|
|
19
22
|
end
|
|
@@ -117,25 +117,28 @@ module Audit
|
|
|
117
117
|
# resulting pages back to the framework.
|
|
118
118
|
perform_browser_analysis( page )
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
120
|
+
run_http = false
|
|
121
|
+
|
|
122
|
+
if checks.any?
|
|
123
|
+
# Remove elements which have already passed through here.
|
|
124
|
+
pre_audit_element_filter( page )
|
|
125
|
+
|
|
126
|
+
notify_on_effective_page_audit( page )
|
|
127
|
+
|
|
128
|
+
# Run checks which **don't** benefit from fingerprinting first, so
|
|
129
|
+
# that we can use the responses of their HTTP requests to fingerprint
|
|
130
|
+
# the webapp platforms, so that the checks which **do** benefit from
|
|
131
|
+
# knowing the remote platforms can run more efficiently.
|
|
132
|
+
run_http = run_checks( @checks.without_platforms, page )
|
|
133
|
+
run_http = true if run_checks( @checks.with_platforms, page )
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
notify_after_page_audit( page )
|
|
137
|
+
|
|
138
|
+
# Makes it easier on the GC but it is important that it be called
|
|
139
|
+
# **after** all the callbacks have been executed because they may need
|
|
140
|
+
# access to the cached data and there's no sense in re-parsing.
|
|
141
|
+
page.clear_cache
|
|
139
142
|
|
|
140
143
|
if Arachni::Check::Auditor.has_timeout_candidates?
|
|
141
144
|
print_line
|
|
@@ -145,10 +148,6 @@ module Audit
|
|
|
145
148
|
run_http = true
|
|
146
149
|
end
|
|
147
150
|
|
|
148
|
-
# Makes it easier on the GC.
|
|
149
|
-
page.clear_cache
|
|
150
|
-
|
|
151
|
-
notify_after_page_audit( page )
|
|
152
151
|
run_http
|
|
153
152
|
end
|
|
154
153
|
|
|
@@ -207,66 +206,21 @@ module Audit
|
|
|
207
206
|
|
|
208
207
|
@audit_queues_done = false
|
|
209
208
|
|
|
210
|
-
|
|
211
|
-
# consume them and get it over with.
|
|
212
|
-
audit_page_queue
|
|
213
|
-
|
|
214
|
-
next_page = nil
|
|
215
|
-
while !suspended? && !page_limit_reached? &&
|
|
216
|
-
(page = next_page || pop_page_from_url_queue)
|
|
217
|
-
|
|
218
|
-
# Schedule the next page to be grabbed along with the audit requests
|
|
219
|
-
# for the current page in order to avoid blocking.
|
|
220
|
-
next_page = nil
|
|
221
|
-
next_page_call = proc do
|
|
222
|
-
pop_page_from_url_queue { |p| next_page = p }
|
|
223
|
-
end
|
|
209
|
+
while !suspended? && !page_limit_reached? && (page = pop_page)
|
|
224
210
|
|
|
225
|
-
|
|
226
|
-
# before grabbing and auditing the next page.
|
|
227
|
-
if session.can_login?
|
|
228
|
-
# Schedule the login check to happen along with the audit requests
|
|
229
|
-
# to prevent blocking and grab the next page as well.
|
|
230
|
-
session.logged_in? do |bool|
|
|
231
|
-
next next_page_call.call if bool
|
|
211
|
+
session.ensure_logged_in
|
|
232
212
|
|
|
233
|
-
|
|
234
|
-
next_page_call
|
|
235
|
-
end
|
|
236
|
-
else
|
|
237
|
-
next_page_call.call
|
|
238
|
-
end
|
|
213
|
+
replenish_page_queue_from_url_queue
|
|
239
214
|
|
|
240
|
-
# We're counting on piggybacking the
|
|
215
|
+
# We're counting on piggybacking the page queue replenishing on the
|
|
241
216
|
# page audit, however if there wasn't an audit we need to force an
|
|
242
217
|
# HTTP run.
|
|
243
218
|
audit_page( page ) or http.run
|
|
244
219
|
|
|
245
|
-
if next_page && suspend?
|
|
246
|
-
data.page_queue << next_page
|
|
247
|
-
end
|
|
248
|
-
|
|
249
220
|
handle_signals
|
|
250
|
-
|
|
251
|
-
# Consume pages somehow triggered by the audit and pushed by the
|
|
252
|
-
# trainer or plugins or whatever.
|
|
253
|
-
audit_page_queue
|
|
254
221
|
end
|
|
255
222
|
|
|
256
|
-
audit_page_queue
|
|
257
|
-
|
|
258
223
|
@audit_queues_done = true
|
|
259
|
-
true
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
# Audits the page queue.
|
|
263
|
-
#
|
|
264
|
-
# @see #pop_page_from_queue
|
|
265
|
-
def audit_page_queue
|
|
266
|
-
while !suspended? && !page_limit_reached? && (page = pop_page_from_queue)
|
|
267
|
-
audit_page( page )
|
|
268
|
-
handle_signals
|
|
269
|
-
end
|
|
270
224
|
end
|
|
271
225
|
|
|
272
226
|
def harvest_http_responses
|
|
@@ -274,10 +228,6 @@ module Audit
|
|
|
274
228
|
print_info 'Depending on server responsiveness and network' <<
|
|
275
229
|
' conditions this may take a while.'
|
|
276
230
|
|
|
277
|
-
# Run all the queued HTTP requests and harvest the responses.
|
|
278
|
-
http.run
|
|
279
|
-
|
|
280
|
-
# Needed for some HTTP callbacks.
|
|
281
231
|
http.run
|
|
282
232
|
end
|
|
283
233
|
|
|
@@ -286,4 +236,3 @@ end
|
|
|
286
236
|
end
|
|
287
237
|
end
|
|
288
238
|
end
|
|
289
|
-
|