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
@@ -1,6 +1,24 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Arachni::HTTP::Headers do
4
+
5
+ context 'when it includes multiple same names that differ in case' do
6
+ subject do
7
+ described_class.new( cookies )
8
+ end
9
+ let(:cookies) do
10
+ {
11
+ 'set-cookie' => 'mycookie1=myvalue1',
12
+ 'Set-Cookie' => 'mycookie2=myvalue2',
13
+ 'SET-COOKIE' => 'mycookie3=myvalue3'
14
+ }
15
+ end
16
+
17
+ it 'merges them into an array' do
18
+ subject['set-cookie'].should == cookies.values
19
+ end
20
+ end
21
+
4
22
  describe '#delete' do
5
23
  it 'deleted a header field' do
6
24
  h = described_class.new( 'x-my-field' => 'stuff' )
@@ -98,6 +98,29 @@ describe Arachni::HTTP::Request do
98
98
  r.parameters.should == { 'test' => 'blah' }
99
99
  end
100
100
 
101
+ describe :fingerprint do
102
+ context true do
103
+ it 'enables fingerprinting' do
104
+ r = described_class.new( options.merge( fingerprint: true ) )
105
+ r.fingerprint?.should be_true
106
+ end
107
+ end
108
+
109
+ context false do
110
+ it 'disables fingerprinting' do
111
+ r = described_class.new( options.merge( fingerprint: false ) )
112
+ r.fingerprint?.should_not be_true
113
+ end
114
+ end
115
+
116
+ context 'nil' do
117
+ it 'enables fingerprinting' do
118
+ r = described_class.new( options.merge( fingerprint: nil ) )
119
+ r.fingerprint?.should be_true
120
+ end
121
+ end
122
+ end
123
+
101
124
  context 'when url is not a String' do
102
125
  it 'raises ArgumentError' do
103
126
  raised = false
@@ -242,11 +242,22 @@ describe Arachni::Issue do
242
242
  end
243
243
 
244
244
  describe '#signature=' do
245
- it 'assigns a signature as a String' do
246
- signature = /test.*/
245
+ context 'when it is a Regexp' do
246
+ it 'stores the source' do
247
+ signature = /test.*/
247
248
 
248
- empty_issue.signature = signature
249
- empty_issue.signature.should == signature.to_s
249
+ empty_issue.signature = signature
250
+ empty_issue.signature.should == signature.source
251
+ end
252
+ end
253
+
254
+ context 'when it is a String' do
255
+ it 'stores it' do
256
+ signature = 'stuff'
257
+
258
+ empty_issue.signature = signature
259
+ empty_issue.signature.should == signature
260
+ end
250
261
  end
251
262
 
252
263
  context 'when no signature has been given' do
@@ -396,7 +407,7 @@ describe Arachni::Issue do
396
407
  remedy_code: 'Sample code on how to fix the issue',
397
408
  tags: %w(these are a few tags),
398
409
  remarks: { the_dude: %w(Hey!) },
399
- signature: '(?-mix:some regexp)',
410
+ signature: 'some regexp',
400
411
  proof: "string matched by '/some regexp/'",
401
412
  check: {
402
413
  name: 'Test check',
@@ -523,7 +534,7 @@ describe Arachni::Issue do
523
534
  },
524
535
  response: issue.response.to_h,
525
536
  remarks: { the_dude: %w(Hey!) },
526
- signature: '(?-mix:some regexp)',
537
+ signature: 'some regexp',
527
538
  proof: "string matched by '/some regexp/'",
528
539
  trusted: true,
529
540
  request: issue.request.to_h,
@@ -468,7 +468,7 @@ describe Arachni::Page do
468
468
  context 'elements with event attributes' do
469
469
  it 'returns true' do
470
470
  create_page(
471
- body: '<a onmouseover="doStuff();">Stuff</a>',
471
+ body: '<a onMouseOver="doStuff();">Stuff</a>',
472
472
  headers: { 'content-type' => 'text/html' }
473
473
  ).has_script?.should be_true
474
474
  end
@@ -476,7 +476,7 @@ describe Arachni::Page do
476
476
  context 'anchors with javacript: in href' do
477
477
  it 'returns true' do
