arachni 1.1 → 1.2

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.
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
@@ -42,6 +42,10 @@ describe Arachni::Browser do
42
42
  Typhoeus::Request.get( "#{@url}/hit-count" ).body.to_i
43
43
  end
44
44
 
45
+ def image_hit_count
46
+ Typhoeus::Request.get( "#{@url}/image-hit-count" ).body.to_i
47
+ end
48
+
45
49
  def clear_hit_count
46
50
  Typhoeus::Request.get( "#{@url}/clear-hit-count" )
47
51
  end
@@ -1011,7 +1015,7 @@ describe Arachni::Browser do
1011
1015
  @browser.load( @url )
1012
1016
  @browser.to_page.dom.instance_variable_get(:@digest).should ==
1013
1017
  '<HTML><HEAD><SCRIPT src=http://javascript.browser.arachni/' <<
1014
- 'taint_tracer.js><SCRIPT><SCRIPT src=http://javascript.' <<
1018
+ 'taint_tracer.js><SCRIPT src=http://javascript.' <<
1015
1019
  'browser.arachni/dom_monitor.js><SCRIPT><TITLE><BODY><' <<
1016
1020
  'DIV><SCRIPT type=text/javascript><SCRIPT type=text/javascript>'
1017
1021
  end
@@ -1871,6 +1875,104 @@ describe Arachni::Browser do
1871
1875
  @browser.source.should include( ua )
1872
1876
  end
1873
1877
 
1878
+ it 'puts the domain in the asset domains list' do
1879
+ subject.goto @url
1880
+ described_class.asset_domains.should include Arachni::URI( @url ).domain
1881
+ end
1882
+
1883
+ context 'when requesting the page URL' do
1884
+ it 'does not send If-None-Match request headers' do
1885
+ subject.goto "#{@url}/If-None-Match"
1886
+ subject.response.code.should == 200
1887
+ subject.response.request.headers.should_not include 'If-None-Match'
1888
+
1889
+ subject.goto "#{@url}/If-None-Match"
1890
+ subject.response.code.should == 200
1891
+ subject.response.request.headers.should_not include 'If-None-Match'
1892
+ end
1893
+
1894
+ it 'does not send If-Modified-Since request headers' do
1895
+ subject.goto "#{@url}/If-Modified-Since"
1896
+ subject.response.code.should == 200
1897
+ subject.response.request.headers.should_not include 'If-Modified-Since'
1898
+
1899
+ subject.goto "#{@url}/If-Modified-Since"
1900
+ subject.response.code.should == 200
1901
+ subject.response.request.headers.should_not include 'If-Modified-Since'
1902
+ end
1903
+ end
1904
+
1905
+ context 'when requesting something other than the page URL' do
1906
+ it 'sends If-None-Match request headers' do
1907
+ url = "#{@url}If-None-Match"
1908
+
1909
+ response = nil
1910
+ subject.on_response do |r|
1911
+ next if r.url == url
1912
+ response = r
1913
+ end
1914
+
1915
+ subject.goto url
1916
+ response.request.headers.should_not include 'If-None-Match'
1917
+
1918
+ subject.goto url
1919
+ response.request.headers.should include 'If-None-Match'
1920
+ end
1921
+
1922
+ it 'sends If-Modified-Since request headers' do
1923
+ url = "#{@url}If-Modified-Since"
1924
+
1925
+ response = nil
1926
+ subject.on_response do |r|
1927
+ next if r.url == url
1928
+ response = r
1929
+ end
1930
+
1931
+ subject.goto url
1932
+ response.request.headers.should_not include 'If-Modified-Since'
1933
+
1934
+ subject.goto url
1935
+ response.request.headers.should include 'If-Modified-Since'
1936
+ end
1937
+ end
1938
+
1939
+ context 'when the page requires an asset' do
1940
+ before do
1941
+ described_class.asset_domains.clear
1942
+ subject.goto url
1943
+ end
1944
+
1945
+ let(:url) { "#{@url}/asset_domains" }
1946
+
1947
+ %w(link input script img).each do |type|
1948
+ context 'via link' do
1949
+ let(:url) { "#{super()}/#{type}" }
1950
+
1951
+ it 'whitelists it' do
1952
+ described_class.asset_domains.should include "#{type}.stuff"
1953
+ end
1954
+ end
1955
+ end
1956
+
1957
+ context 'with an extension of' do
1958
+ described_class::ASSET_EXTENSIONS.each do |extension|
1959
+ context extension do
1960
+ it 'loads it'
1961
+ end
1962
+ end
1963
+ end
1964
+
1965
+ context 'without an extension' do
1966
+ context 'and has been whitelisted' do
1967
+ it 'loads it'
1968
+ end
1969
+
1970
+ context 'and has not been whitelisted' do
1971
+ it 'does not load it'
1972
+ end
1973
+ end
1974
+ end
1975
+
1874
1976
  context 'when the page has JS timeouts' do
