arachni 1.1 → 1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (287) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +159 -0
  3. data/LICENSE.md +126 -196
  4. data/README.md +32 -24
  5. data/arachni.gemspec +7 -7
  6. data/components/checks/active/code_injection_timing.rb +3 -3
  7. data/components/checks/active/csrf.rb +2 -2
  8. data/components/checks/active/file_inclusion.rb +6 -7
  9. data/components/checks/active/os_cmd_injection.rb +3 -3
  10. data/components/checks/active/path_traversal.rb +7 -7
  11. data/components/checks/active/response_splitting.rb +9 -4
  12. data/components/checks/active/session_fixation.rb +7 -3
  13. data/components/checks/active/source_code_disclosure.rb +5 -5
  14. data/components/checks/active/unvalidated_redirect.rb +12 -3
  15. data/components/checks/active/unvalidated_redirect_dom.rb +3 -3
  16. data/components/checks/active/xss.rb +23 -10
  17. data/components/checks/active/xss_dom_inputs.rb +113 -11
  18. data/components/checks/active/xxe.rb +3 -3
  19. data/components/checks/passive/backdoors.rb +6 -5
  20. data/components/checks/passive/backup_directories.rb +6 -6
  21. data/components/checks/passive/backup_files.rb +6 -6
  22. data/components/checks/passive/common_admin_interfaces.rb +58 -0
  23. data/components/checks/passive/common_admin_interfaces/admin-panels.txt +49 -0
  24. data/components/checks/passive/common_directories/directories.txt +0 -16
  25. data/components/checks/passive/common_files.rb +6 -5
  26. data/components/checks/passive/common_files/filenames.txt +0 -2
  27. data/components/checks/passive/directory_listing.rb +6 -6
  28. data/components/checks/passive/grep/cookie_set_for_parent_domain.rb +3 -3
  29. data/components/checks/passive/grep/hsts.rb +6 -3
  30. data/components/checks/passive/grep/http_only_cookies.rb +3 -3
  31. data/components/checks/passive/grep/insecure_cookies.rb +2 -2
  32. data/components/checks/passive/grep/insecure_cors_policy.rb +6 -4
  33. data/components/checks/passive/grep/x_frame_options.rb +6 -4
  34. data/components/checks/passive/htaccess_limit.rb +6 -2
  35. data/components/checks/passive/http_put.rb +8 -4
  36. data/components/checks/passive/interesting_responses.rb +3 -2
  37. data/components/checks/passive/localstart_asp.rb +6 -2
  38. data/components/checks/passive/origin_spoof_access_restriction_bypass.rb +5 -1
  39. data/components/checks/passive/xst.rb +6 -2
  40. data/components/fingerprinters/frameworks/aspx_mvc.rb +43 -0
  41. data/components/fingerprinters/frameworks/cakephp.rb +28 -0
  42. data/components/fingerprinters/frameworks/cherrypy.rb +31 -0
  43. data/components/fingerprinters/frameworks/django.rb +33 -0
  44. data/components/fingerprinters/frameworks/jsf.rb +30 -0
  45. data/components/fingerprinters/frameworks/rack.rb +5 -7
  46. data/components/fingerprinters/frameworks/rails.rb +43 -0
  47. data/components/fingerprinters/languages/aspx.rb +11 -11
  48. data/components/fingerprinters/languages/{jsp.rb → java.rb} +11 -7
  49. data/components/fingerprinters/languages/php.rb +6 -6
  50. data/components/fingerprinters/languages/python.rb +14 -6
  51. data/components/fingerprinters/languages/ruby.rb +3 -5
  52. data/components/fingerprinters/servers/apache.rb +5 -4
  53. data/components/fingerprinters/servers/gunicorn.rb +33 -0
  54. data/components/fingerprinters/servers/jetty.rb +1 -1
  55. data/components/fingerprinters/servers/tomcat.rb +11 -4
  56. data/components/path_extractors/anchors.rb +5 -12
  57. data/components/path_extractors/areas.rb +5 -13
  58. data/components/path_extractors/comments.rb +5 -3
  59. data/components/path_extractors/data_url.rb +21 -0
  60. data/components/path_extractors/forms.rb +5 -13
  61. data/components/path_extractors/frames.rb +6 -13
  62. data/components/path_extractors/generic.rb +3 -12
  63. data/components/path_extractors/links.rb +5 -13
  64. data/components/path_extractors/meta_refresh.rb +5 -13
  65. data/components/path_extractors/scripts.rb +8 -14
  66. data/components/plugins/autologin.rb +17 -5
  67. data/components/plugins/defaults/meta/remedies/discovery.rb +11 -29
  68. data/components/plugins/login_script.rb +40 -10
  69. data/components/plugins/metrics.rb +235 -0
  70. data/components/plugins/proxy.rb +21 -4
  71. data/components/plugins/proxy/panel/page_accordion.html.erb +34 -2
  72. data/components/plugins/restrict_to_dom_state.rb +70 -0
  73. data/components/plugins/vector_feed.rb +38 -9
  74. data/components/reporters/plugin_formatters/html/metrics.rb +290 -0
  75. data/components/reporters/plugin_formatters/stdout/metrics.rb +80 -0
  76. data/components/reporters/plugin_formatters/xml/metrics.rb +29 -0
  77. data/components/reporters/stdout.rb +4 -2
  78. data/components/reporters/xml.rb +4 -4
  79. data/components/reporters/xml/schema.xsd +95 -0
  80. data/lib/arachni.rb +2 -0
  81. data/lib/arachni/browser.rb +132 -77
  82. data/lib/arachni/browser/javascript.rb +173 -45
  83. data/lib/arachni/browser/javascript/scripts/dom_monitor.js +81 -6
  84. data/lib/arachni/browser/javascript/scripts/taint_tracer.js +31 -3
  85. data/lib/arachni/browser_cluster.rb +41 -15
  86. data/lib/arachni/browser_cluster/job.rb +4 -0
  87. data/lib/arachni/browser_cluster/jobs/resource_exploration.rb +0 -9
  88. data/lib/arachni/browser_cluster/worker.rb +8 -5
  89. data/lib/arachni/check/auditor.rb +20 -8
  90. data/lib/arachni/check/base.rb +38 -6
  91. data/lib/arachni/element/base.rb +18 -1
  92. data/lib/arachni/element/capabilities/analyzable/differential.rb +0 -1
  93. data/lib/arachni/element/capabilities/analyzable/taint.rb +40 -10
  94. data/lib/arachni/element/capabilities/analyzable/timeout.rb +27 -23
  95. data/lib/arachni/element/capabilities/auditable/dom.rb +22 -0
  96. data/lib/arachni/element/capabilities/inputtable.rb +6 -2
  97. data/lib/arachni/element/capabilities/submittable.rb +1 -1
  98. data/lib/arachni/element/cookie.rb +37 -23
  99. data/lib/arachni/element/cookie/capabilities/mutable.rb +6 -6
  100. data/lib/arachni/element/cookie/dom.rb +0 -8
  101. data/lib/arachni/element/form.rb +28 -14
  102. data/lib/arachni/element/form/capabilities/auditable.rb +2 -2
  103. data/lib/arachni/element/form/capabilities/mutable.rb +5 -5
  104. data/lib/arachni/element/form/dom.rb +0 -8
  105. data/lib/arachni/element/generic_dom.rb +1 -1
  106. data/lib/arachni/element/json.rb +2 -1
  107. data/lib/arachni/element/json/capabilities/inputtable.rb +6 -6
  108. data/lib/arachni/element/json/capabilities/mutable.rb +1 -1
  109. data/lib/arachni/element/link.rb +13 -16
  110. data/lib/arachni/element/link/dom.rb +1 -14
  111. data/lib/arachni/element/link_template.rb +3 -2
  112. data/lib/arachni/element/link_template/dom.rb +0 -16
  113. data/lib/arachni/element/server.rb +51 -9
  114. data/lib/arachni/element/xml.rb +1 -0
  115. data/lib/arachni/ethon/easy.rb +4 -1
  116. data/lib/arachni/framework/parts/audit.rb +26 -77
  117. data/lib/arachni/framework/parts/browser.rb +50 -55
  118. data/lib/arachni/framework/parts/check.rb +4 -3
  119. data/lib/arachni/framework/parts/data.rb +41 -6
  120. data/lib/arachni/framework/parts/state.rb +16 -7
  121. data/lib/arachni/http/client.rb +66 -38
  122. data/lib/arachni/http/client/dynamic_404_handler.rb +46 -14
  123. data/lib/arachni/http/headers.rb +22 -10
  124. data/lib/arachni/http/proxy_server.rb +67 -22
  125. data/lib/arachni/http/proxy_server/ssl-interceptor-cacert.pem +34 -0
  126. data/lib/arachni/http/proxy_server/ssl-interceptor-cakey.pem +51 -0
  127. data/lib/arachni/http/request.rb +71 -18
  128. data/lib/arachni/issue.rb +17 -3
  129. data/lib/arachni/option_groups/browser_cluster.rb +34 -1
  130. data/lib/arachni/option_groups/http.rb +1 -1
  131. data/lib/arachni/page.rb +26 -13
  132. data/lib/arachni/page/dom/transition.rb +2 -2
  133. data/lib/arachni/parser.rb +28 -11
  134. data/lib/arachni/platform/fingerprinter.rb +5 -0
  135. data/lib/arachni/platform/manager.rb +65 -32
  136. data/lib/arachni/plugin/base.rb +8 -0
  137. data/lib/arachni/processes/instances.rb +25 -11
  138. data/lib/arachni/reporter/manager.rb +2 -2
  139. data/lib/arachni/rpc/client/instance.rb +4 -0
  140. data/lib/arachni/rpc/server/framework/master.rb +3 -3
  141. data/lib/arachni/rpc/server/framework/multi_instance.rb +0 -8
  142. data/lib/arachni/rpc/server/instance.rb +2 -1
  143. data/lib/arachni/ruby/array.rb +5 -0
  144. data/lib/arachni/ruby/hash.rb +5 -0
  145. data/lib/arachni/ruby/string.rb +2 -3
  146. data/lib/arachni/session.rb +32 -6
  147. data/lib/arachni/state/framework.rb +6 -2
  148. data/lib/arachni/support/cache.rb +1 -0
  149. data/lib/arachni/support/cache/base.rb +12 -8
  150. data/lib/arachni/support/cache/least_recently_pushed.rb +29 -0
  151. data/lib/arachni/support/cache/least_recently_used.rb +5 -8
  152. data/lib/arachni/support/cache/preference.rb +1 -1
  153. data/lib/arachni/support/cache/random_replacement.rb +1 -25
  154. data/lib/arachni/support/database/queue.rb +21 -8
  155. data/lib/arachni/support/lookup/base.rb +7 -1
  156. data/lib/arachni/support/mixins/observable.rb +3 -1
  157. data/lib/arachni/support/profiler.rb +51 -10
  158. data/lib/arachni/support/signature.rb +11 -2
  159. data/lib/arachni/trainer.rb +8 -2
  160. data/lib/arachni/uri.rb +28 -25
  161. data/lib/arachni/uri/scope.rb +1 -1
  162. data/lib/arachni/utilities.rb +8 -0
  163. data/lib/arachni/watir/element.rb +1 -1
  164. data/lib/version +1 -1
  165. data/spec/arachni/browser/javascript/dom_monitor_spec.rb +388 -53
  166. data/spec/arachni/browser/javascript/taint_tracer_spec.rb +41 -0
  167. data/spec/arachni/browser/javascript_spec.rb +235 -61
  168. data/spec/arachni/browser_cluster/jobs/resource_exploration_spec.rb +0 -9
  169. data/spec/arachni/browser_cluster_spec.rb +58 -10
  170. data/spec/arachni/browser_spec.rb +170 -26
  171. data/spec/arachni/check/auditor_spec.rb +22 -3
  172. data/spec/arachni/check/base_spec.rb +84 -0
  173. data/spec/arachni/element/body_spec.rb +1 -1
  174. data/spec/arachni/element/capabilities/analyzable/taint_spec.rb +3 -3
  175. data/spec/arachni/element/capabilities/analyzable/timeout_spec.rb +1 -1
  176. data/spec/arachni/element/cookie/dom_spec.rb +0 -9
  177. data/spec/arachni/element/cookie_spec.rb +85 -0
  178. data/spec/arachni/element/form/dom_spec.rb +0 -9
  179. data/spec/arachni/element/form_spec.rb +46 -3
  180. data/spec/arachni/element/json_spec.rb +20 -0
  181. data/spec/arachni/element/link/dom_spec.rb +0 -9
  182. data/spec/arachni/element/link_spec.rb +40 -15
  183. data/spec/arachni/element/link_template/dom_spec.rb +0 -8
  184. data/spec/arachni/element/link_template_spec.rb +2 -6
  185. data/spec/arachni/element/server_spec.rb +94 -8
  186. data/spec/arachni/element/xml_spec.rb +20 -0
  187. data/spec/arachni/framework/parts/audit_spec.rb +12 -14
  188. data/spec/arachni/framework/parts/browser_spec.rb +0 -171
  189. data/spec/arachni/framework/parts/platform_spec.rb +14 -8
  190. data/spec/arachni/framework/parts/report_spec.rb +1 -1
  191. data/spec/arachni/framework/parts/state_spec.rb +0 -9
  192. data/spec/arachni/http/client/dynamic_404_handlers_spec.rb +19 -0
  193. data/spec/arachni/http/client_spec.rb +169 -42
  194. data/spec/arachni/http/headers_spec.rb +18 -0
  195. data/spec/arachni/http/request_spec.rb +23 -0
  196. data/spec/arachni/issue_spec.rb +17 -6
  197. data/spec/arachni/page_spec.rb +22 -2
  198. data/spec/arachni/parser_spec.rb +5 -0
  199. data/spec/arachni/platform/manager_spec.rb +57 -25
  200. data/spec/arachni/reporter/manager_spec.rb +26 -0
  201. data/spec/arachni/rpc/server/active_options_spec.rb +9 -4
  202. data/spec/arachni/state/framework_spec.rb +2 -8
  203. data/spec/arachni/support/cache/least_recently_pushed_spec.rb +90 -0
  204. data/spec/arachni/support/cache/least_recently_used_spec.rb +5 -13
  205. data/spec/arachni/support/database/queue_spec.rb +7 -0
  206. data/spec/arachni/support/mixins/observable_spec.rb +15 -1
  207. data/spec/arachni/trainer_spec.rb +2 -2
  208. data/spec/components/checks/active/code_injection_timing_spec.rb +1 -1
  209. data/spec/components/checks/active/file_inclusion_spec.rb +6 -6
  210. data/spec/components/checks/active/path_traversal_spec.rb +2 -2
  211. data/spec/components/checks/active/source_code_disclosure_spec.rb +2 -2
  212. data/spec/components/checks/active/unvalidated_redirect_spec.rb +6 -6
  213. data/spec/components/checks/active/xss_dom_inputs_spec.rb +3 -5
  214. data/spec/components/checks/active/xss_dom_script_context_spec.rb +1 -1
  215. data/spec/components/checks/active/xss_spec.rb +5 -5
  216. data/spec/components/checks/passive/common_admin_interfaces_spec.rb +15 -0
  217. data/spec/components/checks/passive/interesting_responses_spec.rb +14 -1
  218. data/spec/components/fingerprinters/frameworks/aspx_mvc_spec.rb +31 -0
  219. data/spec/components/fingerprinters/frameworks/cakephp_spec.rb +22 -0
  220. data/spec/components/fingerprinters/frameworks/cherrypy_spec.rb +28 -0
  221. data/spec/components/fingerprinters/frameworks/django_spec.rb +37 -0
  222. data/spec/components/fingerprinters/frameworks/jsf_spec.rb +27 -0
  223. data/spec/components/fingerprinters/frameworks/rack_spec.rb +11 -14
  224. data/spec/components/fingerprinters/frameworks/rails_spec.rb +53 -0
  225. data/spec/components/fingerprinters/languages/asp_spec.rb +7 -9
  226. data/spec/components/fingerprinters/languages/aspx_spec.rb +10 -24
  227. data/spec/components/fingerprinters/languages/java_spec.rb +88 -0
  228. data/spec/components/fingerprinters/languages/php_spec.rb +19 -12
  229. data/spec/components/fingerprinters/languages/python_spec.rb +22 -9
  230. data/spec/components/fingerprinters/languages/ruby.rb +6 -4
  231. data/spec/components/fingerprinters/os/bsd_spec.rb +6 -4
  232. data/spec/components/fingerprinters/os/linux_spec.rb +6 -4
  233. data/spec/components/fingerprinters/os/solaris_spec.rb +6 -4
  234. data/spec/components/fingerprinters/os/unix_spec.rb +6 -4
  235. data/spec/components/fingerprinters/os/windows_spec.rb +6 -4
  236. data/spec/components/fingerprinters/servers/apache_spec.rb +15 -4
  237. data/spec/components/fingerprinters/servers/gunicorn_spec.rb +28 -0
  238. data/spec/components/fingerprinters/servers/iis_spec.rb +6 -6
  239. data/spec/components/fingerprinters/servers/jetty_spec.rb +6 -6
  240. data/spec/components/fingerprinters/servers/nginx_spec.rb +6 -4
  241. data/spec/components/fingerprinters/servers/tomcat_spec.rb +15 -6
  242. data/spec/components/path_extractors/data_url_spec.rb +19 -0
  243. data/spec/components/plugins/autologin_spec.rb +23 -0
  244. data/spec/components/plugins/login_script_spec.rb +112 -24
  245. data/spec/components/plugins/restrict_to_dom_state_spec.rb +16 -0
  246. data/spec/components/plugins/vector_feed_spec.rb +39 -1
  247. data/spec/support/factories/page/dom.rb +9 -4
  248. data/spec/support/factories/page/dom/transition.rb +31 -9
  249. data/spec/support/factories/scan_report.rb +8 -6
  250. data/spec/support/fixtures/empty/placeholder +0 -0
  251. data/spec/support/fixtures/report.afr +0 -0
  252. data/spec/support/fixtures/reporters/manager_spec/error.rb +18 -0
  253. data/spec/support/servers/arachni/browser.rb +117 -11
  254. data/spec/support/servers/arachni/browser/javascript/dom_monitor.rb +148 -4
  255. data/spec/support/servers/arachni/check/auditor.rb +4 -0
  256. data/spec/support/servers/arachni/element/cookie/cookie_dom.rb +1 -1
  257. data/spec/support/servers/arachni/http/client.rb +5 -0
  258. data/spec/support/servers/arachni/http/client/dynamic_404_handler.rb +13 -0
  259. data/spec/support/servers/checks/active/code_injection_timing.rb +1 -1
  260. data/spec/support/servers/checks/active/file_inclusion.rb +2 -2
  261. data/spec/support/servers/checks/active/path_traversal.rb +2 -2
  262. data/spec/support/servers/checks/active/source_code_disclosure.rb +40 -33
  263. data/spec/support/servers/checks/active/trainer_check.rb +9 -10
  264. data/spec/support/servers/checks/active/unvalidated_redirect_dom.rb +7 -4
  265. data/spec/support/servers/checks/active/xss.rb +35 -0
  266. data/spec/support/servers/checks/active/xss_dom.rb +1 -1
  267. data/spec/support/servers/checks/active/xss_dom_inputs.rb +24 -0
  268. data/spec/support/servers/checks/active/xss_dom_script_context.rb +1 -1
  269. data/spec/support/servers/checks/passive/common_admin_interfaces.rb +6 -0
  270. data/spec/support/servers/plugins/autologin.rb +9 -0
  271. data/spec/support/servers/plugins/restrict_to_dom_state.rb +4 -0
  272. data/spec/support/shared/element/base.rb +42 -0
  273. data/spec/support/shared/element/capabilities/auditable.rb +4 -4
  274. data/spec/support/shared/element/capabilities/auditable/dom.rb +26 -0
  275. data/spec/support/shared/element/capabilities/inputtable.rb +16 -11
  276. data/spec/support/shared/element/capabilities/submitable.rb +7 -2
  277. data/spec/support/shared/fingerprinter.rb +8 -0
  278. data/spec/support/shared/path_extractor.rb +1 -1
  279. data/ui/cli/framework.rb +3 -3
  280. data/ui/cli/framework/option_parser.rb +9 -0
  281. data/ui/cli/output.rb +9 -0
  282. data/ui/cli/reporter.rb +5 -2
  283. data/ui/cli/utilities.rb +4 -2
  284. metadata +76 -17
  285. data/lib/arachni/http/proxy_server/ssl-interceptor-cert.pem +0 -34
  286. data/lib/arachni/http/proxy_server/ssl-interceptor-pkey.pem +0 -51
  287. data/spec/components/fingerprinters/languages/jsp_spec.rb +0 -56