478
478
  create_page(
479
- body: '<a href="javascript:doStuff();">Stuff</a>',
479
+ body: '<a href="JavaScript:doStuff();">Stuff</a>',
480
480
  headers: { 'content-type' => 'text/html' }
481
481
  ).has_script?.should be_true
482
482
  end
@@ -497,6 +497,26 @@ describe Arachni::Page do
497
497
  end
498
498
  end
499
499
 
500
+ describe '#has_elements?' do
501
+ context 'when the page has any of the given elements' do
502
+ it 'returns true' do
503
+ create_page(
504
+ body: '<fOrM></form>',
505
+ headers: { 'content-type' => 'text/html' }
506
+ ).has_elements?( 'form', 'script' ).should be_true
507
+ end
508
+ end
509
+
510
+ context 'when the page has none of the given elements' do
511
+ it 'returns false' do
512
+ create_page(
513
+ body: '<fOrM></form>',
514
+ headers: { 'content-type' => 'text/html' }
515
+ ).has_elements?( 'a', 'script' ).should be_false
516
+ end
517
+ end
518
+ end
519
+
500
520
  describe '#text?' do
501
521
  context 'when the HTTP response is text/html' do
502
522
  it 'returns true' do
@@ -495,6 +495,11 @@ describe Arachni::Parser do
495
495
  it 'returns an array of headers' do
496
496
  subject.headers.each { |h| h.class.should == Arachni::Element::Header }
497
497
  end
498
+
499
+ it 'includes headers from the HTTP request' do
500
+ subject.response.request.headers['X-Custom-Header'] = 'My-stuff'
501
+ subject.headers.find { |h| h.name == 'X-Custom-Header' }.should be_true
502
+ end
498
503
  end
499
504
 
500
505
  describe '#link_vars' do
@@ -74,7 +74,7 @@ describe Arachni::Platform::Manager do
74
74
 
75
75
  describe '.clear' do
76
76
  it 'clear all platforms' do
77
- described_class.update( 'http://test/', [:unix, :jsp] )
77
+ described_class.update( 'http://test/', [:unix, :java] )
78
78
  described_class.should be_any
79
79
  described_class.clear
80
80
  described_class.should be_empty
@@ -94,8 +94,17 @@ describe Arachni::Platform::Manager do
94
94
  context 'and it is text based' do
95
95
  context 'and has not yet been fingerprinted' do
96
96
  context 'and is within scope' do
97
- it 'returns true' do
98
- described_class.fingerprint?( page ).should be_true
97
+ context 'and has a #code of 200' do
98
+ it 'returns true' do
99
+ described_class.fingerprint?( page ).should be_true
100
+ end
101
+ end
102
+
103
+ context 'and has a non-200 #code' do
104
+ it 'returns false' do
105
+ page.stub(:code) { 404 }
106
+ described_class.fingerprint?( page ).should be_false
107
+ end
99
108
  end
100
109
  end
101
110
 
@@ -144,6 +153,16 @@ describe Arachni::Platform::Manager do
144
153
  it 'returns the given page' do
145
154
  described_class.fingerprint( page ).should == page
146
155
  end
156
+
157
+ context 'even when no platforms have been identified' do
158
+ it 'marks the page as fingerprinted' do
159
+ page = Arachni::Page.from_url( web_server_url_for( :auditor ) )
160
+
161
+ described_class.fingerprint( page )
162
+ page.platforms.should be_empty
163
+ described_class.fingerprint?( page ).should be_false
164
+ end
165
+ end
147
166
  end
148
167
 
149
168
  describe '.[]' do
@@ -151,7 +170,7 @@ describe Arachni::Platform::Manager do
151
170
  base = 'http://stuff.com/'
152
171
  uri = base + '?stuff=here'
153
172
 
154
- platforms << :unix << :jsp
173
+ platforms << :unix << :java
155
174
  described_class[uri] = platforms
156
175
  described_class[uri].should == platforms
157
176
  described_class[base].should == described_class[uri]
@@ -175,7 +194,7 @@ describe Arachni::Platform::Manager do
175
194
  base = 'http://stuff.com/'
176
195
  uri = base + '?stuff=here'
177
196
 
