arachni 1.0 → 1.0.1
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 +47 -0
- data/README.md +2 -2
- data/arachni.gemspec +1 -1
- data/components/checks/active/code_injection_php_input_wrapper.rb +8 -3
- data/components/checks/active/file_inclusion.rb +7 -3
- data/components/checks/active/path_traversal.rb +7 -3
- data/components/checks/passive/grep/cookie_set_for_parent_domain.rb +5 -3
- data/components/plugins/cookie_collector.rb +1 -1
- data/components/plugins/proxy.rb +4 -3
- data/components/plugins/vector_feed.rb +1 -1
- data/components/reporters/html/default/issue.erb +5 -0
- data/components/reporters/stdout.rb +4 -0
- data/lib/arachni/browser.rb +25 -6
- data/lib/arachni/browser/element_locator.rb +1 -1
- data/lib/arachni/browser/javascript/taint_tracer.rb +3 -3
- data/lib/arachni/browser/javascript/taint_tracer/frame.rb +1 -1
- data/lib/arachni/browser/javascript/taint_tracer/frame/called_function.rb +1 -1
- data/lib/arachni/browser/javascript/taint_tracer/sink/base.rb +1 -1
- data/lib/arachni/check/auditor.rb +2 -0
- data/lib/arachni/component/manager.rb +2 -2
- data/lib/arachni/component/options/base.rb +2 -2
- data/lib/arachni/element/base.rb +2 -2
- data/lib/arachni/element/cookie.rb +4 -4
- data/lib/arachni/element/form.rb +1 -1
- data/lib/arachni/element/generic_dom.rb +1 -1
- data/lib/arachni/framework.rb +9 -1
- data/lib/arachni/http/client.rb +2 -0
- data/lib/arachni/http/request.rb +2 -2
- data/lib/arachni/http/response.rb +1 -1
- data/lib/arachni/issue.rb +2 -2
- data/lib/arachni/option_group.rb +1 -1
- data/lib/arachni/option_groups/input.rb +1 -1
- data/lib/arachni/option_groups/scope.rb +1 -1
- data/lib/arachni/page.rb +1 -1
- data/lib/arachni/page/dom/transition.rb +3 -3
- data/lib/arachni/parser.rb +3 -1
- data/lib/arachni/platform/list.rb +1 -1
- data/lib/arachni/report.rb +1 -1
- data/lib/arachni/rpc/client/instance/framework.rb +6 -6
- data/lib/arachni/rpc/client/instance/service.rb +7 -7
- data/lib/arachni/rpc/server/dispatcher.rb +18 -5
- data/lib/arachni/rpc/server/dispatcher/node.rb +13 -6
- data/lib/arachni/rpc/server/framework/distributor.rb +1 -1
- data/lib/arachni/rpc/server/framework/master.rb +1 -1
- data/lib/arachni/rpc/server/framework/multi_instance.rb +2 -2
- data/lib/arachni/rpc/server/instance.rb +11 -3
- data/lib/arachni/ruby/hash.rb +7 -6
- data/lib/arachni/state/framework.rb +1 -0
- data/lib/version +1 -1
- data/spec/arachni/browser_spec.rb +25 -0
- data/spec/arachni/component/manager_spec.rb +1 -1
- data/spec/arachni/element/cookie_spec.rb +3 -3
- data/spec/arachni/http/request_spec.rb +3 -3
- data/spec/arachni/option_groups/scope_spec.rb +2 -2
- data/spec/arachni/parser_spec.rb +7 -0
- data/spec/arachni/reporter/manager_spec.rb +1 -1
- data/spec/arachni/rpc/server/dispatcher/node_spec.rb +2 -0
- data/spec/arachni/rpc/server/framework_spec.rb +1 -1
- data/spec/arachni/ruby/hash_spec.rb +8 -8
- data/spec/support/servers/checks/passive/grep/cookie_set_for_parent_domain.rb +1 -1
- data/spec/support/shared/element/capabilities/inputtable.rb +2 -2
- data/ui/cli/utilities.rb +3 -0
- metadata +4 -4
@@ -69,7 +69,7 @@ module Master
|
|
69
69
|
return false
|
70
70
|
end
|
71
71
|
|
72
|
-
instance_info = instance_info.
|
72
|
+
instance_info = instance_info.my_symbolize_keys
|
73
73
|
|
74
74
|
fail "Instance info does not contain a 'url' key." if !instance_info[:url]
|
75
75
|
fail "Instance info does not contain a 'token' key." if !instance_info[:token]
|
@@ -86,7 +86,7 @@ module MultiInstance
|
|
86
86
|
# @return [Hash]
|
87
87
|
# Progress data.
|
88
88
|
def progress( opts = {}, &block )
|
89
|
-
opts = opts.
|
89
|
+
opts = opts.my_symbolize_keys
|
90
90
|
|
91
91
|
include_statistics = opts[:statistics].nil? ? true : opts[:statistics]
|
92
92
|
include_slaves = opts[:slaves].nil? ? true : opts[:slaves]
|
@@ -153,7 +153,7 @@ module MultiInstance
|
|
153
153
|
slave_data.compact!
|
154
154
|
|
155
155
|
slave_data.each do |slave|
|
156
|
-
slave = slave.
|
156
|
+
slave = slave.my_symbolize_keys
|
157
157
|
|
158
158
|
if include_errors
|
159
159
|
data[:errors] |= slave[:errors]
|
@@ -532,7 +532,7 @@ class Instance
|
|
532
532
|
end
|
533
533
|
|
534
534
|
# Normalize this sucker to have symbols as keys.
|
535
|
-
opts = opts.
|
535
|
+
opts = opts.my_symbolize_keys( false )
|
536
536
|
|
537
537
|
slaves = opts.delete(:slaves) || []
|
538
538
|
spawn_count = opts[:spawns]
|
@@ -750,7 +750,7 @@ class Instance
|
|
750
750
|
parsed[q.to_sym] = nil
|
751
751
|
|
752
752
|
when Hash
|
753
|
-
parsed.merge!( q.
|
753
|
+
parsed.merge!( q.my_symbolize_keys )
|
754
754
|
end
|
755
755
|
end
|
756
756
|
|
@@ -758,7 +758,7 @@ class Instance
|
|
758
758
|
parsed[w.to_sym] = nil
|
759
759
|
|
760
760
|
when Hash
|
761
|
-
parsed.merge!( w.
|
761
|
+
parsed.merge!( w.my_symbolize_keys )
|
762
762
|
end
|
763
763
|
end
|
764
764
|
|
@@ -806,6 +806,14 @@ class Instance
|
|
806
806
|
|
807
807
|
# Starts RPC service.
|
808
808
|
def run
|
809
|
+
Reactor.global.on_error do |_, e|
|
810
|
+
print_error "Arachni::Reactor: #{e}"
|
811
|
+
|
812
|
+
e.backtrace.each do |l|
|
813
|
+
print_error "Arachni::Reactor: #{l}"
|
814
|
+
end
|
815
|
+
end
|
816
|
+
|
809
817
|
print_status 'Starting the server...'
|
810
818
|
@server.start
|
811
819
|
end
|
data/lib/arachni/ruby/hash.rb
CHANGED
@@ -19,10 +19,11 @@ class Hash
|
|
19
19
|
#
|
20
20
|
# @return [Hash]
|
21
21
|
# Hash with +self+'s keys recursively converted to strings.
|
22
|
-
def
|
22
|
+
def my_stringify_keys( recursively = true )
|
23
23
|
stringified = {}
|
24
24
|
each do |k, v|
|
25
|
-
stringified[k.to_s] = (recursively && v.is_a?( Hash ) ?
|
25
|
+
stringified[k.to_s] = (recursively && v.is_a?( Hash ) ?
|
26
|
+
v.my_stringify_keys : v)
|
26
27
|
end
|
27
28
|
stringified
|
28
29
|
end
|
@@ -34,20 +35,20 @@ class Hash
|
|
34
35
|
#
|
35
36
|
# @return [Hash]
|
36
37
|
# Hash with +self+'s keys recursively converted to symbols.
|
37
|
-
def
|
38
|
+
def my_symbolize_keys( recursively = true )
|
38
39
|
symbolize = {}
|
39
40
|
each do |k, v|
|
40
41
|
k = k.respond_to?(:to_sym) ? k.to_sym : k
|
41
42
|
|
42
43
|
symbolize[k] = (recursively && v.is_a?( Hash ) ?
|
43
|
-
v.
|
44
|
+
v.my_symbolize_keys : v)
|
44
45
|
end
|
45
46
|
symbolize
|
46
47
|
end
|
47
48
|
|
48
49
|
# @return [Hash]
|
49
50
|
# Hash with +self+'s keys and values recursively converted to strings.
|
50
|
-
def
|
51
|
+
def my_stringify
|
51
52
|
apply_recursively(:to_s)
|
52
53
|
end
|
53
54
|
|
@@ -79,7 +80,7 @@ class Hash
|
|
79
80
|
# @return [Hash]
|
80
81
|
# Self with the keys and values converted to lower-case strings.
|
81
82
|
def downcase
|
82
|
-
|
83
|
+
my_stringify_keys.inject({}) do |h, (k, v)|
|
83
84
|
k = k.downcase if k.is_a?( String )
|
84
85
|
v = v.downcase if v.is_a?( String )
|
85
86
|
h[k] = v
|
@@ -100,6 +100,7 @@ class Framework
|
|
100
100
|
suspending_plugins: 'Suspending plugins.',
|
101
101
|
saving_snapshot: 'Saving snapshot at: %s',
|
102
102
|
snapshot_location: 'Snapshot location: %s',
|
103
|
+
browser_cluster_startup: 'Initialising the browser cluster.',
|
103
104
|
browser_cluster_shutdown: 'Shutting down the browser cluster.',
|
104
105
|
clearing_queues: 'Clearing the audit queues.',
|
105
106
|
waiting_for_plugins: 'Waiting for the plugins to finish.',
|
data/lib/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
1
|
+
1.0.1
|
@@ -1797,6 +1797,20 @@ describe Arachni::Browser do
|
|
1797
1797
|
|
1798
1798
|
transition.options[:cookies].should == cookie
|
1799
1799
|
end
|
1800
|
+
|
1801
|
+
context 'when auditing existing cookies' do
|
1802
|
+
it 'preserves the HttpOnly attribute' do
|
1803
|
+
@browser.goto( @url )
|
1804
|
+
@browser.cookies.size.should == 1
|
1805
|
+
|
1806
|
+
cookies = { @browser.cookies.first.name => 'updated' }
|
1807
|
+
@browser.goto( @url, cookies: cookies )
|
1808
|
+
|
1809
|
+
@browser.cookies.first.value == 'updated'
|
1810
|
+
@browser.cookies.first.should be_http_only
|
1811
|
+
end
|
1812
|
+
end
|
1813
|
+
|
1800
1814
|
end
|
1801
1815
|
|
1802
1816
|
describe :take_snapshot do
|
@@ -2269,6 +2283,17 @@ describe Arachni::Browser do
|
|
2269
2283
|
cookie.name.should == 'This name should be updated; and properly escaped'
|
2270
2284
|
cookie.value.should == 'This value should be updated; and properly escaped'
|
2271
2285
|
end
|
2286
|
+
|
2287
|
+
it 'preserves the HttpOnly attribute' do
|
2288
|
+
@browser.load @url
|
2289
|
+
@browser.cookies.first.should be_http_only
|
2290
|
+
end
|
2291
|
+
|
2292
|
+
context 'when no page is available' do
|
2293
|
+
it 'returns an empty Array' do
|
2294
|
+
@browser.cookies.should be_empty
|
2295
|
+
end
|
2296
|
+
end
|
2272
2297
|
end
|
2273
2298
|
|
2274
2299
|
describe '#snapshot_id' do
|
@@ -301,7 +301,7 @@ describe Arachni::Component::Manager do
|
|
301
301
|
'opt_opt' => 'opt_opt value',
|
302
302
|
'default_opt' => 'value2'
|
303
303
|
}
|
304
|
-
@components.prepare_options( c, @components[c], opts ).should == opts.
|
304
|
+
@components.prepare_options( c, @components[c], opts ).should == opts.my_symbolize_keys
|
305
305
|
end
|
306
306
|
|
307
307
|
context 'with missing options' do
|
@@ -199,7 +199,7 @@ describe Arachni::Element::Cookie do
|
|
199
199
|
|
200
200
|
describe '#encode' do
|
201
201
|
it 'encodes the string in a way that makes is suitable to be included in a cookie header' do
|
202
|
-
described_class.encode( 'some stuff ;%=' ).should == 'some+stuff+%3B%25='
|
202
|
+
described_class.encode( 'some stuff \'";%=' ).should == 'some+stuff+%27%22%3B%25='
|
203
203
|
end
|
204
204
|
end
|
205
205
|
|
@@ -214,7 +214,7 @@ describe Arachni::Element::Cookie do
|
|
214
214
|
)
|
215
215
|
|
216
216
|
c.to_set_cookie.should ==
|
217
|
-
'blah%3Dha%25=some+stuff+%3B; Path=/; Domain
|
217
|
+
'blah%3Dha%25=some+stuff+%3B; Path=/; Domain=127.0.0.2; Secure; HttpOnly'
|
218
218
|
described_class.from_set_cookie( url, c.to_set_cookie ).first.should == c
|
219
219
|
|
220
220
|
c = described_class.new(
|
@@ -226,7 +226,7 @@ describe Arachni::Element::Cookie do
|
|
226
226
|
|
227
227
|
described_class.from_set_cookie( url, c.to_set_cookie ).first.should == c
|
228
228
|
c.to_set_cookie.should ==
|
229
|
-
'blah%3Dha%25=some+stuff+%3B; Path=/stuff; Domain
|
229
|
+
'blah%3Dha%25=some+stuff+%3B; Path=/stuff; Domain=127.0.0.2'
|
230
230
|
end
|
231
231
|
end
|
232
232
|
|
@@ -450,12 +450,12 @@ describe Arachni::HTTP::Request do
|
|
450
450
|
described_class.new(
|
451
451
|
url: url,
|
452
452
|
proxy: 'http://stuff/',
|
453
|
-
proxy_type:
|
453
|
+
proxy_type: :http
|
454
454
|
)
|
455
455
|
end
|
456
456
|
|
457
457
|
it 'forwards it' do
|
458
|
-
subject.options[:proxytype].should ==
|
458
|
+
subject.options[:proxytype].should == :http
|
459
459
|
end
|
460
460
|
end
|
461
461
|
end
|
@@ -486,7 +486,7 @@ describe Arachni::HTTP::Request do
|
|
486
486
|
context "and #{Arachni::OptionGroups::HTTP}#proxy_type" do
|
487
487
|
it 'forwards it' do
|
488
488
|
Arachni::Options.http.proxy_type = 'http'
|
489
|
-
subject.options[:proxytype].should ==
|
489
|
+
subject.options[:proxytype].should == :http
|
490
490
|
end
|
491
491
|
end
|
492
492
|
end
|
@@ -214,14 +214,14 @@ describe Arachni::OptionGroups::Scope do
|
|
214
214
|
values = { /redundant_path_patterns/ => 1 }
|
215
215
|
subject.redundant_path_patterns = values
|
216
216
|
|
217
|
-
data['redundant_path_patterns'].should == values.
|
217
|
+
data['redundant_path_patterns'].should == values.my_stringify
|
218
218
|
end
|
219
219
|
|
220
220
|
it "converts 'url_rewrites' to strings" do
|
221
221
|
values = { /url_rewrites/ => 'test' }
|
222
222
|
subject.url_rewrites = values
|
223
223
|
|
224
|
-
data['url_rewrites'].should == values.
|
224
|
+
data['url_rewrites'].should == values.my_stringify
|
225
225
|
end
|
226
226
|
|
227
227
|
%w(exclude_path_patterns exclude_content_patterns include_path_patterns).each do |k|
|
data/spec/arachni/parser_spec.rb
CHANGED
@@ -517,6 +517,13 @@ describe Arachni::Parser do
|
|
517
517
|
subject.link_vars.should == { 'id' => '13' }
|
518
518
|
end
|
519
519
|
end
|
520
|
+
|
521
|
+
context 'when the URL cannot be parsed' do
|
522
|
+
it 'returns an empty array' do
|
523
|
+
subject.url = nil
|
524
|
+
subject.link_vars.should == {}
|
525
|
+
end
|
526
|
+
end
|
520
527
|
end
|
521
528
|
|
522
529
|
end
|
@@ -23,7 +23,7 @@ describe Arachni::Reporter::Manager do
|
|
23
23
|
options = { 'outfile' => 'stuff' }
|
24
24
|
reporter = @reporters.run( :foo, report, options )
|
25
25
|
|
26
|
-
reporter.options.should == options.
|
26
|
+
reporter.options.should == options.my_symbolize_keys(false)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -226,7 +226,7 @@ describe 'Arachni::RPC::Server::Framework' do
|
|
226
226
|
data.keys.sort.should == @progress_keys
|
227
227
|
|
228
228
|
data[:statistics].keys.should == instance.framework.statistics.keys
|
229
|
-
data[:messages].should
|
229
|
+
data[:messages].should be_empty
|
230
230
|
data[:status].should be_true
|
231
231
|
data[:busy].nil?.should be_false
|
232
232
|
data[:issues].should be_any
|
@@ -23,14 +23,14 @@ describe Hash do
|
|
23
23
|
}
|
24
24
|
end
|
25
25
|
|
26
|
-
describe '#
|
26
|
+
describe '#my_stringify_keys' do
|
27
27
|
it 'recursively converts keys to strings' do
|
28
|
-
with_symbols.
|
28
|
+
with_symbols.my_stringify_keys.should == with_strings
|
29
29
|
end
|
30
30
|
|
31
31
|
context 'when the recursive is set to false' do
|
32
32
|
it 'only converts the keys at depth 1' do
|
33
|
-
with_symbols.
|
33
|
+
with_symbols.my_stringify_keys( false ).should == {
|
34
34
|
'stuff' => 'blah',
|
35
35
|
'more' => {
|
36
36
|
stuff: {
|
@@ -42,14 +42,14 @@ describe Hash do
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
describe '#
|
45
|
+
describe '#my_symbolize_keys' do
|
46
46
|
it 'recursively converts keys to symbols' do
|
47
|
-
with_strings.
|
47
|
+
with_strings.my_symbolize_keys.should == with_symbols
|
48
48
|
end
|
49
49
|
|
50
50
|
context 'when the recursive is set to false' do
|
51
51
|
it 'only converts the keys at depth 1' do
|
52
|
-
with_strings.
|
52
|
+
with_strings.my_symbolize_keys( false ).should == {
|
53
53
|
stuff: 'blah',
|
54
54
|
more: {
|
55
55
|
'stuff' => {
|
@@ -75,14 +75,14 @@ describe Hash do
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
describe '#
|
78
|
+
describe '#my_stringify' do
|
79
79
|
it 'returns a Hash with keys and values recursively converted to strings' do
|
80
80
|
{
|
81
81
|
test: 'blah',
|
82
82
|
another_hash: {
|
83
83
|
stuff: 'test'
|
84
84
|
}
|
85
|
-
}.
|
85
|
+
}.my_stringify.should == {
|
86
86
|
'test' => 'blah',
|
87
87
|
'another_hash' => {
|
88
88
|
'stuff' => 'test'
|
@@ -15,7 +15,7 @@ shared_examples_for 'inputtable' do |options = {}|
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
let(:sym_key_inputs) { inputs.
|
18
|
+
let(:sym_key_inputs) { inputs.my_symbolize_keys }
|
19
19
|
|
20
20
|
let(:keys) do
|
21
21
|
subject.inputs.keys
|
@@ -140,7 +140,7 @@ shared_examples_for 'inputtable' do |options = {}|
|
|
140
140
|
context 'when it has the given inputs (names and values)' do
|
141
141
|
it 'returns true' do
|
142
142
|
subject.has_inputs?( subject.inputs ).should be_true
|
143
|
-
subject.has_inputs?( subject.inputs.
|
143
|
+
subject.has_inputs?( subject.inputs.my_symbolize_keys ).should be_true
|
144
144
|
end
|
145
145
|
end
|
146
146
|
context 'when it does not have the given inputs' do
|
data/ui/cli/utilities.rb
CHANGED
@@ -29,9 +29,12 @@ module Utilities
|
|
29
29
|
issue_cnt = issues.count
|
30
30
|
issues.each.with_index do |issue, i|
|
31
31
|
meth = input = ''
|
32
|
+
|
32
33
|
if issue.active?
|
33
34
|
input = " input `#{issue.vector.affected_input_name}`"
|
34
35
|
meth = " using #{issue.vector.method.to_s.upcase}"
|
36
|
+
elsif issue.vector.respond_to?( :inputs )
|
37
|
+
input = " with inputs `#{issue.vector.inputs.keys.join(', ')}`"
|
35
38
|
end
|
36
39
|
|
37
40
|
cnt = "#{i + 1} |".rjust( issue_cnt.to_s.size + 2 )
|
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:
|
4
|
+
version: 1.0.1
|
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-
|
11
|
+
date: 2014-09-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - '='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 0.2.
|
89
|
+
version: 0.2.1.1
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 0.2.
|
96
|
+
version: 0.2.1.1
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: typhoeus
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|