@@ -47,7 +47,7 @@ describe Arachni::Element::Capabilities::Analyzable::Timeout do
47
47
  context 'when #timing_attack_remark_data is' do
48
48
  context 'not nil' do
49
49
  it 'duplicates it' do
50
- h = { stuff: 1 }
50
+ h = { stuff: [1] }
51
51
 
52
52
  subject.timing_attack_remark_data = h
53
53
 
@@ -62,15 +62,6 @@ describe Arachni::Element::Cookie::DOM do
62
62
  end
63
63
  end
64
64
 
65
- %w(encode decode).each do |m|
66
- describe "##{m}" do
67
- it "delegates to #{Arachni::Element::Cookie}.#{m}" do
68
- Arachni::Element::Cookie.stub(m) { |arg| "#{arg}1" }
69
- subject.send( m, 'blah' ).should == 'blah1'
70
- end
71
- end
72
- end
73
-
74
65
  describe '#type' do
75
66
  it 'returns :cookie_dom' do
76
67
  subject.type.should == :cookie_dom
@@ -2,6 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Arachni::Element::Cookie do
4
4
  it_should_behave_like 'element'
5
+ it_should_behave_like 'with_source'
5
6
  it_should_behave_like 'with_dom'
6
7
  it_should_behave_like 'auditable', single_input: true
