arachni 1.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/README.md +2 -2
  4. data/arachni.gemspec +1 -1
  5. data/components/checks/active/code_injection_php_input_wrapper.rb +8 -3
  6. data/components/checks/active/file_inclusion.rb +7 -3
  7. data/components/checks/active/path_traversal.rb +7 -3
  8. data/components/checks/passive/grep/cookie_set_for_parent_domain.rb +5 -3
  9. data/components/plugins/cookie_collector.rb +1 -1
  10. data/components/plugins/proxy.rb +4 -3
  11. data/components/plugins/vector_feed.rb +1 -1
  12. data/components/reporters/html/default/issue.erb +5 -0
  13. data/components/reporters/stdout.rb +4 -0
  14. data/lib/arachni/browser.rb +25 -6
  15. data/lib/arachni/browser/element_locator.rb +1 -1
  16. data/lib/arachni/browser/javascript/taint_tracer.rb +3 -3
  17. data/lib/arachni/browser/javascript/taint_tracer/frame.rb +1 -1
  18. data/lib/arachni/browser/javascript/taint_tracer/frame/called_function.rb +1 -1
  19. data/lib/arachni/browser/javascript/taint_tracer/sink/base.rb +1 -1
  20. data/lib/arachni/check/auditor.rb +2 -0
  21. data/lib/arachni/component/manager.rb +2 -2
  22. data/lib/arachni/component/options/base.rb +2 -2
  23. data/lib/arachni/element/base.rb +2 -2
  24. data/lib/arachni/element/cookie.rb +4 -4
  25. data/lib/arachni/element/form.rb +1 -1
  26. data/lib/arachni/element/generic_dom.rb +1 -1
  27. data/lib/arachni/framework.rb +9 -1
  28. data/lib/arachni/http/client.rb +2 -0
  29. data/lib/arachni/http/request.rb +2 -2
  30. data/lib/arachni/http/response.rb +1 -1
  31. data/lib/arachni/issue.rb +2 -2
  32. data/lib/arachni/option_group.rb +1 -1
  33. data/lib/arachni/option_groups/input.rb +1 -1
  34. data/lib/arachni/option_groups/scope.rb +1 -1
  35. data/lib/arachni/page.rb +1 -1
  36. data/lib/arachni/page/dom/transition.rb +3 -3
  37. data/lib/arachni/parser.rb +3 -1
  38. data/lib/arachni/platform/list.rb +1 -1
  39. data/lib/arachni/report.rb +1 -1
  40. data/lib/arachni/rpc/client/instance/framework.rb +6 -6
  41. data/lib/arachni/rpc/client/instance/service.rb +7 -7
  42. data/lib/arachni/rpc/server/dispatcher.rb +18 -5
  43. data/lib/arachni/rpc/server/dispatcher/node.rb +13 -6
  44. data/lib/arachni/rpc/server/framework/distributor.rb +1 -1
  45. data/lib/arachni/rpc/server/framework/master.rb +1 -1
  46. data/lib/arachni/rpc/server/framework/multi_instance.rb +2 -2
  47. data/lib/arachni/rpc/server/instance.rb +11 -3
  48. data/lib/arachni/ruby/hash.rb +7 -6
  49. data/lib/arachni/state/framework.rb +1 -0
  50. data/lib/version +1 -1
  51. data/spec/arachni/browser_spec.rb +25 -0
  52. data/spec/arachni/component/manager_spec.rb +1 -1
  53. data/spec/arachni/element/cookie_spec.rb +3 -3
  54. data/spec/arachni/http/request_spec.rb +3 -3
  55. data/spec/arachni/option_groups/scope_spec.rb +2 -2
  56. data/spec/arachni/parser_spec.rb +7 -0
  57. data/spec/arachni/reporter/manager_spec.rb +1 -1
  58. data/spec/arachni/rpc/server/dispatcher/node_spec.rb +2 -0
  59. data/spec/arachni/rpc/server/framework_spec.rb +1 -1
  60. data/spec/arachni/ruby/hash_spec.rb +8 -8
  61. data/spec/support/servers/checks/passive/grep/cookie_set_for_parent_domain.rb +1 -1
  62. data/spec/support/shared/element/capabilities/inputtable.rb +2 -2
  63. data/ui/cli/utilities.rb +3 -0
  64. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0bbd91e8fb1bcbcf5164c22e187397214e1894ac