1875
1977
  it 'waits for them to complete' do
1876
1978
  time = Time.now
@@ -1906,38 +2008,70 @@ describe Arachni::Browser do
1906
2008
  end
1907
2009
  end
1908
2010
 
2011
+ context "with #{Arachni::OptionGroups::BrowserCluster}#wait_for_elements" do
2012
+ before do
2013
+ Arachni::Options.browser_cluster.wait_for_elements = {
2014
+ 'stuff' => '#matchThis'
2015
+ }
2016
+ end
2017
+
2018
+ context 'when the URL matches a pattern' do
2019
+ it 'waits for the element matching the CSS to appear' do
2020
+ t = Time.now
2021
+ @browser.goto( @url + '/wait_for_elements#stuff/here' )
2022
+ (Time.now - t).should > 5
2023
+
2024
+ @browser.watir.element( css: '#matchThis' ).tag_name.should == 'button'
2025
+ end
2026
+
2027
+ it "waits a maximum of #{Arachni::OptionGroups::BrowserCluster}#job_timeout" do
2028
+ Arachni::Options.browser_cluster.job_timeout = 4
2029
+
2030
+ t = Time.now
2031
+ @browser.goto( @url + '/wait_for_elements#stuff/here' )
2032
+ (Time.now - t).should < 5
2033
+
2034
+ expect do
2035
+ @browser.watir.element( css: '#matchThis' ).tag_name
2036
+ end.to raise_error Watir::Exception::UnknownObjectException
2037
+ end
2038
+ end
2039
+
2040
+ context 'when the URL does not match any patterns' do
2041
+ it 'does not wait' do
2042
+ t = Time.now
2043
+ @browser.goto( @url + '/wait_for_elements' )
2044
+ (Time.now - t).should < 5
2045
+
2046
+ expect do
2047
+ @browser.watir.element( css: '#matchThis' ).tag_name
2048
+ end.to raise_error Watir::Exception::UnknownObjectException
2049
+ end
2050
+ end
2051
+ end
2052
+
1909
2053
  context "#{Arachni::OptionGroups::BrowserCluster}#ignore_images" do
1910
2054
  context true do
1911
2055
  it 'does not load images' do
1912
2056
  Arachni::Options.browser_cluster.ignore_images = true
1913
2057
  @browser.shutdown
1914
- @browser = described_class.new
1915
-
1916
- loaded_image = false
1917
- @browser.on_response do |response|
1918
- loaded_image ||= (response.parsed_url.resource_extension == 'png')
1919
- end
2058
+ @browser = described_class.new( disk_cache: false )
1920
2059
 
1921
2060
  @browser.load( "#{@url}form-with-image-button" )
1922
2061
 
1923
- loaded_image.should be_false
2062
+ image_hit_count.should == 0
1924
2063
  end
1925
2064
  end
1926
2065
 
1927
2066
  context false do
1928
- it 'does not load images' do
2067
+ it 'loads images' do
1929
2068
  Arachni::Options.browser_cluster.ignore_images = false
1930
2069
  @browser.shutdown
1931
- @browser = described_class.new
1932
-
1933
- loaded_image = false
1934
- @browser.on_response do |response|
1935
- loaded_image ||= (response.parsed_url.resource_extension == 'png')
1936
- end
2070
+ @browser = described_class.new( disk_cache: false )
1937
2071
 
1938
2072
  @browser.load( "#{@url}form-with-image-button" )
1939
2073
 
1940
- loaded_image.should be_true
2074
+ image_hit_count.should == 1
1941
2075
  end
1942
2076
  end
1943
2077
  end
@@ -1986,21 +2120,20 @@ describe Arachni::Browser do
1986
2120
  transition.options[:cookies].should == cookie
1987
2121
  end
1988
2122
 
1989
- context 'when auditing existing cookies' do
1990
- it 'preserves the HttpOnly attribute' do
1991
- @browser.goto( @url )
1992
- @browser.cookies.size.should == 1
2123
+ context 'when auditing existing cookies' do
2124
+ it 'preserves the HttpOnly attribute' do
2125
+ @browser.goto( @url )
2126
+ @browser.cookies.size.should == 1
1993
2127
 
1994
- cookies = { @browser.cookies.first.name => 'updated' }
1995
- @browser.goto( @url, cookies: cookies )
2128
+ cookies = { @browser.cookies.first.name => 'updated' }
2129
+ @browser.goto( @url, cookies: cookies )
1996
2130
 