178
- platforms << :unix << :jsp
197
+ platforms << :unix << :java
179
198
 
180
199
  described_class[uri] = platforms
181
200
  described_class[uri].should == platforms
@@ -183,7 +202,7 @@ describe Arachni::Platform::Manager do
183
202
  end
184
203
 
185
204
  it 'set the platforms for the given URI' do
186
- platforms = [:unix, :jsp]
205
+ platforms = [:unix, :java]
187
206
  described_class['http://stuff.com'] = platforms
188
207
 
189
208
  platforms.each do |platform|
@@ -192,13 +211,23 @@ describe Arachni::Platform::Manager do
192
211
  end
193
212
 
194
213
  it "converts the value to a #{described_class}" do
195
- platforms = [:unix, :jsp]
214
+ platforms = [:unix, :java]
196
215
  described_class['http://stuff.com'] = platforms
197
216
  platforms.each do |platform|
198
217
  described_class['http://stuff.com'].should be_kind_of described_class
199
218
  end
200
219
  end
201
220
 
221
+ it 'includes Options.platforms' do
222
+ Arachni::Options.platforms = [:ruby, :windows]
223
+ platforms = [:unix, :java]
224
+
225
+ described_class['http://stuff.com'] = platforms
226
+
227
+ described_class['http://stuff.com'].sort.should ==
228
+ (Arachni::Options.platforms | platforms).sort
229
+ end
230
+
202
231
  context 'when invalid platforms are given' do
203
232
  it 'raises Arachni::Platform::Error::Invalid' do
204
233
  expect {
@@ -212,8 +241,8 @@ describe Arachni::Platform::Manager do
212
241
  context 'with valid platforms' do
213
242
  it 'updates self with the given platforms' do
214
243
  described_class['http://test.com/'] << :unix
215
- described_class.update( 'http://test.com/', [:jsp] )
216
- described_class['http://test.com/'].sort.should == [:unix, :jsp].sort
244
+ described_class.update( 'http://test.com/', [:java] )
245
+ described_class['http://test.com/'].sort.should == [:unix, :java].sort
217
246
  end
218
247
  end
219
248
  context 'with invalid platforms' do
@@ -252,19 +281,21 @@ describe Arachni::Platform::Manager do
252
281
  end
253
282
  end
254
283
 
284
+ describe '#new_from_options' do
285
+ it 'includes Options.platforms' do
286
+ Arachni::Options.platforms = [:ruby, :windows]
287
+ platforms = [:unix, :java]
288
+
289
+ described_class.new_from_options( platforms ).sort.should ==
290
+ (platforms | Arachni::Options.platforms).sort
291
+ end
292
+ end
293
+
255
294
  describe '#initialize' do
256
295
  it 'initializes the manager with the given platforms' do
257
- platforms = [:unix, :jsp, :mysql].sort
296
+ platforms = [:unix, :java, :mysql].sort
258
297
  described_class.new( platforms ).sort.should == platforms
259
298
  end
260
-
261
- context 'when there are Options.platforms' do
262
- it 'takes them into account' do
263
- platforms = [:unix]
264
- Arachni::Options.platforms = [:php, :mysql]
265
- described_class.new( platforms ).sort.should == (Arachni::Options.platforms | platforms).sort
266
- end
267
- end
268
299
  end
269
300
 
270
301
  describe '#os' do
@@ -314,7 +345,7 @@ describe Arachni::Platform::Manager do
314
345
  unix: [ 'UNIX stuff' ],
315
346
  php: [ 'PHP stuff' ]
316
347
  }
317
- data = applicable_data.merge( jsp: [ 'JSP stuff' ],
348
+ data = applicable_data.merge( java: [ 'JSP stuff' ],
318
349
  windows: [ 'Windows stuff' ] )
319
350
 
320
351
  platforms << :unix << :php
@@ -326,7 +357,7 @@ describe Arachni::Platform::Manager do
326
357
  linux: [ 'UNIX stuff' ],
327
358
  bsd: [ 'UNIX stuff' ],
328
359
  php: [ 'PHP stuff' ],
329
- jsp: [ 'JSP stuff' ]
360
+ java: [ 'JSP stuff' ]
330
361
  }
331
362
  data = applicable_data.merge( windows: [ 'Windows stuff' ] )