4
- data.tar.gz: 16adc7946a2fa8da04a50b2417cd8b731d291652
3
+ metadata.gz: a4f1fba6f25f0dd437f9d31c82b3f036d4b87ec9
4
+ data.tar.gz: eaa9814da188578b10283e23101525828d42b17a
5
5
  SHA512:
6
- metadata.gz: 913913c30128c176a2e55614ee95530343fd6f300cdf3008cbd6df69cf93b78c2b9c87ea748ae330524061a32a160563fb1aafdfc2b06ad4dcf853e5f9eb8b50
7
- data.tar.gz: 59bd68596db84ed440707cde96554f13d6397a52ca0025f9019073ba250bf0e32296adbebd50ac099c02262bff40ac5c27d9d3bcffeb0d2afe74666577816b3d
6
+ metadata.gz: a98cde207400471e0ba80cffc9fce6ce46348d43e76c509cbd06f5c7e6b4867f62f9e5382bedaa7b500d731a82428cde04d23db0ea72a4cfceb9087c8fe8062a
7
+ data.tar.gz: a66344c76f782b7042f003c0e7b525b5ea173d2f72257d77f9a4673be35280624d4c73a5f874c157b4b66fd5b3eb46a0196480d9b91379639da6cf26e288c045
@@ -1,5 +1,52 @@
1
1
  # ChangeLog
2
2
 
3
+ ## 1.0.1 _(September 7, 2014)_
4
+
5
+ - `RPC::Server::Dispatcher`
6
+ - Check for Instance status via the bind address, not the external one.
7
+ - Added more status and debugging messages
8
+ - Fixed RPC connection leak when in Grid configuration.
9
+ - `Node`
10
+ - Don't raise error if the initial neighbour is unreachable, just add
11
+ it to the dead list as usual.
12
+ - `Browser`
13
+ - Fixed issue causing the removal of cookie HttpOnly flags.
14
+ - `Parser`
15
+ - `#link_vars` -- Return empty `Hash` when dealing with unparsable URL.
16
+ - `HTTP::Client`
17
+ - Debugging messages now include the `HTTP::Request#performer`.
18
+ - `HTTP::Request`
19
+ - `#to_typhoeus` -- Converted proxy type to `Symbol` to prevent the option
20
+ from being ignored.
21
+ - `UI::CLI::Utilities`
22
+ - `#print_issues` -- Updated to include all inputs of the given vector in
23
+ the message, if the issue is passive.
24
+ - `Check::Auditor`
25
+ - `#log` -- Updated to include all inputs of the given vector in the success
26
+ message, if the issue is passive.
27
+ - `Element::Cookie`
28
+ - `.encode` -- Encode `'` and `"`.
29
+ - `Hash` -- Renamed added methods to avoid clashes with `ActiveSupport`.
30
+ - `stringify_keys` => `my_stringify_keys`
31
+ - `symbolize_keys` => `my_symbolize_keys`
32
+ - `stringify` => `my_stringify`
33
+ - Plugins
34
+ - `proxy` -- Show control panel URL in output.
35
+ - Reporters
36
+ - `stdout`
37
+ - Updated to print out information about all available vector inputs.
38
+ - `html`
39
+ - Updated to include information about all available vector inputs in
40
+ issue title for passive issues.
41
+ - Checks
42
+ - Active
43
+ - `code_injection_php_input_wrapper` -- Fixed `nil` error when
44
+ manipulating mutations.
45
+ - `file_inclusion` -- Fixed `nil` error when manipulating mutations.
46
+ - `path_traversal` -- Fixed `nil` error when manipulating mutations.
47
+ - Passive
48
+ - `cookie_set_for_parent_domain` -- Only check `HTTP::Response` cookies.
49
+
3
50
  ## 1.0 _(August 29, 2014)_
