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
@@ -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