arachni 1.0.1 → 1.0.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 +21 -0
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/components/checks/active/code_injection_php_input_wrapper.rb +3 -6
- data/components/checks/active/file_inclusion.rb +3 -6
- data/components/checks/active/path_traversal.rb +3 -6
- data/components/checks/active/source_code_disclosure.rb +3 -6
- data/components/checks/active/xss_dom_inputs.rb +5 -3
- data/lib/arachni/browser.rb +1 -0
- data/lib/arachni/browser_cluster.rb +6 -0
- data/lib/arachni/browser_cluster/jobs/browser_provider.rb +4 -0
- data/lib/arachni/browser_cluster/jobs/resource_exploration.rb +4 -0
- data/lib/arachni/browser_cluster/jobs/resource_exploration/event_trigger.rb +5 -0
- data/lib/arachni/browser_cluster/jobs/resource_exploration/result.rb +6 -0
- data/lib/arachni/browser_cluster/jobs/taint_trace.rb +5 -0
- data/lib/arachni/browser_cluster/jobs/taint_trace/event_trigger.rb +6 -0
- data/lib/arachni/browser_cluster/worker.rb +5 -1
- data/lib/arachni/element/capabilities/auditable/dom.rb +1 -1
- data/lib/arachni/element/capabilities/with_auditor/output.rb +1 -1
- data/lib/arachni/element/form.rb +15 -0
- data/lib/arachni/page.rb +4 -0
- data/lib/arachni/page/dom.rb +22 -5
- data/lib/arachni/report.rb +13 -7
- data/lib/arachni/state/audit.rb +1 -1
- data/lib/arachni/support/profiler.rb +46 -17
- data/lib/arachni/ui/foo/output.rb +5 -0
- data/lib/version +1 -1
- data/spec/arachni/element/form_spec.rb +30 -0
- data/spec/arachni/report_spec.rb +8 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f1ab8801aa396dbd2a6aa10c911a91777b046542
|
4
|
+
data.tar.gz: 2251a40388dec9fc771bc8aa51ddc7680bb4f825
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ccf69071cb3b2ddb1d880041979ac24d8d2f0d61662eadae5ad77544cbd226d47aa746e8505022d03b466290bece49410efc61957d0fc3fbd9359e5361d0b198
|
7
|
+
data.tar.gz: 8d3f66447ef08172a43b29605b1f611131a0565a06ba70c706ee199d191043ee78c93b1eb8bef80d95e7215950e54a1ad3d650e3d6d440cc9fb5ab2babbb21f1
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# ChangeLog
|
2
2
|
|
3
|
+
## 1.0.2 _(September 13, 2014)_
|
4
|
+
|
5
|
+
- `UI::Output` -- Updated null output interface with placeholder debugging methods.
|
6
|
+
- `Browser`
|
7
|
+
- Updated to catch exception when trying to manipulate read-only inputs.
|
8
|
+
- `BrowserCluster`
|
9
|
+
- Added debugging messages for job processing.
|
10
|
+
- `Worker`
|
11
|
+
- `#run_job` -- Clear the `@window_responses` cache after each job in
|
12
|
+
addition to after each browser re-spawn.
|
13
|
+
- `Form`
|
14
|
+
- `#audit` -- `:each_mutation` callback now ignores `#mutation_with_original_values`
|
15
|
+
and `#mutation_with_sample_values`.
|
16
|
+
- Checks
|
17
|
+
- Active
|
18
|
+
- `xss_dom_inputs` -- Ignore out-of-scope browser pages.
|
19
|
+
- `code_injection_php_input_wrapper` -- Cleaned up `:each_mutation` callback.
|
20
|
+
- `file_inclusion` -- Cleaned up `:each_mutation` callback.
|
21
|
+
- `path_traversal` -- Cleaned up `:each_mutation` callback.
|
22
|
+
- `source_code_disclosure` -- Cleaned up `:each_mutation` callback.
|
23
|
+
|
3
24
|
## 1.0.1 _(September 7, 2014)_
|
4
25
|
|
5
26
|
- `RPC::Server::Dispatcher`
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
=end
|
8
8
|
|
9
9
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
10
|
-
# @version 0.1.
|
10
|
+
# @version 0.1.2
|
11
11
|
# @see OWASP https://www.owasp.org/index.php/Top_10_2007-Malicious_File_Execution
|
12
12
|
class Arachni::Checks::CodeInjectionPhpInputWrapper < Arachni::Check::Base
|
13
13
|
|
@@ -20,10 +20,7 @@ class Arachni::Checks::CodeInjectionPhpInputWrapper < Arachni::Check::Base
|
|
20
20
|
# Add one more mutation (on the fly) which will include the extension
|
21
21
|
# of the original value (if that value was a filename) after a null byte.
|
22
22
|
each_mutation: proc do |mutation|
|
23
|
-
next if !mutation.affected_input_value
|
24
|
-
(mutation.is_a?( Arachni::Form ) &&
|
25
|
-
(mutation.mutation_with_original_values? ||
|
26
|
-
mutation.mutation_with_sample_values?))
|
23
|
+
next if !mutation.affected_input_value
|
27
24
|
|
28
25
|
# Don't bother if the current element type can't carry nulls.
|
29
26
|
next if !mutation.valid_input_value_data?( "\0" )
|
@@ -56,7 +53,7 @@ to try and load it.
|
|
56
53
|
},
|
57
54
|
elements: [ Element::Form, Element::Link, Element::Cookie, Element::Header ],
|
58
55
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com> ',
|
59
|
-
version: '0.1.
|
56
|
+
version: '0.1.2',
|
60
57
|
platforms: [:php],
|
61
58
|
|
62
59
|
issue: {
|
@@ -9,7 +9,7 @@
|
|
9
9
|
# File inclusion check.
|
10
10
|
#
|
11
11
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
12
|
-
# @version 0.1.
|
12
|
+
# @version 0.1.3
|
13
13
|
#
|
14
14
|
# @see http://cwe.mitre.org/data/definitions/98.html
|
15
15
|
# @see https://www.owasp.org/index.php/PHP_File_Inclusion
|
@@ -50,10 +50,7 @@ class Arachni::Checks::FileInclusion < Arachni::Check::Base
|
|
50
50
|
# Add one more mutation (on the fly) which will include the extension
|
51
51
|
# of the original value (if that value was a filename) after a null byte.
|
52
52
|
each_mutation: proc do |mutation|
|
53
|
-
next if !mutation.affected_input_value
|
54
|
-
(mutation.is_a?( Arachni::Form ) &&
|
55
|
-
(mutation.mutation_with_original_values? ||
|
56
|
-
mutation.mutation_with_sample_values?))
|
53
|
+
next if !mutation.affected_input_value
|
57
54
|
|
58
55
|
# Don't bother if the current element type can't carry nulls.
|
59
56
|
next if !mutation.valid_input_value_data?( "\0" )
|
@@ -105,7 +102,7 @@ content or errors in the HTTP response body.
|
|
105
102
|
elements: [ Element::Form, Element::Link, Element::Cookie,
|
106
103
|
Element::Header, Element::LinkTemplate ],
|
107
104
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com> ',
|
108
|
-
version: '0.1.
|
105
|
+
version: '0.1.3',
|
109
106
|
platforms: options[:regexp].keys,
|
110
107
|
|
111
108
|
issue: {
|
@@ -9,7 +9,7 @@
|
|
9
9
|
# Path Traversal check.
|
10
10
|
#
|
11
11
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
12
|
-
# @version 0.4.
|
12
|
+
# @version 0.4.3
|
13
13
|
#
|
14
14
|
# @see http://cwe.mitre.org/data/definitions/22.html
|
15
15
|
# @see http://www.owasp.org/index.php/Path_Traversal
|
@@ -39,10 +39,7 @@ class Arachni::Checks::PathTraversal < Arachni::Check::Base
|
|
39
39
|
# Add one more mutation (on the fly) which will include the extension
|
40
40
|
# of the original value (if that value was a filename) after a null byte.
|
41
41
|
each_mutation: proc do |mutation|
|
42
|
-
next if !mutation.affected_input_value
|
43
|
-
(mutation.is_a?( Arachni::Form ) &&
|
44
|
-
(mutation.mutation_with_original_values? ||
|
45
|
-
mutation.mutation_with_sample_values?))
|
42
|
+
next if !mutation.affected_input_value
|
46
43
|
|
47
44
|
# Don't bother if the current element type can't carry nulls.
|
48
45
|
next if !mutation.valid_input_value_data?( "\0" )
|
@@ -115,7 +112,7 @@ of relevant content in the HTML responses.
|
|
115
112
|
elements: [ Element::Form, Element::Link, Element::Cookie,
|
116
113
|
Element::Header, Element::LinkTemplate ],
|
117
114
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com> ',
|
118
|
-
version: '0.4.
|
115
|
+
version: '0.4.3',
|
119
116
|
platforms: payloads.keys,
|
120
117
|
|
121
118
|
issue: {
|
@@ -12,7 +12,7 @@
|
|
12
12
|
#
|
13
13
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
14
14
|
#
|
15
|
-
# @version 0.2
|
15
|
+
# @version 0.2.1
|
16
16
|
#
|
17
17
|
# @see http://cwe.mitre.org/data/definitions/540.html
|
18
18
|
class Arachni::Checks::SourceCodeDisclosure < Arachni::Check::Base
|
@@ -39,10 +39,7 @@ class Arachni::Checks::SourceCodeDisclosure < Arachni::Check::Base
|
|
39
39
|
# Add one more mutation (on the fly) which will include the extension
|
40
40
|
# of the original value (if that value was a filename) after a null byte.
|
41
41
|
each_mutation: proc do |mutation|
|
42
|
-
next if !mutation.affected_input_value
|
43
|
-
(mutation.is_a?( Arachni::Form ) &&
|
44
|
-
(mutation.mutation_with_original_values? ||
|
45
|
-
mutation.mutation_with_sample_values?))
|
42
|
+
next if !mutation.affected_input_value
|
46
43
|
|
47
44
|
# Don't bother if the current element type can't carry nulls.
|
48
45
|
next if !mutation.valid_input_value_data?( "\0" )
|
@@ -122,7 +119,7 @@ source code.
|
|
122
119
|
elements: [ Element::Form, Element::Link, Element::Cookie,
|
123
120
|
Element::Header, Element::LinkTemplate ],
|
124
121
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
|
125
|
-
version: '0.2',
|
122
|
+
version: '0.2.1',
|
126
123
|
platforms: options[:regexp].keys,
|
127
124
|
|
128
125
|
issue: {
|
@@ -7,7 +7,7 @@
|
|
7
7
|
=end
|
8
8
|
|
9
9
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
10
|
-
# @version 0.1
|
10
|
+
# @version 0.1.1
|
11
11
|
class Arachni::Checks::XssDomInputs < Arachni::Check::Base
|
12
12
|
|
13
13
|
INPUTS = Set.new([:input, :textarea])
|
@@ -41,7 +41,9 @@ class Arachni::Checks::XssDomInputs < Arachni::Check::Base
|
|
41
41
|
transition = b.fire_event( locator, event, value: self.tag )
|
42
42
|
next if !transition
|
43
43
|
|
44
|
-
|
44
|
+
# Page may be out of scope, some sort of JS redirection.
|
45
|
+
next if !(p = b.to_page)
|
46
|
+
|
45
47
|
p.dom.transitions << transition
|
46
48
|
|
47
49
|
check_and_log p
|
@@ -77,7 +79,7 @@ Injects an HTML element into page text fields, triggers their associated events
|
|
77
79
|
and inspects the DOM for proof of vulnerability.
|
78
80
|
},
|
79
81
|
author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
|
80
|
-
version: '0.1',
|
82
|
+
version: '0.1.1',
|
81
83
|
elements: [Element::GenericDOM],
|
82
84
|
|
83
85
|
issue: {
|
data/lib/arachni/browser.rb
CHANGED
@@ -883,6 +883,7 @@ class Browser
|
|
883
883
|
input.set( value.to_s )
|
884
884
|
# Disabled inputs and such...
|
885
885
|
rescue Watir::Exception::ObjectDisabledException,
|
886
|
+
Watir::Exception::ObjectReadOnlyException,
|
886
887
|
Selenium::WebDriver::Error::InvalidElementStateError => e
|
887
888
|
print_debug_level_2 "Could not fill in form input '#{name_or_id}'" <<
|
888
889
|
" because: #{e} [#{e.class}"
|
@@ -150,6 +150,8 @@ class BrowserCluster
|
|
150
150
|
@done_signal.clear
|
151
151
|
|
152
152
|
synchronize do
|
153
|
+
print_debug "Queueing: #{job}"
|
154
|
+
|
153
155
|
@pending_job_counter += 1
|
154
156
|
@pending_jobs[job.id] += 1
|
155
157
|
@job_callbacks[job.id] = block if block
|
@@ -200,6 +202,8 @@ class BrowserCluster
|
|
200
202
|
# {Worker} states.
|
201
203
|
def job_done( job )
|
202
204
|
synchronize do
|
205
|
+
print_debug "Job done: #{job}"
|
206
|
+
|
203
207
|
if !job.never_ending?
|
204
208
|
@skip_states_per_job.delete job.id
|
205
209
|
@job_callbacks.delete job.id
|
@@ -241,6 +245,8 @@ class BrowserCluster
|
|
241
245
|
return if job_done? result.job
|
242
246
|
|
243
247
|
synchronize do
|
248
|
+
print_debug "Got job result: #{result}"
|
249
|
+
|
244
250
|
exception_jail( false ) do
|
245
251
|
@job_callbacks[result.job.id].call result
|
246
252
|
end
|
@@ -35,6 +35,11 @@ class EventTrigger < ResourceExploration
|
|
35
35
|
browser.trigger_event( resource, element, event )
|
36
36
|
end
|
37
37
|
|
38
|
+
def to_s
|
39
|
+
"#<#{self.class}:#{object_id} @resource=#{@resource} " +
|
40
|
+
"@event=#{@event.inspect} @element=#{@element.inspect}>"
|
41
|
+
end
|
42
|
+
|
38
43
|
end
|
39
44
|
|
40
45
|
end
|
@@ -13,8 +13,14 @@ class ResourceExploration
|
|
13
13
|
|
14
14
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
15
15
|
class Result < Job::Result
|
16
|
+
|
16
17
|
# @return [Page]
|
17
18
|
attr_accessor :page
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
"#<#{self.class}:#{object_id} @job=#{@job} @page=#{@page}>"
|
22
|
+
end
|
23
|
+
|
18
24
|
end
|
19
25
|
|
20
26
|
end
|
@@ -25,6 +25,12 @@ class EventTrigger < ResourceExploration::EventTrigger
|
|
25
25
|
super
|
26
26
|
end
|
27
27
|
|
28
|
+
def to_s
|
29
|
+
"#<#{self.class}:#{object_id} @resource=#{@resource} " +
|
30
|
+
"@event=#{@event.inspect} @element=#{@element.inspect} " +
|
31
|
+
"@forwarder=#{@forwarder}>"
|
32
|
+
end
|
33
|
+
|
28
34
|
end
|
29
35
|
|
30
36
|
end
|
@@ -78,6 +78,7 @@ class Worker < Arachni::Browser
|
|
78
78
|
# @see Arachni::Browser#trigger_events
|
79
79
|
def run_job( job )
|
80
80
|
@job = job
|
81
|
+
print_debug "Started: #{@job}"
|
81
82
|
|
82
83
|
# PhantomJS may have crashed (it happens sometimes) so make sure that
|
83
84
|
# we've got a live one before running the job.
|
@@ -94,7 +95,7 @@ class Worker < Arachni::Browser
|
|
94
95
|
end
|
95
96
|
end
|
96
97
|
rescue TimeoutError => e
|
97
|
-
print_debug "Job timed-out after #{@job_timeout} seconds: #{job}"
|
98
|
+
print_debug "Job timed-out after #{@job_timeout} seconds: #{@job}"
|
98
99
|
|
99
100
|
# Could have left us with a broken browser.
|
100
101
|
browser_respawn
|
@@ -110,6 +111,8 @@ class Worker < Arachni::Browser
|
|
110
111
|
decrease_time_to_live
|
111
112
|
browser_respawn_if_necessary
|
112
113
|
|
114
|
+
print_debug "Finished: #{@job}"
|
115
|
+
|
113
116
|
true
|
114
117
|
rescue Selenium::WebDriver::Error::WebDriverError
|
115
118
|
browser_respawn
|
@@ -122,6 +125,7 @@ class Worker < Arachni::Browser
|
|
122
125
|
@captured_pages.clear
|
123
126
|
@page_snapshots.clear
|
124
127
|
@page_snapshots_with_sinks.clear
|
128
|
+
@window_responses.clear
|
125
129
|
|
126
130
|
# The jobs may have configured callbacks to capture pages etc.,
|
127
131
|
# remove them.
|
@@ -12,7 +12,7 @@ module WithAuditor
|
|
12
12
|
|
13
13
|
# Delegate output related methods to the {WithAuditor#auditor}.
|
14
14
|
module Output
|
15
|
-
extend Forwardable
|
15
|
+
extend ::Forwardable
|
16
16
|
|
17
17
|
[ :debug?, :print_error, :print_status, :print_verbose, :print_info,
|
18
18
|
:print_line, :print_ok, :print_bad, :print_debug, :print_debug_backtrace,
|
data/lib/arachni/element/form.rb
CHANGED
@@ -490,6 +490,21 @@ class Form < Base
|
|
490
490
|
|
491
491
|
private
|
492
492
|
|
493
|
+
def audit_single( payload, opts = {}, &block )
|
494
|
+
opts = opts.dup
|
495
|
+
|
496
|
+
if (each_m = opts.delete(:each_mutation))
|
497
|
+
opts[:each_mutation] = proc do |mutation|
|
498
|
+
next if mutation.mutation_with_original_values? ||
|
499
|
+
mutation.mutation_with_sample_values?
|
500
|
+
|
501
|
+
each_m.call( mutation )
|
502
|
+
end
|
503
|
+
end
|
504
|
+
|
505
|
+
super( payload, opts, &block )
|
506
|
+
end
|
507
|
+
|
493
508
|
def skip?( elem )
|
494
509
|
if elem.mutation_with_original_values? || elem.mutation_with_sample_values?
|
495
510
|
id = elem.audit_id
|
data/lib/arachni/page.rb
CHANGED
data/lib/arachni/page/dom.rb
CHANGED
@@ -69,9 +69,16 @@ class DOM
|
|
69
69
|
@url = url.freeze
|
70
70
|
end
|
71
71
|
|
72
|
-
def digest=(
|
73
|
-
return @digest = nil if !
|
74
|
-
|
72
|
+
def digest=( d )
|
73
|
+
return @digest = nil if !d
|
74
|
+
|
75
|
+
if d.include?( url ) || d.include?( page.url )
|
76
|
+
d = d.dup
|
77
|
+
d.gsub!( url, '' )
|
78
|
+
d.gsub!( page.url, '' )
|
79
|
+
end
|
80
|
+
|
81
|
+
@digest = d.freeze
|
75
82
|
end
|
76
83
|
|
77
84
|
# @param [Transition] transition
|
@@ -198,6 +205,10 @@ class DOM
|
|
198
205
|
to_h
|
199
206
|
end
|
200
207
|
|
208
|
+
def to_s
|
209
|
+
"#<#{self.class}:#{object_id} @url=#{@url.inspect}>"
|
210
|
+
end
|
211
|
+
|
201
212
|
# @return [Hash]
|
202
213
|
# Data representing this instance that are suitable the RPC transmission.
|
203
214
|
def to_rpc_data
|
@@ -270,8 +281,14 @@ class DOM
|
|
270
281
|
protected
|
271
282
|
|
272
283
|
def digest_without_urls( other )
|
273
|
-
digest.
|
274
|
-
|
284
|
+
if !digest.include?( other.url ) && !digest.include?( other.page.url )
|
285
|
+
return digest
|
286
|
+
end
|
287
|
+
|
288
|
+
d = digest.dup
|
289
|
+
d.gsub!( other.url, '' )
|
290
|
+
d.gsub!( other.page.url, '' )
|
291
|
+
d
|
275
292
|
end
|
276
293
|
|
277
294
|
end
|
data/lib/arachni/report.rb
CHANGED
@@ -131,7 +131,7 @@ class Report
|
|
131
131
|
end
|
132
132
|
|
133
133
|
# @param [String] location
|
134
|
-
# Location for the dumped report file.
|
134
|
+
# Location for the {#to_afr dumped} report file.
|
135
135
|
#
|
136
136
|
# @return [String]
|
137
137
|
# Absolute location of the report.
|
@@ -144,15 +144,21 @@ class Report
|
|
144
144
|
location += "/#{default_filename}"
|
145
145
|
end
|
146
146
|
|
147
|
-
IO.binwrite( location,
|
147
|
+
IO.binwrite( location, to_afr )
|
148
148
|
|
149
|
-
|
149
|
+
File.expand_path( location )
|
150
|
+
end
|
151
|
+
|
152
|
+
# @return [String]
|
153
|
+
# Report serialized in the Arachni Framework Report format..
|
154
|
+
def to_afr
|
155
|
+
afr = RPC::Serializer.dump( self )
|
156
|
+
|
157
|
+
# Append metadata to the end of the dump.
|
150
158
|
metadata = RPC::Serializer.dump( summary )
|
151
|
-
|
152
|
-
f.write [metadata, metadata.size].pack( 'a*N' )
|
153
|
-
end
|
159
|
+
afr << [metadata, metadata.size].pack( 'a*N' )
|
154
160
|
|
155
|
-
|
161
|
+
afr
|
156
162
|
end
|
157
163
|
|
158
164
|
# @return [Hash]
|
data/lib/arachni/state/audit.rb
CHANGED
@@ -6,6 +6,7 @@
|
|
6
6
|
web site for more information on licensing and terms of use.
|
7
7
|
=end
|
8
8
|
|
9
|
+
require 'sys/proctable'
|
9
10
|
require 'ruby-mass'
|
10
11
|
require 'stackprof'
|
11
12
|
|
@@ -15,6 +16,22 @@ module Support
|
|
15
16
|
# @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
|
16
17
|
class Profiler
|
17
18
|
|
19
|
+
def self.write_samples_to_disk( file, options = {} )
|
20
|
+
profiler = Support::Profiler.new
|
21
|
+
|
22
|
+
Thread.new do
|
23
|
+
begin
|
24
|
+
loop do
|
25
|
+
profiler.write_object_space( file, options )
|
26
|
+
sleep options[:interval] || 1
|
27
|
+
end
|
28
|
+
rescue => e
|
29
|
+
ap e
|
30
|
+
ap e.backtrace
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
18
35
|
def trace_allocations
|
19
36
|
require 'objspace'
|
20
37
|
ObjectSpace.trace_object_allocations_start
|
@@ -60,26 +77,19 @@ class Profiler
|
|
60
77
|
ap find_references( o )
|
61
78
|
end
|
62
79
|
|
63
|
-
def
|
64
|
-
klass
|
65
|
-
namespaces
|
66
|
-
|
67
|
-
with_references = options[:with_references]
|
68
|
-
with_dependencies = options[:with_dependencies]
|
69
|
-
max_entries = options[:max_entries] || 50
|
80
|
+
def object_space( options = {} )
|
81
|
+
klass = options[:class]
|
82
|
+
namespaces = options[:namespaces] || [Arachni]
|
83
|
+
max_entries = options[:max_entries] || 50
|
70
84
|
|
71
85
|
object_space = Hash.new(0)
|
72
86
|
@object_space ||= Hash.new(0)
|
73
87
|
|
74
88
|
ObjectSpace.each_object do |o|
|
75
|
-
next if o.class != klass
|
76
|
-
|
77
|
-
print_object_allocations( o ) if with_allocation_info
|
78
|
-
print_references( o ) if with_references
|
79
|
-
print_dependencies( o ) if with_dependencies
|
80
|
-
|
89
|
+
next if o.class != klass && !object_within_namespace?( o, namespaces )
|
81
90
|
object_space[o.class] += 1
|
82
91
|
end
|
92
|
+
|
83
93
|
object_space = Hash[object_space.sort_by { |_, v| v }.reverse[0..max_entries]]
|
84
94
|
|
85
95
|
with_deltas = object_space.dup
|
@@ -91,9 +101,30 @@ class Profiler
|
|
91
101
|
end
|
92
102
|
end
|
93
103
|
|
94
|
-
ap with_deltas
|
95
|
-
|
96
104
|
@object_space = object_space.dup
|
105
|
+
with_deltas
|
106
|
+
end
|
107
|
+
|
108
|
+
def write_object_space( file, options = {} )
|
109
|
+
consumption = resource_consumption
|
110
|
+
|
111
|
+
str = "RAM: #{consumption[:memory_usage].round(3)}MB"
|
112
|
+
str << " (#{consumption[:memory_utilization]}%)"
|
113
|
+
str << " - CPU: #{consumption[:cpu_utilization]}%\n\n"
|
114
|
+
|
115
|
+
os = object_space( options )
|
116
|
+
maxsize = os.keys.map(&:to_s).map(&:size).sort.reverse.first
|
117
|
+
|
118
|
+
os.each do |klass, info|
|
119
|
+
offset = maxsize - klass.to_s.size
|
120
|
+
str << "#{klass}: #{' ' * offset}#{info}\n"
|
121
|
+
end
|
122
|
+
|
123
|
+
IO.write( file, str )
|
124
|
+
end
|
125
|
+
|
126
|
+
def print_object_space( options = {} )
|
127
|
+
ap object_space( options )
|
97
128
|
end
|
98
129
|
|
99
130
|
def count_objects( klass )
|
@@ -101,8 +132,6 @@ class Profiler
|
|
101
132
|
end
|
102
133
|
|
103
134
|
def resource_consumption
|
104
|
-
require 'sys/proctable'
|
105
|
-
|
106
135
|
procinfo = ::Sys::ProcTable.ps( Process.pid )
|
107
136
|
{
|
108
137
|
cpu_utilization: procinfo[:pctcpu],
|
data/lib/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.2
|
@@ -101,6 +101,36 @@ describe Arachni::Element::Form do
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
+
describe '#audit' do
|
105
|
+
describe :each_mutation do
|
106
|
+
it 'ignores #mutation_with_original_values' do
|
107
|
+
had_mutation_with_original_values = false
|
108
|
+
each_mutation = proc do |mutation|
|
109
|
+
had_mutation_with_original_values ||=
|
110
|
+
mutation.mutation_with_original_values?
|
111
|
+
end
|
112
|
+
|
113
|
+
subject.audit( 'stuff', each_mutation: each_mutation ) {}
|
114
|
+
subject.http.run
|
115
|
+
|
116
|
+
had_mutation_with_original_values.should be_false
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'ignores mutation_with_sample_values' do
|
120
|
+
had_mutation_with_sample_values = false
|
121
|
+
each_mutation = proc do |mutation|
|
122
|
+
had_mutation_with_sample_values ||=
|
123
|
+
mutation.mutation_with_sample_values?
|
124
|
+
end
|
125
|
+
|
126
|
+
subject.audit( 'stuff', each_mutation: each_mutation ) {}
|
127
|
+
subject.http.run
|
128
|
+
|
129
|
+
had_mutation_with_sample_values.should be_false
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
104
134
|
describe '#name_or_id' do
|
105
135
|
context 'when a #name is available' do
|
106
136
|
it 'returns it' do
|
data/spec/arachni/report_spec.rb
CHANGED
@@ -221,6 +221,14 @@ describe Arachni::Report do
|
|
221
221
|
end
|
222
222
|
end
|
223
223
|
|
224
|
+
describe '#to_afr' do
|
225
|
+
it 'returns the object in AFR format' do
|
226
|
+
@report_file = report.save
|
227
|
+
|
228
|
+
IO.binread( @report_file ).should == report.to_afr
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
224
232
|
describe '#to_h' do
|
225
233
|
it 'returns the object as a hash' do
|
226
234
|
report.to_h.should == {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arachni
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tasos Laskos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|