4
51
 
5
52
  - Executables:
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  * Arachni's license has changed, please see the _LICENSE_ file before working
4
4
  with the project.
5
- * v1.0 is not backwards compatible.
5
+ * v1.0 is not backwards compatible with v0.4.
6
6
 
7
7
  <hr/>
8
8
 
@@ -11,7 +11,7 @@
11
11
  <table>
12
12
  <tr>
13
13
  <th>Version</th>
14
- <td>1.0</td>
14
+ <td>1.0.1</td>
15
15
  </tr>
16
16
  <tr>
17
17
  <th>Homepage</th>
@@ -61,7 +61,7 @@ Gem::Specification.new do |s|
61
61
  end
62
62
 
63
63
  # RPC client/server implementation.
64
- s.add_dependency 'arachni-rpc', '0.2.0'
64
+ s.add_dependency 'arachni-rpc', '0.2.1.1'
65
65
 
66
66
  # HTTP client.
67
67
  s.add_dependency 'typhoeus', '0.6.9'
@@ -6,9 +6,9 @@
6
6
  web site for more information on licensing and terms of use.
7
7
  =end
8
8
 
9
- # @see OWASP https://www.owasp.org/index.php/Top_10_2007-Malicious_File_Execution
10
9
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
11
- # @version 0.1
10
+ # @version 0.1.1
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
 
14
14
  def self.options
@@ -20,6 +20,11 @@ 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?))
27
+
23
28
  # Don't bother if the current element type can't carry nulls.
24
29
  next if !mutation.valid_input_value_data?( "\0" )
25
30
 
@@ -51,7 +56,7 @@ to try and load it.
51
56
  },
52
57
  elements: [ Element::Form, Element::Link, Element::Cookie, Element::Header ],
53
58
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com> ',
54
- version: '0.1',
59
+ version: '0.1.1',
55
60
  platforms: [:php],
56
61
 
57
62
  issue: {
@@ -9,8 +9,7 @@
9
9
  # File inclusion check.
10
10
  #
11
11
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
12
- #
13
- # @version 0.1.1
12
+ # @version 0.1.2
14
13
  #
15
14
  # @see http://cwe.mitre.org/data/definitions/98.html
16
15
  # @see https://www.owasp.org/index.php/PHP_File_Inclusion
@@ -51,6 +50,11 @@ class Arachni::Checks::FileInclusion < Arachni::Check::Base
51
50
  # Add one more mutation (on the fly) which will include the extension
52
51
  # of the original value (if that value was a filename) after a null byte.
53
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?))
57
+
54
58
  # Don't bother if the current element type can't carry nulls.
55
59
  next if !mutation.valid_input_value_data?( "\0" )
56
60
 
@@ -101,7 +105,7 @@ content or errors in the HTTP response body.
101
105
  elements: [ Element::Form, Element::Link, Element::Cookie,
102
106
  Element::Header, Element::LinkTemplate ],
103
107
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com> ',
104
- version: '0.1.1',
108
+ version: '0.1.2',
105
109
  platforms: options[:regexp].keys,
106
110
 
107
111
  issue: {
@@ -9,8 +9,7 @@
9
9
  # Path Traversal check.
10
10
  #
11
11
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
12
- #
13
- # @version 0.4.1
12
+ # @version 0.4.2
14
13
  #
15
14
  # @see http://cwe.mitre.org/data/definitions/22.html
16
15
  # @see http://www.owasp.org/index.php/Path_Traversal
@@ -40,6 +39,11 @@ class Arachni::Checks::PathTraversal < Arachni::Check::Base
40
39
  # Add one more mutation (on the fly) which will include the extension
41
40
  # of the original value (if that value was a filename) after a null byte.
42
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?))
46
+
43
47
  # Don't bother if the current element type can't carry nulls.