7
8
 
@@ -452,6 +453,7 @@ describe Arachni::Element::Cookie do
452
453
  cookie.name.should == 'coo@ki e2'
453
454
  cookie.value.should == 'blah val2@'
454
455
  cookie.path.should == '/stuff'
456
+ cookie.source.should == sc3
455
457
  end
456
458
 
457
459
  context 'when there is no path' do
@@ -465,6 +467,44 @@ describe Arachni::Element::Cookie do
465
467
  cookie.path.should == '/'
466
468
  end
467
469
  end
470
+
471
+ context 'when its value is' do
472
+ let(:value) { 'a' * size }
473
+ let(:cookie) { "cookie=#{value}; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain=.foo.com; HttpOnly" }
474
+
475
+ context "equal to #{described_class::MAX_SIZE}" do
476
+ let(:size) { described_class::MAX_SIZE }
477
+
478
+ it 'returns empty array' do
479
+ described_class.from_set_cookie(
480
+ 'http://test.com/stuff',
481
+ cookie
482
+ ).first.value.should be_empty
483
+ end
484
+ end
485
+
486
+ context "larger than #{described_class::MAX_SIZE}" do
487
+ let(:size) { described_class::MAX_SIZE + 1 }
488
+
489
+ it 'sets empty value' do
490
+ described_class.from_set_cookie(
491
+ 'http://test.com/stuff',
492
+ cookie
493
+ ).first.value.should be_empty
494
+ end
495
+ end
496
+
497
+ context "smaller than #{described_class::MAX_SIZE}" do
498
+ let(:size) { described_class::MAX_SIZE - 1 }
499
+
500
+ it 'leaves the values alone' do
501
+ described_class.from_set_cookie(
502
+ 'http://test.com/stuff',
503
+ cookie
504
+ ).first.value.should == value
505
+ end
506
+ end
507
+ end
468
508
  end