1997
- @browser.cookies.first.value == 'updated'
1998
- @browser.cookies.first.should be_http_only
2131
+ @browser.cookies.first.value == 'updated'
2132
+ @browser.cookies.first.should be_http_only
2133
+ end
1999
2134
  end
2000
2135
  end
2001
2136
 
2002
- end
2003
-
2004
2137
  describe :take_snapshot do
2005
2138
  describe true do
2006
2139
  it 'captures a snapshot of the loaded page' do
@@ -2512,6 +2645,17 @@ describe Arachni::Browser do
2512
2645
  @browser.cookies.first.should be_http_only
2513
2646
  end
2514
2647
 
2648
+ context 'when parsing v1 cookies' do
2649
+ it 'removes the quotes' do
2650
+ cookie = 'rsession="06142010_0%3Ae275d357943e9a2de0"'
2651
+
2652
+ @browser.load @url
2653
+ @browser.javascript.run( "document.cookie = '#{cookie}';" )
2654
+
2655
+ @browser.cookies.first.value.should == '06142010_0:e275d357943e9a2de0'
2656
+ end
2657
+ end
2658
+
2515
2659
  context 'when no page is available' do
2516
2660
  it 'returns an empty Array' do
2517
2661
  @browser.cookies.should be_empty
@@ -202,10 +202,13 @@ describe Arachni::Check::Auditor do
202
202
  element_classes.each do |element|
203
203
  context "when #{Arachni::OptionGroups::Audit}##{element.type.to_s.gsub( '_dom', '')}? is" do
204
204
  let(:page) do
205
- Arachni::Page.from_data(
205
+ p = Arachni::Page.from_data(
206
206
  url: url,
207
207
  "#{element.type}s".gsub( '_dom', '').to_sym => [Factory[element.type]]
208
208
  )
209
+ p.dom.stub(:depth) { 1 }
210
+ p.stub(:has_script?) { true }
211
+ p
209
212
  end
210
213
  before(:each) { auditor.class.info[:elements] = [element] }
211
214
 
@@ -226,6 +229,22 @@ describe Arachni::Check::Auditor do
226
229
  if element == Arachni::Element::Form::DOM ||
227
230
  element == Arachni::Element::Cookie::DOM
228
231
 
232
+ context 'and Page::DOM#depth is' do
233
+ context '0' do
234
+ it 'returns false' do
235
+ page.dom.stub(:depth) { 0 }
236
+ auditor.class.check?( page ).should be_false
237
+ end
238
+ end
239
+
240
+ context '> 0' do
241
+ it 'returns true' do
242
+ page.dom.stub(:depth) { 1 }
243
+ auditor.class.check?( page ).should be_true
244
+ end
245
+ end
246
+ end
247
+
229
248
  context 'and Page#has_script? is' do
230
249
  context true do
231
250
  it 'returns true' do
@@ -587,13 +606,13 @@ describe Arachni::Check::Auditor do
587
606
  logged_issue = Arachni::Data.issues.flatten.first
588
607
 
589
608
  logged_issue.to_h.tap do |h|
590
- h[:page][:dom][:transitions].first.delete :time
609
+ h[:page][:dom][:transitions].each { |t| t.delete :time }
591
610
  end.should eq issue.to_h.merge( referring_page: {
592
611
  body: auditor.page.body,
593
612
  dom: auditor.page.dom.to_h.tap do |h|
594
613
  h.delete :skip_states
595
614
  end
596
- }).tap { |h| h[:page][:dom][:transitions].first.delete :time }
615
+ }).tap { |h| h[:page][:dom][:transitions].each { |t| t.delete :time } }
597
616
  end
598
617
 
599
618
  it 'assigns a #referring_page' do
@@ -53,6 +53,28 @@ describe Arachni::Check::Base do
53
53
  end
54
54
  end
55
55
 
56
+ describe '#has_exempt_platforms?' do
57
+ context 'when exempt platforms are provided' do
58
+ before do
59
+ described_class.stub(:info) { { exempt_platforms: [ :unix ] } }
60
+ end
61
+
62
+ it 'returns true' do
63
+ described_class.has_exempt_platforms?.should be_true
64
+ end
65
+ end
66
+
67
+ context 'when exempt platforms are not provided' do
68
+ before do
69
+ described_class.stub(:info) { { exempt_platforms: [] } }
70
+ end
71
+
72
+ it 'returns false' do
73
+ described_class.has_exempt_platforms?.should be_false
74
+ end
75
+ end
76
+ end
77
+
56
78
  describe '#supports_platforms?' do
57
79
  context 'when empty platforms are given' do
58
80
  it 'returns true' do