332
363
 
@@ -358,7 +389,7 @@ describe Arachni::Platform::Manager do
358
389
  linux: [ 'Linux stuff' ],
359
390
  php: [ 'PHP stuff' ]
360
391
  }
361
- data = applicable_data.merge( jsp: [ 'JSP stuff' ],
392
+ data = applicable_data.merge( java: [ 'JSP stuff' ],
362
393
  windows: [ 'Windows stuff' ] )
363
394
 
364
395
  platforms << :linux << :php << :unix
@@ -386,15 +417,16 @@ describe Arachni::Platform::Manager do
386
417
  [:unix, :linux, :bsd, :solaris, :windows,
387
418
  :db2, :emc, :informix, :interbase, :mssql, :mysql,
388
419
  :oracle, :firebird, :maxdb, :pgsql, :sqlite, :apache, :iis, :nginx,
389
- :tomcat, :asp, :aspx, :jsp, :perl, :php, :python, :ruby, :rack,
420
+ :tomcat, :asp, :aspx, :java, :perl, :php, :python, :ruby, :rack,
390
421
  :sybase, :frontbase, :ingres, :hsqldb, :access, :jetty, :mongodb,
391
- :aix, :sql, :nosql].sort
422
+ :aix, :sql, :nosql, :aspx_mvc, :rails, :django, :gunicorn, :cakephp,
423
+ :cherrypy, :jsf].sort
392
424
  end
393
425
  end
394
426
 
395
427
  describe '#each' do
396
428
  it 'iterates over all applicable platforms' do
397
- included_platforms = platforms.update( [:unix, :jsp] ).sort
429
+ included_platforms = platforms.update( [:unix, :java] ).sort
398
430
  included_platforms.should be_any
399
431
 
400
432
  iterated = []
@@ -408,7 +440,7 @@ describe Arachni::Platform::Manager do
408
440
 
409
441
  describe '#clear' do
410
442
  it 'clear the platforms' do
411
- platforms.update( [:unix, :jsp] )
443
+ platforms.update( [:unix, :java] )
412
444
  platforms.should be_any
413
445
  platforms.clear
414
446
  platforms.should be_empty
@@ -26,6 +26,32 @@ describe Arachni::Reporter::Manager do
26
26
  reporter.options.should == options.my_symbolize_keys(false)
27
27
  end
28
28
  end
29
+
30
+ context 'when the raise argument is'do
31
+ context 'not given' do
32
+ context 'and the report raises an exception' do
33
+ it 'does not raise it' do
34
+ expect { @reporters.run( :error, report ) }.to_not raise_error
35
+ end
36
+ end
37
+ end
38
+
39
+ context false do
40
+ context 'and the report raises an exception' do
41
+ it 'does not raise it' do
42
+ expect { @reporters.run( :error, report, {}, false ) }.to_not raise_error
43
+ end
44
+ end
45
+ end
46
+
47
+ context true do
48
+ context 'and the report raises an exception' do
49
+ it 'does not raise it' do
50
+ expect { @reporters.run( :error, report, {}, true ) }.to raise_error
51
+ end
52
+ end
53
+ end
54
+ end
29
55
  end
30
56
 
31
57
  describe '#reset' do
@@ -24,8 +24,11 @@ describe Arachni::RPC::Server::ActiveOptions do
24
24
  },
25
25
  'datastore' => { 'key' => 'val' },
26
26
  'http' => {
27
- 'cookies' => { 'name' => 'value' },
28
- 'cookie_string' => 'name3=value3'
27
+ 'cookies' => {
28
+ 'name' => 'value',
29
+ 'name2' => 'value2'
30
+ },
31
+ 'cookie_string' => 'name3=value3;name4=value4'
29
32
  }
30
33
  }
31
34
 
@@ -44,8 +47,10 @@ describe Arachni::RPC::Server::ActiveOptions do
44
47
  h['datastore'].should == opts['datastore']
45
48
 