469
509
 
470
510
  describe '.from_string' do
@@ -485,6 +525,51 @@ describe Arachni::Element::Cookie do
485
525
  c.name.should == 'name2'
486
526
  c.value.should == 'value2'
487
527
  end
528
+
529
+ it 'can handle v1 values' do
530
+ described_class.from_string(
531
+ 'http://owner-url.com',
532
+ 'cookie="blah stuff"'
533
+ ).first.value.should == 'blah stuff'
534
+ end
535
+
536
+ context 'when its value is' do
537
+ let(:value) { 'a' * size }
538
+ let(:cookie) { "cookie=#{value}" }
539
+
540
+ context "equal to #{described_class::MAX_SIZE}" do
541
+ let(:size) { described_class::MAX_SIZE }
542
+
543
+ it 'sets empty value' do
544
+ described_class.from_string(
545
+ 'http://owner-url.com',
546
+ cookie
547
+ ).first.value.should be_empty
548
+ end
549
+ end
550
+
551
+ context "larger than #{described_class::MAX_SIZE}" do
552
+ let(:size) { described_class::MAX_SIZE + 1 }
553
+
554
+ it 'sets empty value' do
555
+ described_class.from_string(
556
+ 'http://owner-url.com',
557
+ cookie
558
+ ).first.value.should be_empty
559
+ end
560
+ end
561
+
562
+ context "smaller than #{described_class::MAX_SIZE}" do
563
+ let(:size) { described_class::MAX_SIZE - 1 }
564
+
565
+ it 'leaves the values alone' do
566
+ described_class.from_string(
567
+ 'http://owner-url.com',
568
+ cookie
569
+ ).first.value.should == value
570
+ end
571
+ end
572
+ end
488
573
  end