44
48
  next if !mutation.valid_input_value_data?( "\0" )
45
49
 
@@ -111,7 +115,7 @@ of relevant content in the HTML responses.
111
115
  elements: [ Element::Form, Element::Link, Element::Cookie,
112
116
  Element::Header, Element::LinkTemplate ],
113
117
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com> ',
114
- version: '0.4.1',
118
+ version: '0.4.2',
115
119
  platforms: payloads.keys,
116
120
 
117
121
  issue: {
@@ -7,11 +7,13 @@
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::CookieSetForParentDomain < Arachni::Check::Base
12
12
 
13
13
  def run
14
- page.cookies.each do |cookie|
14
+ return if !page.parser
15
+
16
+ page.parser.cookies.each do |cookie|
15
17
  next if !cookie.domain.start_with?( '.' ) || audited?( cookie.name )
16
18
 
17
19
  log( vector: cookie )
@@ -25,7 +27,7 @@ class Arachni::Checks::CookieSetForParentDomain < Arachni::Check::Base
25
27
  description: %q{Logs cookies that are accessible by all subdomains.},
26
28
  elements: [ Element::Cookie ],
27
29
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
28
- version: '0.1',
30
+ version: '0.1.1',
29
31
 
30
32
  issue: {
31
33
  name: %q{Cookie set for parent domain},
@@ -44,7 +44,7 @@ class Arachni::Plugins::CookieCollector < Arachni::Plugin::Base
44
44
 
45
45
  @cookies << {
46
46
  'time' => Time.now.to_s,
47
- 'response' => response_hash.stringify_keys,
47
+ 'response' => response_hash.my_stringify_keys,
48
48
  'cookies' => cookies
49
49
  }
50
50
  end
@@ -16,7 +16,7 @@ require 'ostruct'
16
16
  #
17
17
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
18
18
  #
19
- # @version 0.3
19
+ # @version 0.3.1
20
20
  class Arachni::Plugins::Proxy < Arachni::Plugin::Base
21
21
 
22
22
  BASEDIR = "#{File.dirname( __FILE__ )}/proxy/"
@@ -58,7 +58,8 @@ class Arachni::Plugins::Proxy < Arachni::Plugin::Base
58
58
  def run
59
59
  print_status "Listening on: http://#{@server[:BindAddress]}:#{@server[:Port]}"
60
60
 
61
- print_status "Shutdown URL: #{url_for( :shutdown )}"
61
+ print_info "Control panel URL: #{url_for( :panel )}"
62
+ print_info "Shutdown URL: #{url_for( :shutdown )}"
62
63
  print_info 'The scan will resume once you visit the shutdown URL.'
63
64
 
64
65
  print_info
@@ -463,7 +464,7 @@ a way to restrict usage enough to avoid users unwittingly interfering with each
463
464
  others' sessions.
464
465
  },
465
466
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
466
- version: '0.3',
467
+ version: '0.3.1',
467
468
  options: [
468
469
  Options::Port.new( :port,
469
470
  description: 'Port to bind to.',
@@ -58,7 +58,7 @@ class Arachni::Plugins::VectorFeed < Arachni::Plugin::Base
58
58
  page_buffer = []
59
59
  print_status "Imported #{feed.size} vectors."
60
60
  feed.each do |obj|
61
- vector = (obj.respond_to?( :value ) ? obj.value : obj).symbolize_keys( false )
61
+ vector = (obj.respond_to?( :value ) ? obj.value : obj).my_symbolize_keys( false )
62
62
 
63
63
  exception_jail false do
64
64
  if page?( vector )
@@ -10,6 +10,11 @@
10
10
  <% if issue.active? %>
11
11
  input
12
12
  <code><%= issue.affected_input_name %></code>
13
+ <% elsif issue.vector.respond_to? :inputs %>
14
+ with inputs
15
+ <% issue.vector.inputs.keys.map do |iname| %>
16
+ <code><%= iname %></code>
17
+ <% end.join( ', ') %>
13
18
  <% end %>
14
19
 
15
20
  <% if issue.variations.first.request %>
@@ -109,6 +109,10 @@ class Arachni::Reporters::Stdout < Arachni::Reporter::Base
109
109
  print_info "Input name: #{issue.affected_input_name}"
110
110
  end
111
111
 
112
+ if issue.vector.respond_to? :inputs
113
+ print_info "All inputs: #{issue.vector.inputs.keys.join(', ')}"
114
+ end
115
+
112
116
  print_line
113
117
  print_info "Tags: #{issue.tags.join(', ')}" if issue.tags.is_a?( Array )
114
118
  print_line
@@ -308,6 +308,7 @@ class Browser
308
308
 
309
309
  @javascript.wait_till_ready
310
310
  wait_for_timers
311
+
311
312
  wait_for_pending_requests
312
313
  end
313
314
 
@@ -553,7 +554,7 @@ class Browser
553
554
  event = event.to_s.downcase.sub( /^on/, '' ).to_sym
554
555
  locator = nil
555
556
 
556
- options[:inputs] = options[:inputs].stringify if options[:inputs]
557
+ options[:inputs] = options[:inputs].my_stringify if options[:inputs]
557
558
 
558
559
  if element.is_a? ElementLocator
559
560
  locator = element
@@ -792,10 +793,22 @@ class Browser
792
793
  # @return [Array<Cookie>]
793
794
  # Browser cookies.
794
795
  def cookies
796
+ js_cookies = begin
797
+ # Watir doesn't tell us if cookies are HttpOnly, so we need to figure
798
+ # this out ourselves, by checking for JS visibility.
799
+ javascript.run( 'return document.cookie' )
800
+ # We may not have a page.
801
+ rescue Selenium::WebDriver::Error::UnknownError
802
+ ''
803
+ end
804
+
795
805
  watir.cookies.to_a.map do |c|
796
- c[:path] = '/' if c[:path] == '//'
797
- c[:name] = Cookie.decode( c[:name].to_s )
798
- c[:value] = Cookie.decode( c[:value].to_s )
806
+ original_name = c[:name].to_s
807
+
808
+ c[:path] = '/' if c[:path] == '//'
809
+ c[:name] = Cookie.decode( c[:name].to_s )
810
+ c[:value] = Cookie.decode( c[:value].to_s )
811
+ c[:httponly] = !js_cookies.include?( original_name )
799
812
 
800
813
  Cookie.new c.merge( url: @last_url )
801
814
  end
@@ -944,7 +957,8 @@ class Browser
944
957
  self.class.executable,
945
958
  "--webdriver=#{port}",
946
959
  "--proxy=http://#{@proxy.address}/",
947
- '--ignore-ssl-errors=true'
960
+ '--ignore-ssl-errors=true',
961
+ "--debug=#{!!debug?}"
948
962
  )
949
963
  @process.detach = true
950
964
 
@@ -1065,7 +1079,12 @@ class Browser
1065
1079
  set_cookies[cookie.name] = cookie
1066
1080
  end
1067
1081
  cookies.each do |name, value|
1068
- set_cookies[name] = Cookie.new( url: url, inputs: { name => value } )
1082
+ if set_cookies[name]
1083
+ set_cookies[name] = set_cookies[name].dup
1084
+ set_cookies[name].update( name => value )
1085
+ else
1086
+ set_cookies[name] = Cookie.new( url: url, inputs: { name => value } )
1087
+ end
1069
1088
  end
1070
1089
 
1071
1090
  url = "#{url}/set-cookies-#{request_token}"
@@ -91,7 +91,7 @@ class ElementLocator
91
91
  # @return [Hash]
92
92
  # Data representing this instance that are suitable the RPC transmission.
93
93
  def to_rpc_data
94
- to_h.stringify_keys
94
+ to_h.my_stringify_keys
95
95
  end
96
96
 
97
97
  # @param [Hash] data {#to_rpc_data}
@@ -74,9 +74,9 @@ class TaintTracer < Proxy
74
74
  return [] if !data
75
75
 
76
76
  data.map do |entry|
77
- Sink::DataFlow.new( (entry['data'] || {}).symbolize_keys( false ).merge(
77
+ Sink::DataFlow.new( (entry['data'] || {}).my_symbolize_keys( false ).merge(
78
78
  trace: [entry['trace']].flatten.compact.
79
- map { |h| Frame.new h.symbolize_keys( false ) }
79
+ map { |h| Frame.new h.my_symbolize_keys( false ) }
80
80
  )
81
81
  )
82
82
  end
@@ -88,7 +88,7 @@ class TaintTracer < Proxy
88
88
  data.map do |entry|
89
89
  Sink::ExecutionFlow.new( entry.merge(
90
90
  trace: [entry['trace']].flatten.compact.
91
- map { |h| Frame.new h.symbolize_keys( false ) }
91
+ map { |h| Frame.new h.my_symbolize_keys( false ) }
92
92
  )
93
93
  )
94
94
  end
@@ -35,7 +35,7 @@ class Frame
35
35
  @function = CalledFunction.new( options.delete(:function) )
36
36
  end
37
37
 
38
- options.symbolize_keys(false).each do |k, v|
38
+ options.my_symbolize_keys(false).each do |k, v|
39
39
  send( "#{k}=", v )
40
40
  end
41
41
  end
@@ -28,7 +28,7 @@ class CalledFunction
28
28
  attr_accessor :arguments
29
29
 
30
30
  def initialize( options = {} )
31
- options.symbolize_keys(false).each do |k, v|
31
+ options.my_symbolize_keys(false).each do |k, v|
32
32
  send( "#{k}=", v )
33
33
  end
34
34
  end
@@ -20,7 +20,7 @@ class Base
20
20
  attr_accessor :trace
21
21
 
22
22
  def initialize( options = {} )
23
- options.symbolize_keys(false).each do |k, v|
23
+ options.my_symbolize_keys(false).each do |k, v|
24
24
  send( "#{k}=", v )
25
25
  end
26
26
 
@@ -271,6 +271,8 @@ module Auditor
271
271
 
272
272
  if active
273
273
  msg << " input '#{vector.affected_input_name}'"
274
+ elsif vector.respond_to?( :inputs )
275
+ msg << " with inputs '#{vector.inputs.keys.join(', ')}'"
274
276
  end
275
277
 
276
278
  print_ok "#{msg} with action #{vector.action}"
@@ -172,7 +172,7 @@ class Manager < Hash
172
172
  return {} if !info.include?( :options ) || info[:options].empty?
173
173
 
174
174
  user_opts ||= {}
175
- user_opts = user_opts.symbolize_keys(false)
175
+ user_opts = user_opts.my_symbolize_keys(false)
176
176
 
177
177
  options = {}
178
178
  errors = {}
@@ -209,7 +209,7 @@ class Manager < Hash
209
209
  format_error_string( component_name, errors )
210
210
  end
211
211
 
212
- options.symbolize_keys( false )
212
+ options.my_symbolize_keys( false )
213
213
  end
214
214
 
215
215
  # It parses the component array making sure that its structure is valid
@@ -117,7 +117,7 @@ class Arachni::Component::Options::Base
117
117
  # @return [Hash]
118
118
  # Data representing this instance that are suitable the RPC transmission.
119
119
  def to_rpc_data
120
- to_h.merge( class: self.class.to_s ).stringify_keys
120
+ to_h.merge( class: self.class.to_s ).my_stringify_keys
121
121
  end
122
122
 
123
123
  # @param [Hash] data {#to_rpc_data}
@@ -127,7 +127,7 @@ class Arachni::Component::Options::Base
127
127
  data.delete('class')
128
128
  name = data.delete('name')
129
129
 
130
- new name, data.symbolize_keys(false)
130
+ new name, data.my_symbolize_keys(false)
131
131
  end
132
132
 
133
133
  def ==( option )