46
49
  @instance.service.cookies.map { |c| Arachni::Cookie.from_rpc_data c }.should == [
47
- Arachni::Cookie.new( url: opts['url'], inputs: opts['http']['cookies'] ),
48
- Arachni::Cookie.new( url: opts['url'], inputs: { name3: 'value3' } )
50
+ Arachni::Cookie.new( url: opts['url'], inputs: { 'name' => 'value' } ),
51
+ Arachni::Cookie.new( url: opts['url'], inputs: { 'name2' => 'value2' } ),
52
+ Arachni::Cookie.new( url: opts['url'], inputs: { 'name3' => 'value3' } ),
53
+ Arachni::Cookie.new( url: opts['url'], inputs: { 'name4' => 'value4' } )
49
54
  ]
50
55
  end
51
56
  end
@@ -52,8 +52,8 @@ describe Arachni::State::Framework do
52
52
  context Symbol do
53
53
  context 'and it exists in #available_status_messages' do
54
54
  it 'pushes the associated message to #status_messages' do
55
- subject.add_status_message :pausing
56
- subject.status_messages.should == [subject.available_status_messages[:pausing]]
55
+ subject.add_status_message :suspending
56
+ subject.status_messages.should == [subject.available_status_messages[:suspending]]
57
57
  end
58
58
  end
59
59
 
@@ -633,12 +633,6 @@ describe Arachni::State::Framework do
633
633
  subject.status.should == :pausing
634
634
  end
635
635
 
636
- it 'sets the status message to :pausing' do
637
- subject.pause( :a_caller, false )
638
- subject.status_messages.should ==
639
- [subject.available_status_messages[:pausing]]
640
- end
641
-
642
636
  it 'returns true' do
643
637
  subject.pause( :a_caller, false ).should be_true
644
638
  end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe Arachni::Support::Cache::LeastRecentlyPushed do
4
+ it_behaves_like 'cache'
5
+
6
+ it 'prunes itself by removing Least Recently Pushed entries' do
7
+ subject.max_size = 3
8
+
9
+ subject[:k] = '1'
10
+ subject[:k2] = '2'
11
+ subject[:k3] = '3'
12
+ subject[:k4] = '4'
13
+ subject.size.should == 3
14
+
15
+ subject[:k4].should be_true
16
+ subject[:k3].should be_true
17
+ subject[:k2].should be_true
18
+ subject[:k].should be_nil
19
+
20
+ subject.clear
21
+
22
+ subject.max_size = 1
23
+ subject[:k] = '1'
24
+ subject[:k2] = '3'
25
+ subject[:k3] = '4'
26
+ subject.size.should == 1
27
+
28
+ subject[:k3].should be_true
29
+ subject[:k2].should be_nil
30
+ subject[:k].should be_nil
31
+ end
32
+
33
+ describe '#[]=' do
34
+ it 'stores an object' do
35
+ v = 'val'
36
+ (subject[:key] = v).should == v
37
+ subject[:key].should == v
38
+ end
39
+ it 'alias of #store' do
40
+ v = 'val2'
41
+ subject.store( :key2, v ).should == v
42
+ subject[:key2].should == v
43
+ end
44
+ end
45
+
46
+ describe '#[]' do
47
+ it 'retrieves an object by key' do
48
+ v = 'val2'
49
+ subject[:key] = v
50
+ subject[:key].should == v
51
+ subject.empty?.should be_false
52
+ end
53
+
54
+ context 'when the key does not exist' do
55
+ it 'returns nil' do
56
+ subject[:some_key].should be_nil
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '#delete' do
62
+ context 'when the key exists' do
63
+ it 'deletes a key and return its value' do
64
+ v = 'my_val'
65
+ subject[:my_key] = v
66
+ subject.delete( :my_key ).should == v
67
+ subject[:my_key].should be_nil
68
+ subject.include?( :my_key ).should be_false
69
+ end
70
+ end
71
+ context 'when the key does not exist' do
72
+ it 'returns nil' do
73
+ subject.delete( :my_key2 ).should be_nil
74
+ end
75
+ end
76
+ end
77
+
78
+ describe '#clear' do
79
+ it 'empties the cache' do
80
+ subject[:my_key2] = 'v'
81
+ subject.size.should > 0
82
+ subject.empty?.should be_false
83
+ subject.clear
84
+
85
+ subject.size.should == 0
86
+ subject.empty?.should be_true
87
+ end
88
+ end
89
+
90
+ end