489
574
 
490
575
  end
@@ -43,15 +43,6 @@ describe Arachni::Element::Form::DOM do
43
43
  end
44
44
  end
45
45
 
46
- %w(encode decode).each do |m|
47
- describe "##{m}" do
48
- it "delegates to #{Arachni::Element::Form}.#{m}" do
49
- Arachni::Element::Form.stub(m) { |arg| "#{arg}1" }
50
- subject.send( m, 'blah' ).should == 'blah1'
51
- end
52
- end
53
- end
54
-
55
46
  describe '#parent' do
56
47
  it 'returns the parent element' do
57
48
  subject.parent.should be_kind_of Arachni::Element::Form
@@ -1076,12 +1076,55 @@ EOHTML
1076
1076
  }
1077
1077
  end
1078
1078
  end
1079
+
1080
+ context 'when its value is' do
1081
+ let(:form) { described_class.from_document( url, form_html ).first }
1082
+ let(:value) { 'a' * size }
1083
+ let(:form_html) do
1084
+ '<html>
1085
+ <body>
1086
+ <form method="post" action="/form" name="my_form">
1087
+ <input type="text" name="input_1" value="' + value + '">
1088
+ <input type="text" name="input_2" value="val_2">
1089
+ <input type="submit">
1090
+ </form>
1091
+ </body>
1092
+ </html>'
1093
+ end
1094
+
1095
+ context "equal to #{described_class::MAX_SIZE}" do
1096
+ let(:size) { described_class::MAX_SIZE }
1097
+
1098
+ it 'returns empty array' do
1099
+ form.inputs['input_1'].should be_empty
1100
+ form.inputs['input_2'].should == 'val_2'
1101
+ end
1102
+ end
1103
+
1104
+ context "larger than #{described_class::MAX_SIZE}" do
1105
+ let(:size) { described_class::MAX_SIZE + 1 }
1106
+
1107
+ it 'sets empty value' do
1108
+ form.inputs['input_1'].should be_empty
1109
+ form.inputs['input_2'].should == 'val_2'
1110
+ end
1111
+ end
1112
+
1113
+ context "smaller than #{described_class::MAX_SIZE}" do
1114
+ let(:size) { described_class::MAX_SIZE - 1 }
1115
+
1116
+ it 'leaves the values alone' do
1117
+ form.inputs['input_1'].should == value
1118
+ form.inputs['input_2'].should == 'val_2'
1119
+ end
1120
+ end
1121
+ end
1079
1122
  end
