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
|
@@ -16,34 +16,10 @@ module Support::Cache
|
|
|
16
16
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
|
17
17
|
class RandomReplacement < Base
|
|
18
18
|
|
|
19
|
-
# @see Arachni::Cache::Base#initialize
|
|
20
|
-
def initialize( * )
|
|
21
|
-
super
|
|
22
|
-
@keys = []
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# @see Arachni::Cache::Base#store
|
|
26
|
-
def store( k, v )
|
|
27
|
-
already_in = include?( k )
|
|
28
|
-
|
|
29
|
-
super( k, v )
|
|
30
|
-
ensure
|
|
31
|
-
@keys << k if !already_in
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def clear
|
|
35
|
-
super
|
|
36
|
-
@keys.clear
|
|
37
|
-
end
|
|
38
|
-
|
|
39
19
|
private
|
|
40
20
|
|
|
41
|
-
def prune_candidate
|
|
42
|
-
@keys.delete_at( rand( size ) )
|
|
43
|
-
end
|
|
44
|
-
|
|
45
21
|
def prune
|
|
46
|
-
delete(
|
|
22
|
+
@cache.delete( @cache.keys.sample )
|
|
47
23
|
end
|
|
48
24
|
|
|
49
25
|
end
|
|
@@ -80,12 +80,13 @@ class Queue < Base
|
|
|
80
80
|
def pop( non_block = false )
|
|
81
81
|
synchronize do
|
|
82
82
|
loop do
|
|
83
|
-
if
|
|
83
|
+
if internal_empty?
|
|
84
84
|
raise ThreadError, 'queue empty' if non_block
|
|
85
85
|
@waiting.push Thread.current
|
|
86
86
|
@mutex.sleep
|
|
87
87
|
else
|
|
88
|
-
return @buffer.shift
|
|
88
|
+
return @buffer.shift if !@buffer.empty?
|
|
89
|
+
return load_and_delete_file( @disk.shift )
|
|
89
90
|
end
|
|
90
91
|
end
|
|
91
92
|
end
|
|
@@ -100,6 +101,10 @@ class Queue < Base
|
|
|
100
101
|
end
|
|
101
102
|
alias :length :size
|
|
102
103
|
|
|
104
|
+
def free_buffer_size
|
|
105
|
+
max_buffer_size - buffer_size
|
|
106
|
+
end
|
|
107
|
+
|
|
103
108
|
def buffer_size
|
|
104
109
|
@buffer.size
|
|
105
110
|
end
|
|
@@ -111,17 +116,21 @@ class Queue < Base
|
|
|
111
116
|
# @return [Bool]
|
|
112
117
|
# `true` if the queue if empty, `false` otherwise.
|
|
113
118
|
def empty?
|
|
114
|
-
|
|
119
|
+
synchronize do
|
|
120
|
+
internal_empty?
|
|
121
|
+
end
|
|
115
122
|
end
|
|
116
123
|
|
|
117
124
|
# Removes all objects from the queue.
|
|
118
125
|
def clear
|
|
119
|
-
|
|
126
|
+
synchronize do
|
|
127
|
+
@buffer.clear
|
|
120
128
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
129
|
+
while !@disk.empty?
|
|
130
|
+
path = @disk.pop
|
|
131
|
+
next if !path
|
|
132
|
+
delete_file path
|
|
133
|
+
end
|
|
125
134
|
end
|
|
126
135
|
end
|
|
127
136
|
|
|
@@ -131,6 +140,10 @@ class Queue < Base
|
|
|
131
140
|
|
|
132
141
|
private
|
|
133
142
|
|
|
143
|
+
def internal_empty?
|
|
144
|
+
@buffer.empty? && @disk.empty?
|
|
145
|
+
end
|
|
146
|
+
|
|
134
147
|
def synchronize( &block )
|
|
135
148
|
@mutex.synchronize( &block )
|
|
136
149
|
end
|
|
@@ -24,7 +24,9 @@ module Mixins
|
|
|
24
24
|
#
|
|
25
25
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
|
26
26
|
module Observable
|
|
27
|
+
include UI::Output
|
|
27
28
|
include Utilities
|
|
29
|
+
|
|
28
30
|
include MonitorMixin
|
|
29
31
|
|
|
30
32
|
def self.included( base )
|
|
@@ -73,7 +75,7 @@ module Observable
|
|
|
73
75
|
def notify_observers( event, *args )
|
|
74
76
|
synchronize do
|
|
75
77
|
observers_for( event ).each do |block|
|
|
76
|
-
exception_jail { block.call( *args ) }
|
|
78
|
+
exception_jail( false ) { block.call( *args ) }
|
|
77
79
|
end
|
|
78
80
|
end
|
|
79
81
|
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
web site for more information on licensing and terms of use.
|
|
7
7
|
=end
|
|
8
8
|
|
|
9
|
+
require 'objspace'
|
|
9
10
|
require 'sys/proctable'
|
|
10
11
|
require 'ruby-mass'
|
|
11
12
|
require 'stackprof'
|
|
@@ -79,30 +80,70 @@ class Profiler
|
|
|
79
80
|
|
|
80
81
|
def object_space( options = {} )
|
|
81
82
|
klass = options[:class]
|
|
82
|
-
namespaces = options[:namespaces] || [
|
|
83
|
+
namespaces = options[:namespaces] || [
|
|
84
|
+
Arachni,
|
|
85
|
+
Ethon,
|
|
86
|
+
Typhoeus,
|
|
87
|
+
Watir,
|
|
88
|
+
Selenium,
|
|
89
|
+
Addressable,
|
|
90
|
+
Nokogiri,
|
|
91
|
+
String,
|
|
92
|
+
Hash,
|
|
93
|
+
Array,
|
|
94
|
+
Set,
|
|
95
|
+
Thread
|
|
96
|
+
]
|
|
97
|
+
|
|
83
98
|
max_entries = options[:max_entries] || 50
|
|
84
99
|
|
|
85
|
-
object_space =
|
|
86
|
-
@object_space ||=
|
|
100
|
+
object_space = {}
|
|
101
|
+
@object_space ||= {}
|
|
87
102
|
|
|
88
103
|
ObjectSpace.each_object do |o|
|
|
89
104
|
next if o.class != klass && !object_within_namespace?( o, namespaces )
|
|
90
|
-
|
|
105
|
+
|
|
106
|
+
# if o.class == Thread
|
|
107
|
+
# ap ObjectSpace.allocation_class_path( o ).to_s
|
|
108
|
+
# ap "#{ObjectSpace.allocation_sourcefile( o )}:#{ObjectSpace.allocation_sourceline( o )}"
|
|
109
|
+
# ap Utilities.bytes_to_megabytes( ObjectSpace.memsize_of( o ) )
|
|
110
|
+
# ap '-' * 120
|
|
111
|
+
# end
|
|
112
|
+
|
|
113
|
+
object_space[o.class] ||= {
|
|
114
|
+
memsize: 0,
|
|
115
|
+
count: 0
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
object_space[o.class][:memsize] += ObjectSpace.memsize_of(o)
|
|
119
|
+
object_space[o.class][:count] += 1
|
|
91
120
|
end
|
|
92
121
|
|
|
93
|
-
object_space = Hash[object_space.sort_by { |_, v| v }.reverse[0..max_entries]]
|
|
122
|
+
object_space = Hash[object_space.sort_by { |_, v| v[:memsize] }.reverse[0..max_entries]]
|
|
123
|
+
|
|
124
|
+
with_deltas = {}
|
|
125
|
+
object_space.each do |k, v|
|
|
126
|
+
@object_space[k] ||= {
|
|
127
|
+
memsize: 0,
|
|
128
|
+
count: 0
|
|
129
|
+
}
|
|
94
130
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
with_deltas[k]
|
|
131
|
+
if v[:count].is_a? Numeric
|
|
132
|
+
with_deltas[k] = "#{v[:count]} (#{v[:count] - @object_space[k][:count]})"
|
|
133
|
+
with_deltas[k] << " -- #{Utilities.bytes_to_megabytes v[:memsize]}"
|
|
134
|
+
with_deltas[k] << " (#{Utilities.bytes_to_megabytes v[:memsize] - @object_space[k][:memsize]})"
|
|
99
135
|
else
|
|
100
|
-
with_deltas[k] = v
|
|
136
|
+
with_deltas[k] = "#{v[:count]} -- #{Utilities.bytes_to_megabytes v[:memsize]}"
|
|
101
137
|
end
|
|
102
138
|
end
|
|
103
139
|
|
|
104
140
|
@object_space = object_space.dup
|
|
105
141
|
with_deltas
|
|
142
|
+
|
|
143
|
+
rescue => e
|
|
144
|
+
ap e
|
|
145
|
+
ap e.backtrace
|
|
146
|
+
{}
|
|
106
147
|
end
|
|
107
148
|
|
|
108
149
|
def write_object_space( file, options = {} )
|
|
@@ -14,6 +14,10 @@ module Arachni::Support
|
|
|
14
14
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
|
15
15
|
class Signature
|
|
16
16
|
|
|
17
|
+
CACHE = {
|
|
18
|
+
tokens: Cache::LeastRecentlyPushed.new( 100 )
|
|
19
|
+
}
|
|
20
|
+
|
|
17
21
|
attr_reader :tokens
|
|
18
22
|
|
|
19
23
|
# @note The string will be tokenized based on whitespace.
|
|
@@ -109,14 +113,19 @@ class Signature
|
|
|
109
113
|
# hashes, depending on which is smaller in size.
|
|
110
114
|
def tokenize( data )
|
|
111
115
|
return data.tokens if data.is_a? self.class
|
|
112
|
-
|
|
116
|
+
|
|
117
|
+
if CACHE[:tokens][data]
|
|
118
|
+
CACHE[:tokens][data].dup
|
|
119
|
+
else
|
|
120
|
+
CACHE[:tokens][data] = compress( data.split( /(?![\w])/ ) )
|
|
121
|
+
end
|
|
113
122
|
end
|
|
114
123
|
|
|
115
124
|
# Compresses the tokens by only storing unique #hash values.
|
|
116
125
|
# Seems kinda silly but this can actually save us GB of RAM when comparing
|
|
117
126
|
# large signatures, not to mention CPU cycles.
|
|
118
127
|
def compress( tokens )
|
|
119
|
-
tokens.
|
|
128
|
+
Set.new( tokens.map(&:hash) )
|
|
120
129
|
end
|
|
121
130
|
|
|
122
131
|
end
|
data/lib/arachni/trainer.rb
CHANGED
|
@@ -120,6 +120,7 @@ class Trainer
|
|
|
120
120
|
# no new cookies have appeared there's no reason to analyze the page
|
|
121
121
|
if incoming_page.body == @page.body && !has_new_elements &&
|
|
122
122
|
@page.url == incoming_page.url
|
|
123
|
+
incoming_page.clear_cache
|
|
123
124
|
print_debug 'Page hasn\'t changed.'
|
|
124
125
|
return
|
|
125
126
|
end
|
|
@@ -140,12 +141,17 @@ class Trainer
|
|
|
140
141
|
end
|
|
141
142
|
end
|
|
142
143
|
|
|
144
|
+
incoming_page.clear_cache
|
|
145
|
+
|
|
143
146
|
print_debug 'Training complete.'
|
|
144
147
|
end
|
|
145
148
|
|
|
146
149
|
def has_new?( incoming_page, element_type )
|
|
147
|
-
count = ElementFilter.send(
|
|
148
|
-
|
|
150
|
+
count = ElementFilter.send(
|
|
151
|
+
"update_#{element_type}".to_sym,
|
|
152
|
+
incoming_page.send( element_type )
|
|
153
|
+
)
|
|
154
|
+
|
|
149
155
|
return if count == 0
|
|
150
156
|
|
|
151
157
|
print_info "Found #{count} new #{element_type}."
|
data/lib/arachni/uri.rb
CHANGED
|
@@ -50,21 +50,21 @@ class URI
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
CACHE_SIZES = {
|
|
53
|
-
parse:
|
|
54
|
-
ruby_parse:
|
|
55
|
-
fast_parse:
|
|
53
|
+
parse: 1000,
|
|
54
|
+
ruby_parse: 1000,
|
|
55
|
+
fast_parse: 1000,
|
|
56
|
+
encode: 1000,
|
|
57
|
+
decode: 1000,
|
|
56
58
|
normalize: 1000,
|
|
57
59
|
to_absolute: 1000
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
CACHE = {
|
|
61
|
-
parser:
|
|
62
|
-
ruby_parse: Support::Cache::RandomReplacement.new( CACHE_SIZES[:ruby_parse] ),
|
|
63
|
-
parse: Support::Cache::RandomReplacement.new( CACHE_SIZES[:parse] ),
|
|
64
|
-
fast_parse: Support::Cache::RandomReplacement.new( CACHE_SIZES[:fast_parse] ),
|
|
65
|
-
normalize: Support::Cache::RandomReplacement.new( CACHE_SIZES[:normalize] ),
|
|
66
|
-
to_absolute: Support::Cache::RandomReplacement.new( CACHE_SIZES[:to_absolute] )
|
|
63
|
+
parser: ::URI::Parser.new
|
|
67
64
|
}
|
|
65
|
+
CACHE_SIZES.each do |name, size|
|
|
66
|
+
CACHE[name] = Support::Cache::LeastRecentlyPushed.new( size )
|
|
67
|
+
end
|
|
68
68
|
|
|
69
69
|
class <<self
|
|
70
70
|
|
|
@@ -76,14 +76,15 @@ class URI
|
|
|
76
76
|
# URL encodes a string.
|
|
77
77
|
#
|
|
78
78
|
# @param [String] string
|
|
79
|
-
# @param [String, Regexp]
|
|
80
|
-
# Class of characters to
|
|
79
|
+
# @param [String, Regexp] good_characters
|
|
80
|
+
# Class of characters to allow -- if {String} is passed, it should
|
|
81
81
|
# formatted as a regexp (for `Regexp.new`).
|
|
82
82
|
#
|
|
83
83
|
# @return [String]
|
|
84
84
|
# Encoded string.
|
|
85
|
-
def encode( string,
|
|
86
|
-
|
|
85
|
+
def encode( string, good_characters = nil )
|
|
86
|
+
CACHE[__method__][[string, good_characters]] ||=
|
|
87
|
+
Addressable::URI.encode_component( *[string, good_characters].compact )
|
|
87
88
|
end
|
|
88
89
|
|
|
89
90
|
# URL decodes a string.
|
|
@@ -92,7 +93,7 @@ class URI
|
|
|
92
93
|
#
|
|
93
94
|
# @return [String]
|
|
94
95
|
def decode( string )
|
|
95
|
-
Addressable::URI.unencode( string )
|
|
96
|
+
CACHE[__method__][string] ||= Addressable::URI.unencode( string )
|
|
96
97
|
end
|
|
97
98
|
|
|
98
99
|
# @note This method's results are cached for performance reasons.
|
|
@@ -176,8 +177,11 @@ class URI
|
|
|
176
177
|
url = url.to_s.dup
|
|
177
178
|
|
|
178
179
|
# Remove the fragment if there is one.
|
|
179
|
-
|
|
180
|
-
|
|
180
|
+
if url.include?( '#' )
|
|
181
|
+
url = url.split( '#', 2 )[0...-1].join
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
c_url = url.dup
|
|
181
185
|
|
|
182
186
|
components = {
|
|
183
187
|
scheme: nil,
|
|
@@ -204,7 +208,7 @@ class URI
|
|
|
204
208
|
return cache[c_url] = addressable_parse( c_url ).freeze
|
|
205
209
|
end
|
|
206
210
|
|
|
207
|
-
url = url.recode
|
|
211
|
+
url = url.recode!
|
|
208
212
|
url = html_decode( url )
|
|
209
213
|
|
|
210
214
|
dupped_url = url.dup
|
|
@@ -282,9 +286,8 @@ class URI
|
|
|
282
286
|
!(query = dupped_url.split( '?', 2 ).last).empty?
|
|
283
287
|
|
|
284
288
|
components[:query] = (query.split( '&', -1 ).map do |pair|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
)
|
|
289
|
+
encode( decode( pair ),
|
|
290
|
+
Addressable::URI::CharacterClasses::QUERY.sub( '\\&', '' ) )
|
|
288
291
|
end).join( '&' )
|
|
289
292
|
end
|
|
290
293
|
end
|
|
@@ -300,7 +303,7 @@ class URI
|
|
|
300
303
|
print_debug "Error: #{e}"
|
|
301
304
|
print_debug_backtrace( e )
|
|
302
305
|
|
|
303
|
-
cache[c_url] = addressable_parse( c_url.recode ).freeze
|
|
306
|
+
cache[c_url] = addressable_parse( c_url.recode! ).freeze
|
|
304
307
|
rescue => ex
|
|
305
308
|
print_debug "Failed to parse '#{c_url}'."
|
|
306
309
|
print_debug "Error: #{ex}"
|
|
@@ -405,8 +408,8 @@ class URI
|
|
|
405
408
|
|
|
406
409
|
cache = CACHE[__method__]
|
|
407
410
|
|
|
408
|
-
url = url.to_s.strip
|
|
409
|
-
c_url = url.
|
|
411
|
+
url = url.to_s.strip
|
|
412
|
+
c_url = url.dup
|
|
410
413
|
|
|
411
414
|
begin
|
|
412
415
|
if (v = cache[url]) && v == :err
|
|
@@ -494,13 +497,13 @@ class URI
|
|
|
494
497
|
self.class.ruby_parse( url )
|
|
495
498
|
|
|
496
499
|
when ::URI
|
|
497
|
-
url
|
|
500
|
+
url
|
|
498
501
|
|
|
499
502
|
when Hash
|
|
500
503
|
::URI::Generic.build( url )
|
|
501
504
|
|
|
502
505
|
when Arachni::URI
|
|
503
|
-
self.parsed_url = url.parsed_url
|
|
506
|
+
self.parsed_url = url.parsed_url
|
|
504
507
|
|
|
505
508
|
else
|
|
506
509
|
to_string = url.to_s rescue ''
|
data/lib/arachni/uri/scope.rb
CHANGED
|
@@ -80,7 +80,7 @@ class Scope < Arachni::Scope
|
|
|
80
80
|
|
|
81
81
|
check_scheme = @url.scheme.to_s
|
|
82
82
|
|
|
83
|
-
return false if
|
|
83
|
+
return false if check_scheme != 'http' && check_scheme != 'https'
|
|
84
84
|
|
|
85
85
|
parsed_ref = Arachni::URI( Options.url )
|
|
86
86
|
return false if !parsed_ref
|
data/lib/arachni/utilities.rb
CHANGED
|
@@ -391,6 +391,14 @@ module Utilities
|
|
|
391
391
|
0
|
|
392
392
|
end
|
|
393
393
|
|
|
394
|
+
def bytes_to_megabytes( bytes )
|
|
395
|
+
(bytes / 1024.0 / 1024.0).round( 3 )
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
def bytes_to_kilobytes( bytes )
|
|
399
|
+
(bytes / 1024.0 ).round( 3 )
|
|
400
|
+
end
|
|
401
|
+
|
|
394
402
|
# Wraps the `block` in exception handling code and runs it.
|
|
395
403
|
#
|
|
396
404
|
# @param [Bool] raise_exception
|