arachni 1.1 → 1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +159 -0
- data/LICENSE.md +126 -196
- data/README.md +32 -24
- data/arachni.gemspec +7 -7
- data/components/checks/active/code_injection_timing.rb +3 -3
- data/components/checks/active/csrf.rb +2 -2
- data/components/checks/active/file_inclusion.rb +6 -7
- data/components/checks/active/os_cmd_injection.rb +3 -3
- data/components/checks/active/path_traversal.rb +7 -7
- data/components/checks/active/response_splitting.rb +9 -4
- data/components/checks/active/session_fixation.rb +7 -3
- data/components/checks/active/source_code_disclosure.rb +5 -5
- data/components/checks/active/unvalidated_redirect.rb +12 -3
- data/components/checks/active/unvalidated_redirect_dom.rb +3 -3
- data/components/checks/active/xss.rb +23 -10
- data/components/checks/active/xss_dom_inputs.rb +113 -11
- data/components/checks/active/xxe.rb +3 -3
- data/components/checks/passive/backdoors.rb +6 -5
- data/components/checks/passive/backup_directories.rb +6 -6
- data/components/checks/passive/backup_files.rb +6 -6
- data/components/checks/passive/common_admin_interfaces.rb +58 -0
- data/components/checks/passive/common_admin_interfaces/admin-panels.txt +49 -0
- data/components/checks/passive/common_directories/directories.txt +0 -16
- data/components/checks/passive/common_files.rb +6 -5
- data/components/checks/passive/common_files/filenames.txt +0 -2
- data/components/checks/passive/directory_listing.rb +6 -6
- data/components/checks/passive/grep/cookie_set_for_parent_domain.rb +3 -3
- data/components/checks/passive/grep/hsts.rb +6 -3
- data/components/checks/passive/grep/http_only_cookies.rb +3 -3
- data/components/checks/passive/grep/insecure_cookies.rb +2 -2
- data/components/checks/passive/grep/insecure_cors_policy.rb +6 -4
- data/components/checks/passive/grep/x_frame_options.rb +6 -4
- data/components/checks/passive/htaccess_limit.rb +6 -2
- data/components/checks/passive/http_put.rb +8 -4
- data/components/checks/passive/interesting_responses.rb +3 -2
- data/components/checks/passive/localstart_asp.rb +6 -2
- data/components/checks/passive/origin_spoof_access_restriction_bypass.rb +5 -1
- data/components/checks/passive/xst.rb +6 -2
- data/components/fingerprinters/frameworks/aspx_mvc.rb +43 -0
- data/components/fingerprinters/frameworks/cakephp.rb +28 -0
- data/components/fingerprinters/frameworks/cherrypy.rb +31 -0
- data/components/fingerprinters/frameworks/django.rb +33 -0
- data/components/fingerprinters/frameworks/jsf.rb +30 -0
- data/components/fingerprinters/frameworks/rack.rb +5 -7
- data/components/fingerprinters/frameworks/rails.rb +43 -0
- data/components/fingerprinters/languages/aspx.rb +11 -11
- data/components/fingerprinters/languages/{jsp.rb → java.rb} +11 -7
- data/components/fingerprinters/languages/php.rb +6 -6
- data/components/fingerprinters/languages/python.rb +14 -6
- data/components/fingerprinters/languages/ruby.rb +3 -5
- data/components/fingerprinters/servers/apache.rb +5 -4
- data/components/fingerprinters/servers/gunicorn.rb +33 -0
- data/components/fingerprinters/servers/jetty.rb +1 -1
- data/components/fingerprinters/servers/tomcat.rb +11 -4
- data/components/path_extractors/anchors.rb +5 -12
- data/components/path_extractors/areas.rb +5 -13
- data/components/path_extractors/comments.rb +5 -3
- data/components/path_extractors/data_url.rb +21 -0
- data/components/path_extractors/forms.rb +5 -13
- data/components/path_extractors/frames.rb +6 -13
- data/components/path_extractors/generic.rb +3 -12
- data/components/path_extractors/links.rb +5 -13
- data/components/path_extractors/meta_refresh.rb +5 -13
- data/components/path_extractors/scripts.rb +8 -14
- data/components/plugins/autologin.rb +17 -5
- data/components/plugins/defaults/meta/remedies/discovery.rb +11 -29
- data/components/plugins/login_script.rb +40 -10
- data/components/plugins/metrics.rb +235 -0
- data/components/plugins/proxy.rb +21 -4
- data/components/plugins/proxy/panel/page_accordion.html.erb +34 -2
- data/components/plugins/restrict_to_dom_state.rb +70 -0
- data/components/plugins/vector_feed.rb +38 -9
- data/components/reporters/plugin_formatters/html/metrics.rb +290 -0
- data/components/reporters/plugin_formatters/stdout/metrics.rb +80 -0
- data/components/reporters/plugin_formatters/xml/metrics.rb +29 -0
- data/components/reporters/stdout.rb +4 -2
- data/components/reporters/xml.rb +4 -4
- data/components/reporters/xml/schema.xsd +95 -0
- data/lib/arachni.rb +2 -0
- data/lib/arachni/browser.rb +132 -77
- data/lib/arachni/browser/javascript.rb +173 -45
- data/lib/arachni/browser/javascript/scripts/dom_monitor.js +81 -6
- data/lib/arachni/browser/javascript/scripts/taint_tracer.js +31 -3
- data/lib/arachni/browser_cluster.rb +41 -15
- data/lib/arachni/browser_cluster/job.rb +4 -0
- data/lib/arachni/browser_cluster/jobs/resource_exploration.rb +0 -9
- data/lib/arachni/browser_cluster/worker.rb +8 -5
- data/lib/arachni/check/auditor.rb +20 -8
- data/lib/arachni/check/base.rb +38 -6
- data/lib/arachni/element/base.rb +18 -1
- data/lib/arachni/element/capabilities/analyzable/differential.rb +0 -1
- data/lib/arachni/element/capabilities/analyzable/taint.rb +40 -10
- data/lib/arachni/element/capabilities/analyzable/timeout.rb +27 -23
- data/lib/arachni/element/capabilities/auditable/dom.rb +22 -0
- data/lib/arachni/element/capabilities/inputtable.rb +6 -2
- data/lib/arachni/element/capabilities/submittable.rb +1 -1
- data/lib/arachni/element/cookie.rb +37 -23
- data/lib/arachni/element/cookie/capabilities/mutable.rb +6 -6
- data/lib/arachni/element/cookie/dom.rb +0 -8
- data/lib/arachni/element/form.rb +28 -14
- data/lib/arachni/element/form/capabilities/auditable.rb +2 -2
- data/lib/arachni/element/form/capabilities/mutable.rb +5 -5
- data/lib/arachni/element/form/dom.rb +0 -8
- data/lib/arachni/element/generic_dom.rb +1 -1
- data/lib/arachni/element/json.rb +2 -1
- data/lib/arachni/element/json/capabilities/inputtable.rb +6 -6
- data/lib/arachni/element/json/capabilities/mutable.rb +1 -1
- data/lib/arachni/element/link.rb +13 -16
- data/lib/arachni/element/link/dom.rb +1 -14
- data/lib/arachni/element/link_template.rb +3 -2
- data/lib/arachni/element/link_template/dom.rb +0 -16
- data/lib/arachni/element/server.rb +51 -9
- data/lib/arachni/element/xml.rb +1 -0
- data/lib/arachni/ethon/easy.rb +4 -1
- data/lib/arachni/framework/parts/audit.rb +26 -77
- data/lib/arachni/framework/parts/browser.rb +50 -55
- data/lib/arachni/framework/parts/check.rb +4 -3
- data/lib/arachni/framework/parts/data.rb +41 -6
- data/lib/arachni/framework/parts/state.rb +16 -7
- data/lib/arachni/http/client.rb +66 -38
- data/lib/arachni/http/client/dynamic_404_handler.rb +46 -14
- data/lib/arachni/http/headers.rb +22 -10
- data/lib/arachni/http/proxy_server.rb +67 -22
- data/lib/arachni/http/proxy_server/ssl-interceptor-cacert.pem +34 -0
- data/lib/arachni/http/proxy_server/ssl-interceptor-cakey.pem +51 -0
- data/lib/arachni/http/request.rb +71 -18
- data/lib/arachni/issue.rb +17 -3
- data/lib/arachni/option_groups/browser_cluster.rb +34 -1
- data/lib/arachni/option_groups/http.rb +1 -1
- data/lib/arachni/page.rb +26 -13
- data/lib/arachni/page/dom/transition.rb +2 -2
- data/lib/arachni/parser.rb +28 -11
- data/lib/arachni/platform/fingerprinter.rb +5 -0
- data/lib/arachni/platform/manager.rb +65 -32
- data/lib/arachni/plugin/base.rb +8 -0
- data/lib/arachni/processes/instances.rb +25 -11
- data/lib/arachni/reporter/manager.rb +2 -2
- data/lib/arachni/rpc/client/instance.rb +4 -0
- data/lib/arachni/rpc/server/framework/master.rb +3 -3
- data/lib/arachni/rpc/server/framework/multi_instance.rb +0 -8
- data/lib/arachni/rpc/server/instance.rb +2 -1
- data/lib/arachni/ruby/array.rb +5 -0
- data/lib/arachni/ruby/hash.rb +5 -0
- data/lib/arachni/ruby/string.rb +2 -3
- data/lib/arachni/session.rb +32 -6
- data/lib/arachni/state/framework.rb +6 -2
- data/lib/arachni/support/cache.rb +1 -0
- data/lib/arachni/support/cache/base.rb +12 -8
- data/lib/arachni/support/cache/least_recently_pushed.rb +29 -0
- data/lib/arachni/support/cache/least_recently_used.rb +5 -8
- data/lib/arachni/support/cache/preference.rb +1 -1
- data/lib/arachni/support/cache/random_replacement.rb +1 -25
- data/lib/arachni/support/database/queue.rb +21 -8
- data/lib/arachni/support/lookup/base.rb +7 -1
- data/lib/arachni/support/mixins/observable.rb +3 -1
- data/lib/arachni/support/profiler.rb +51 -10
- data/lib/arachni/support/signature.rb +11 -2
- data/lib/arachni/trainer.rb +8 -2
- data/lib/arachni/uri.rb +28 -25
- data/lib/arachni/uri/scope.rb +1 -1
- data/lib/arachni/utilities.rb +8 -0
- data/lib/arachni/watir/element.rb +1 -1
- data/lib/version +1 -1
- data/spec/arachni/browser/javascript/dom_monitor_spec.rb +388 -53
- data/spec/arachni/browser/javascript/taint_tracer_spec.rb +41 -0
- data/spec/arachni/browser/javascript_spec.rb +235 -61
- data/spec/arachni/browser_cluster/jobs/resource_exploration_spec.rb +0 -9
- data/spec/arachni/browser_cluster_spec.rb +58 -10
- data/spec/arachni/browser_spec.rb +170 -26
- data/spec/arachni/check/auditor_spec.rb +22 -3
- data/spec/arachni/check/base_spec.rb +84 -0
- data/spec/arachni/element/body_spec.rb +1 -1
- data/spec/arachni/element/capabilities/analyzable/taint_spec.rb +3 -3
- data/spec/arachni/element/capabilities/analyzable/timeout_spec.rb +1 -1
- data/spec/arachni/element/cookie/dom_spec.rb +0 -9
- data/spec/arachni/element/cookie_spec.rb +85 -0
- data/spec/arachni/element/form/dom_spec.rb +0 -9
- data/spec/arachni/element/form_spec.rb +46 -3
- data/spec/arachni/element/json_spec.rb +20 -0
- data/spec/arachni/element/link/dom_spec.rb +0 -9
- data/spec/arachni/element/link_spec.rb +40 -15
- data/spec/arachni/element/link_template/dom_spec.rb +0 -8
- data/spec/arachni/element/link_template_spec.rb +2 -6
- data/spec/arachni/element/server_spec.rb +94 -8
- data/spec/arachni/element/xml_spec.rb +20 -0
- data/spec/arachni/framework/parts/audit_spec.rb +12 -14
- data/spec/arachni/framework/parts/browser_spec.rb +0 -171
- data/spec/arachni/framework/parts/platform_spec.rb +14 -8
- data/spec/arachni/framework/parts/report_spec.rb +1 -1
- data/spec/arachni/framework/parts/state_spec.rb +0 -9
- data/spec/arachni/http/client/dynamic_404_handlers_spec.rb +19 -0
- data/spec/arachni/http/client_spec.rb +169 -42
- data/spec/arachni/http/headers_spec.rb +18 -0
- data/spec/arachni/http/request_spec.rb +23 -0
- data/spec/arachni/issue_spec.rb +17 -6
- data/spec/arachni/page_spec.rb +22 -2
- data/spec/arachni/parser_spec.rb +5 -0
- data/spec/arachni/platform/manager_spec.rb +57 -25
- data/spec/arachni/reporter/manager_spec.rb +26 -0
- data/spec/arachni/rpc/server/active_options_spec.rb +9 -4
- data/spec/arachni/state/framework_spec.rb +2 -8
- data/spec/arachni/support/cache/least_recently_pushed_spec.rb +90 -0
- data/spec/arachni/support/cache/least_recently_used_spec.rb +5 -13
- data/spec/arachni/support/database/queue_spec.rb +7 -0
- data/spec/arachni/support/mixins/observable_spec.rb +15 -1
- data/spec/arachni/trainer_spec.rb +2 -2
- data/spec/components/checks/active/code_injection_timing_spec.rb +1 -1
- data/spec/components/checks/active/file_inclusion_spec.rb +6 -6
- data/spec/components/checks/active/path_traversal_spec.rb +2 -2
- data/spec/components/checks/active/source_code_disclosure_spec.rb +2 -2
- data/spec/components/checks/active/unvalidated_redirect_spec.rb +6 -6
- data/spec/components/checks/active/xss_dom_inputs_spec.rb +3 -5
- data/spec/components/checks/active/xss_dom_script_context_spec.rb +1 -1
- data/spec/components/checks/active/xss_spec.rb +5 -5
- data/spec/components/checks/passive/common_admin_interfaces_spec.rb +15 -0
- data/spec/components/checks/passive/interesting_responses_spec.rb +14 -1
- data/spec/components/fingerprinters/frameworks/aspx_mvc_spec.rb +31 -0
- data/spec/components/fingerprinters/frameworks/cakephp_spec.rb +22 -0
- data/spec/components/fingerprinters/frameworks/cherrypy_spec.rb +28 -0
- data/spec/components/fingerprinters/frameworks/django_spec.rb +37 -0
- data/spec/components/fingerprinters/frameworks/jsf_spec.rb +27 -0
- data/spec/components/fingerprinters/frameworks/rack_spec.rb +11 -14
- data/spec/components/fingerprinters/frameworks/rails_spec.rb +53 -0
- data/spec/components/fingerprinters/languages/asp_spec.rb +7 -9
- data/spec/components/fingerprinters/languages/aspx_spec.rb +10 -24
- data/spec/components/fingerprinters/languages/java_spec.rb +88 -0
- data/spec/components/fingerprinters/languages/php_spec.rb +19 -12
- data/spec/components/fingerprinters/languages/python_spec.rb +22 -9
- data/spec/components/fingerprinters/languages/ruby.rb +6 -4
- data/spec/components/fingerprinters/os/bsd_spec.rb +6 -4
- data/spec/components/fingerprinters/os/linux_spec.rb +6 -4
- data/spec/components/fingerprinters/os/solaris_spec.rb +6 -4
- data/spec/components/fingerprinters/os/unix_spec.rb +6 -4
- data/spec/components/fingerprinters/os/windows_spec.rb +6 -4
- data/spec/components/fingerprinters/servers/apache_spec.rb +15 -4
- data/spec/components/fingerprinters/servers/gunicorn_spec.rb +28 -0
- data/spec/components/fingerprinters/servers/iis_spec.rb +6 -6
- data/spec/components/fingerprinters/servers/jetty_spec.rb +6 -6
- data/spec/components/fingerprinters/servers/nginx_spec.rb +6 -4
- data/spec/components/fingerprinters/servers/tomcat_spec.rb +15 -6
- data/spec/components/path_extractors/data_url_spec.rb +19 -0
- data/spec/components/plugins/autologin_spec.rb +23 -0
- data/spec/components/plugins/login_script_spec.rb +112 -24
- data/spec/components/plugins/restrict_to_dom_state_spec.rb +16 -0
- data/spec/components/plugins/vector_feed_spec.rb +39 -1
- data/spec/support/factories/page/dom.rb +9 -4
- data/spec/support/factories/page/dom/transition.rb +31 -9
- data/spec/support/factories/scan_report.rb +8 -6
- data/spec/support/fixtures/empty/placeholder +0 -0
- data/spec/support/fixtures/report.afr +0 -0
- data/spec/support/fixtures/reporters/manager_spec/error.rb +18 -0
- data/spec/support/servers/arachni/browser.rb +117 -11
- data/spec/support/servers/arachni/browser/javascript/dom_monitor.rb +148 -4
- data/spec/support/servers/arachni/check/auditor.rb +4 -0
- data/spec/support/servers/arachni/element/cookie/cookie_dom.rb +1 -1
- data/spec/support/servers/arachni/http/client.rb +5 -0
- data/spec/support/servers/arachni/http/client/dynamic_404_handler.rb +13 -0
- data/spec/support/servers/checks/active/code_injection_timing.rb +1 -1
- data/spec/support/servers/checks/active/file_inclusion.rb +2 -2
- data/spec/support/servers/checks/active/path_traversal.rb +2 -2
- data/spec/support/servers/checks/active/source_code_disclosure.rb +40 -33
- data/spec/support/servers/checks/active/trainer_check.rb +9 -10
- data/spec/support/servers/checks/active/unvalidated_redirect_dom.rb +7 -4
- data/spec/support/servers/checks/active/xss.rb +35 -0
- data/spec/support/servers/checks/active/xss_dom.rb +1 -1
- data/spec/support/servers/checks/active/xss_dom_inputs.rb +24 -0
- data/spec/support/servers/checks/active/xss_dom_script_context.rb +1 -1
- data/spec/support/servers/checks/passive/common_admin_interfaces.rb +6 -0
- data/spec/support/servers/plugins/autologin.rb +9 -0
- data/spec/support/servers/plugins/restrict_to_dom_state.rb +4 -0
- data/spec/support/shared/element/base.rb +42 -0
- data/spec/support/shared/element/capabilities/auditable.rb +4 -4
- data/spec/support/shared/element/capabilities/auditable/dom.rb +26 -0
- data/spec/support/shared/element/capabilities/inputtable.rb +16 -11
- data/spec/support/shared/element/capabilities/submitable.rb +7 -2
- data/spec/support/shared/fingerprinter.rb +8 -0
- data/spec/support/shared/path_extractor.rb +1 -1
- data/ui/cli/framework.rb +3 -3
- data/ui/cli/framework/option_parser.rb +9 -0
- data/ui/cli/output.rb +9 -0
- data/ui/cli/reporter.rb +5 -2
- data/ui/cli/utilities.rb +4 -2
- metadata +76 -17
- data/lib/arachni/http/proxy_server/ssl-interceptor-cert.pem +0 -34
- data/lib/arachni/http/proxy_server/ssl-interceptor-pkey.pem +0 -51
- data/spec/components/fingerprinters/languages/jsp_spec.rb +0 -56
@@ -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
|