1080
1123
  end
1081
1124
 
1082
1125
  describe '.encode' do
1083
1126
  it 'form-encodes the passed string' do
1084
- described_class.encode( '% value\ +=&;' ).should == '%25+value%5C+%2B%3D%26%3B'
1127
+ described_class.encode( '% value\ +=&;' ).should == '%25%20value%5C%20%2B%3D%26%3B'
1085
1128
  end
1086
1129
  end
1087
1130
  describe '#encode' do
@@ -1093,12 +1136,12 @@ EOHTML
1093
1136
 
1094
1137
  describe '.decode' do
1095
1138
  it 'form-decodes the passed string' do
1096
- described_class.decode( '%25+value%5C+%2B%3D%26%3B' ).should == '% value\ +=&;'
1139
+ described_class.decode( '%25%20value%5C%20%2B%3D%26%3B' ).should == '% value\ +=&;'
1097
1140
  end
1098
1141
  end
1099
1142
  describe '#decode' do
1100
1143
  it 'form-decodes the passed string' do
1101
- v = '%25+value%5C+%2B%3D%26%3B'
1144
+ v = '%25%20value%5C%20%2B%3D%26%3B'
1102
1145
  subject.decode( v ).should == described_class.decode( v )
1103
1146
  end
1104
1147
  end
@@ -517,6 +517,26 @@ describe Arachni::Element::JSON do
517
517
  context 'when there are no inputs' do
518
518
  it 'returns nil'
519
519
  end
520
+
521
+ context 'when it is' do
522
+ context "equal to #{described_class::MAX_SIZE}" do
523
+ let(:size) { described_class::MAX_SIZE }
524
+
525
+ it 'returns nil'
526
+ end
527
+
528
+ context "larger than #{described_class::MAX_SIZE}" do
529
+ let(:size) { described_class::MAX_SIZE + 1 }
530
+
531
+ it 'returns nil'
532
+ end
533
+
534
+ context "smaller than #{described_class::MAX_SIZE}" do
535
+ let(:size) { described_class::MAX_SIZE - 1 }
536
+
537
+ it 'leaves parses it'
538
+ end
539
+ end
520
540
  end