@@ -80,6 +102,16 @@ describe Arachni::Check::Base do
80
102
  end
81
103
  end
82
104
 
105
+ context 'when any of the given platforms are exempt' do
106
+ before do
107
+ described_class.stub(:info) { { exempt_platforms: [:php] } }
108
+ end
109
+
110
+ it 'returns false' do
111
+ described_class.supports_platforms?([:unix, :php]).should be_false
112
+ end
113
+ end
114
+
83
115
  context 'when a parent of any of the given platforms is supported' do
84
116
  before do
85
117
  described_class.stub(:info) { { platforms: [:unix] } }
@@ -90,6 +122,17 @@ describe Arachni::Check::Base do
90
122
  end
91
123
  end
92
124
 
125
+ context 'when a parent of any of the given platforms is exempt' do
126
+ before do
127
+ described_class.stub(:info) { { exempt_platforms: [:unix] } }
128
+ end
129
+
130
+ it 'returns false' do
131
+ described_class.supports_platforms?([:linux]).should be_false
132
+ end
133
+ end
134
+
135
+
93
136
  context 'when a child of any of the given platforms is supported' do
94
137
  before do
95
138
  described_class.stub(:info) { { platforms: [:linux] } }
@@ -100,6 +143,16 @@ describe Arachni::Check::Base do
100
143
  end
101
144
  end
102
145
 
146
+ context 'when a child of any of the given platforms is exempt' do
147
+ before do
148
+ described_class.stub(:info) { { exempt_platforms: [:linux] } }
149
+ end
150
+
151
+ it 'returns false' do
152
+ described_class.supports_platforms?([:unix]).should be_false
153
+ end
154
+ end
155
+
103
156
  context 'when none of the given platforms are not provided' do
104
157
  before do
105
158
  described_class.stub(:info) { { platforms: [:windows] } }
@@ -109,5 +162,36 @@ describe Arachni::Check::Base do
109
162
  described_class.supports_platforms?([:unix]).should be_false
110
163
  end
111
164
  end
165
+
166
+ context 'when none of the given platforms are exempt' do
167
+ before do
168
+ described_class.stub(:info) { { exempt_platforms: [:windows] } }
169
+ end
170
+
171
+ it 'returns true' do
172
+ described_class.supports_platforms?([:unix]).should be_true
173
+ end
174
+ end
175
+
176
+ context 'when any of the given platforms are exempt' do
177
+ before do
178
+ described_class.stub(:info) { { exempt_platforms: [:windows, :linux] } }
179
+ end
180
+
181
+ it 'returns false' do
182
+ described_class.supports_platforms?([:unix]).should be_false
183
+ end
184
+ end
185
+
186
+ context 'when a platforms of different type is exempt' do
187
+ before do
188
+ described_class.stub(:info) { { exempt_platforms: [:windows] } }
189
+ end
190
+
191
+ it 'returns true' do
192
+ described_class.supports_platforms?([:ruby]).should be_true
193
+ end
194
+ end
195
+
112
196
  end
113
197
  end
@@ -42,7 +42,7 @@ describe Arachni::Element::Body do
42
42
 
43
43
  logged_issue.vector.url.should == Arachni::Utilities.normalize_url( @url )
44
44
  logged_issue.vector.class.should == Arachni::Element::Body
45
- logged_issue.signature.should == valid_pattern.to_s
45
+ logged_issue.signature.should == valid_pattern.source
46
46
  logged_issue.proof.should == 'Match'
47
47
  logged_issue.trusted.should be_true
48
48
  end
@@ -109,7 +109,7 @@ describe Arachni::Element::Capabilities::Analyzable::Taint do
109
109
 
110
110
  issues.size.should == 1
111
111
  issues[0].platform_name.should == :windows
112
- issues[0].signature.should == regexps[:windows].to_s
112
+ issues[0].signature.should == regexps[:windows].source
113
113
  end
114
114
 
115
115
  context 'when the payloads are per platform' do
@@ -148,7 +148,7 @@ describe Arachni::Element::Capabilities::Analyzable::Taint do
148
148
 
149
149
  issue.vector.seed.should == payloads[platform]
150
150
  issue.platform_name.should == platform
151
- issue.signature.should == regexps[platform].to_s
151
+ issue.signature.should == regexps[platform].source
152
152
  end
153
153
  end
154
154
 
@@ -177,7 +177,7 @@ describe Arachni::Element::Capabilities::Analyzable::Taint do
177
177
  issue = issues.first
178
178
 
179
179
  issue.platform_name.should == :asp
180
- issue.signature.should == regexps[:asp].to_s
180
+ issue.signature.should == regexps[:asp].source
181
181
  end
182
182
  end
183
183
  end