521
541
 
522
542
  end
@@ -43,15 +43,6 @@ describe Arachni::Element::Link::DOM do
43
43
  end
44
44
  end
45
45
 
46
- %w(encode decode).each do |m|
47
- describe "##{m}" do
48
- it "delegates to #{Arachni::Element::Link}.#{m}" do
49
- Arachni::Element::Link.stub(m) { |arg| "#{arg}1" }
50
- subject.send( m, 'blah' ).should == 'blah1'
51
- end
52
- end
53
- end
54
-
55
46
  describe '#parent' do
56
47
  it 'returns the parent element' do
57
48
  subject.parent.should be_kind_of Arachni::Element::Link
@@ -254,26 +254,51 @@ describe Arachni::Element::Link do
254
254
  end
255
255
  end
256
256
  end
257
- end
258
257
 
259
- describe '.encode_query_params' do
260
- it "encodes '='" do
261
- v = 'stuff='
262
- described_class.encode_query_params( v ).should == 'stuff%3D'
263
- end
264
- end
265
- describe '#encode_query_params' do
266
- it "encodes '='" do
267
- v = 'stuff='
268
- subject.encode_query_params( v ).should ==
269
- described_class.encode_query_params( v )
258
+ context 'when its value is' do
259
+ let(:link) { described_class.from_document( url, link_html ).first }
260
+ let(:value) { 'a' * size }
261
+ let(:href) { "test?param=#{value}" }
262
+ let(:link_html) do
263
+ tpl = '<html>
264
+ <body>
265
+ <a href="%s"></a>
266
+ </body>
267
+ </html>'
268
+
269
+ tpl % href[0...size]
270
+ end
271
+
272
+ context "equal to #{described_class::MAX_SIZE}" do
273
+ let(:size) { described_class::MAX_SIZE }
274
+
275
+ it 'returns empty array' do
276
+ link.should be_nil
277
+ end
278
+ end
279
+
280
+ context "larger than #{described_class::MAX_SIZE}" do
281
+ let(:size) { described_class::MAX_SIZE + 1 }
282
+
283
+ it 'sets empty value' do
284
+ link.should be_nil
285
+ end
286
+ end
287
+
288
+ context "smaller than #{described_class::MAX_SIZE}" do
289
+ let(:size) { described_class::MAX_SIZE - 1 }
290
+
291
+ it 'leaves the values alone' do
292
+ link.inputs['param'].should_not be_empty
293
+ end
294
+ end
270
295
  end
271
296
  end
272
297
 
273
298
  describe '.encode' do
274
299
  it 'URL-encodes the passed string' do
275
300
  v = '% value\ +=&;'
276
- described_class.encode( v ).should == URI.encode( v )
301
+ described_class.encode( v ).should == '%25%20value%5C%20%2B%3D%26%3B'
277
302
  end
278
303
  end
279
304
  describe '#encode' do
@@ -285,13 +310,13 @@ describe Arachni::Element::Link do
285
310
 
286
311
  describe '.decode' do
287
312
  it 'URL-decodes the passed string' do
288
- v = '%25+value%5C+%2B%3D%26%3B'
313
+ v = '%25%20value%5C%20%2B%3D%26%3B'
289
314
  described_class.decode( v ).should == URI.decode( v )
290
315
  end
291
316
  end
292
317
  describe '#decode' do
293
318
  it 'URL-decodes the passed string' do
294
- v = '%25+value%5C+%2B%3D%26%3B'
319
+ v = '%25%20value%5C%20%2B%3D%26%3B'
295
320
  subject.decode( v ).should == described_class.decode( v )
296
321
  end
297
322
  end
@@ -60,14 +60,6 @@ describe Arachni::Element::LinkTemplate::DOM do
60
60
  end
61
61
  end
62
62
 
63
- %w(encode decode).each do |m|
64
- describe "##{m}" do
65
- it 'returns the string as is' do
66
- subject.send( m, 'blah' ).should == 'blah'
67
- end
68
- end
69
- end
70
-
71
63
  describe '#parent' do
72
64
  it 'returns the parent element' do
73
65
  subject.parent.should be_kind_of Arachni::Element::LinkTemplate
@@ -215,12 +215,8 @@ describe Arachni::Element::LinkTemplate do
215
215
  end
216
216
 
217
217
  describe '.encode' do
218
- it "double encodes ';'" do
219
- described_class.encode( 'test;' ).should == 'test%253B'
220
- end
221
-
222
- it "double encodes '/'" do
223
- described_class.encode( 'test/' ).should == 'test%2F'
218
+ it 'URL-encodes the passed string' do
219
+ described_class.encode( 'test/;' ).should == 'test%2F%3B'
224
220
  end
225
221
  end
226
222
 
@@ -75,16 +75,30 @@ describe Arachni::Element::Server do
75
75
  name: 'Auditor',
76
76
  shortname: 'auditor_test'
77
77
  }
78
+ logged_issue.variations.first.proof.should ==
79
+ logged_issue.variations.first.page.response.status_line
80
+
78
81
  logged_issue.name.should == @auditor.class.info[:issue][:name]
79
82
  logged_issue.trusted.should be_true
80
83
  end
81
84
 
82
- it "does not push the response to the #{Arachni::Trainer}" do
83
- file = @base_url + 'true'
84
- auditable.log_remote_file_if_exists( file )
85
+ context 'when one issue is logged' do
86
+ it "does not push the response to the #{Arachni::Trainer}" do
87
+ auditable.log_remote_file_if_exists( @base_url + 'true' )
85
88
 
86
- @framework.trainer.should_not receive(:push)
87
- @framework.http.run
89
+ @framework.trainer.should_not receive(:push)
90
+ @framework.http.run
91
+ end
92
+ end
93
+
94
+ context 'when multiple issues are logged' do
95
+ it "pushes the responses to the #{Arachni::Trainer}" do
96
+ auditable.log_remote_file_if_exists( @base_url + 'true' )
97
+ auditable.log_remote_file_if_exists( "#{url}/each_candidate_dom_element" )
98
+
99
+ @framework.trainer.should receive(:push).twice
100
+ @framework.http.run
101
+ end
88
102
  end
89
103
  end
90
104
 
@@ -94,12 +108,41 @@ describe Arachni::Element::Server do
94
108
  @framework.http.run
95
109
  Arachni::Data.issues.should be_empty
96
110
  end
111
+
112
+ it "does not push the responses to the #{Arachni::Trainer}" do
113
+ auditable.log_remote_file_if_exists( @base_url + 'false' )
114
+
115
+ @framework.trainer.should_not receive(:push)
116
+ @framework.http.run
117
+ end
97
118
  end
98
119
 
99
120
  context 'when issues are too similar' do
121
+ let(:check_url) { @base_url + 'true' }
122
+
123
+ it 'flags them as untrusted' do
124
+ 10.times { auditable.log_remote_file_if_exists( check_url ) }
125
+ @framework.http.run
126
+
127
+ issues.should be_any
128
+ issues.each do |issue|
129
+ issue.should be_untrusted
130
+ end
131
+ end
132
+
133
+ it 'assigns a remark' do
134
+ 10.times { auditable.log_remote_file_if_exists( check_url ) }
135
+ @framework.http.run
136
+
137
+ issues.should be_any
138
+
139
+ issues.each do |issue|
140
+ issue.remarks[:meta_analysis].should == [described_class::REMARK]
141
+ end
142
+ end
143
+
100
144
  it "does not push the responses to the #{Arachni::Trainer}" do
101
- file = @base_url + 'true'
102
- 10.times { auditable.log_remote_file_if_exists( file ) }
145
+ 10.times { auditable.log_remote_file_if_exists( url ) }
103
146
 
104
147
  @framework.trainer.should_not receive(:push)
105
148
  @framework.http.run
@@ -125,11 +168,33 @@ describe Arachni::Element::Server do
125
168
  end
126
169
 
127
170
  context 'without a custom 404 handler' do
171
+ it 'performs fingerprinting' do
172
+ url = @base_url + 'true'
173
+
174
+ # We run this twice because the cache is empty the first time
175
+ # around so we don't know what kind of handler we're dealing with.
176
+
177
+ auditable.remote_file_exist?( url ) {}
178
+ @framework.http.run
179
+
180
+ request = nil
181
+ @framework.http.on_complete do |response|
182
+ next if url != response.url
183
+ request = response.request
184
+ end
185
+
186
+ auditable.remote_file_exist?( url ) {}
187
+ @framework.http.run
188
+
189
+ request.fingerprint?.should be_true
190
+ end
191
+
128
192
  context 'when a remote file exists' do
129
193
  it 'yields true' do
130
194
  exists = false
131
195
  auditable.remote_file_exist?( @base_url + 'true' ) { |bool| exists = bool }
132
196
  @framework.http.run
197
+ exists.should be_true
133
198
  end
134
199
 
135
200
  context 'on subsequent calls' do
@@ -165,9 +230,30 @@ describe Arachni::Element::Server do
165
230
  end
166
231
  end
167
232
 
168
- context 'without a custom 404 handler' do
233
+ context 'with a custom 404 handler' do
169
234
  before { @_404_url = @base_url + 'custom_404/' }
170
235
 
236
+ it 'does not perform fingerprinting' do
237
+ url = @_404_url + 'true'
238
+
239
+ # We run this twice because the cache is empty the first time
240
+ # around so we don't know what kind of handler we're dealing with.
241
+
242
+ auditable.remote_file_exist?( url ) {}
243
+ @framework.http.run
244
+
245
+ request = nil
246
+ @framework.http.on_complete do |response|
247
+ next if url != response.url
248
+ request = response.request
249
+ end
250
+
251
+ auditable.remote_file_exist?( url ) {}
252
+ @framework.http.run
253
+
254
+ request.fingerprint?.should be_false
255
+ end
256
+
171
257
  context 'and the response' do
172
258
  context 'is static' do
173
259
  it 'yields false' do