arachni 1.2.1 → 1.3

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 (373) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -0
  3. data/Gemfile +1 -1
  4. data/README.md +16 -5
  5. data/components/checks/active/ldap_injection/errors.txt +1 -0
  6. data/components/checks/active/source_code_disclosure.rb +1 -1
  7. data/components/checks/active/unvalidated_redirect.rb +6 -6
  8. data/components/checks/active/unvalidated_redirect_dom.rb +10 -7
  9. data/components/checks/passive/grep/captcha.rb +14 -5
  10. data/components/checks/passive/grep/form_upload.rb +7 -3
  11. data/components/checks/passive/grep/hsts.rb +3 -3
  12. data/components/checks/passive/grep/html_objects.rb +2 -3
  13. data/components/checks/passive/grep/http_only_cookies.rb +2 -3
  14. data/components/checks/passive/grep/insecure_cookies.rb +1 -1
  15. data/components/checks/passive/grep/password_autocomplete.rb +2 -2
  16. data/components/checks/passive/grep/unencrypted_password_forms.rb +7 -7
  17. data/components/checks/passive/grep/x_frame_options.rb +2 -2
  18. data/components/checks/passive/http_put.rb +2 -3
  19. data/components/path_extractors/comments.rb +3 -3
  20. data/components/path_extractors/scripts.rb +10 -1
  21. data/components/plugins/defaults/autothrottle.rb +27 -18
  22. data/components/plugins/defaults/meta/remedies/discovery.rb +30 -33
  23. data/components/plugins/defaults/meta/remedies/timing_attacks.rb +7 -11
  24. data/components/plugins/login_script.rb +9 -3
  25. data/components/plugins/proxy.rb +4 -3
  26. data/components/reporters/html.rb +11 -14
  27. data/components/reporters/html/default/issue.erb +13 -38
  28. data/components/reporters/html/default/issue/info.erb +1 -1
  29. data/components/reporters/html/default/summary/issues/by_name.erb +3 -3
  30. data/components/reporters/stdout.rb +62 -71
  31. data/components/reporters/xml.rb +26 -40
  32. data/components/reporters/xml/schema.xsd +43 -89
  33. data/lib/arachni/browser.rb +52 -3
  34. data/lib/arachni/browser/javascript.rb +3 -3
  35. data/lib/arachni/browser/javascript/scripts/taint_tracer.js +46 -25
  36. data/lib/arachni/browser_cluster.rb +61 -0
  37. data/lib/arachni/browser_cluster/job.rb +21 -1
  38. data/lib/arachni/browser_cluster/jobs/browser_provider.rb +3 -1
  39. data/lib/arachni/browser_cluster/jobs/resource_exploration.rb +2 -1
  40. data/lib/arachni/browser_cluster/jobs/resource_exploration/event_trigger.rb +2 -1
  41. data/lib/arachni/browser_cluster/jobs/taint_trace.rb +3 -2
  42. data/lib/arachni/browser_cluster/jobs/taint_trace/event_trigger.rb +1 -1
  43. data/lib/arachni/browser_cluster/worker.rb +5 -0
  44. data/lib/arachni/check/auditor.rb +22 -12
  45. data/lib/arachni/data/framework.rb +13 -1
  46. data/lib/arachni/data/issues.rb +9 -25
  47. data/lib/arachni/element/base.rb +9 -3
  48. data/lib/arachni/element/capabilities/analyzable.rb +2 -6
  49. data/lib/arachni/element/capabilities/analyzable/differential.rb +24 -7
  50. data/lib/arachni/element/capabilities/analyzable/{taint.rb → signature.rb} +23 -23
  51. data/lib/arachni/element/capabilities/auditable.rb +0 -6
  52. data/lib/arachni/element/capabilities/dom_only.rb +61 -0
  53. data/lib/arachni/element/capabilities/with_dom.rb +3 -1
  54. data/lib/arachni/element/cookie.rb +35 -5
  55. data/lib/arachni/element/cookie/dom.rb +13 -4
  56. data/lib/arachni/element/{capabilities/auditable/dom.rb → dom.rb} +20 -68
  57. data/lib/arachni/element/dom/capabilities/auditable.rb +29 -0
  58. data/lib/arachni/element/dom/capabilities/inputtable.rb +27 -0
  59. data/lib/arachni/element/dom/capabilities/mutable.rb +21 -0
  60. data/lib/arachni/element/dom/capabilities/submittable.rb +52 -0
  61. data/lib/arachni/element/form.rb +12 -1
  62. data/lib/arachni/element/form/capabilities/mutable.rb +2 -1
  63. data/lib/arachni/element/form/capabilities/with_dom.rb +0 -1
  64. data/lib/arachni/element/form/dom.rb +9 -3
  65. data/lib/arachni/element/header.rb +14 -33
  66. data/lib/arachni/element/header/capabilities/inputtable.rb +29 -0
  67. data/lib/arachni/element/header/capabilities/mutable.rb +51 -0
  68. data/lib/arachni/element/input/dom.rb +71 -0
  69. data/lib/arachni/element/json.rb +2 -0
  70. data/lib/arachni/element/link.rb +3 -0
  71. data/lib/arachni/element/link/capabilities/with_dom.rb +0 -1
  72. data/lib/arachni/element/link/dom.rb +16 -3
  73. data/lib/arachni/element/link/dom/capabilities/submittable.rb +29 -0
  74. data/lib/arachni/element/link_template.rb +3 -5
  75. data/lib/arachni/element/link_template/capabilities/inputtable.rb +5 -0
  76. data/lib/arachni/element/link_template/capabilities/with_dom.rb +0 -1
  77. data/lib/arachni/element/link_template/dom.rb +16 -3
  78. data/lib/arachni/element/link_template/dom/capabilities/submittable.rb +29 -0
  79. data/lib/arachni/element/server.rb +3 -5
  80. data/lib/arachni/element/ui_form.rb +106 -0
  81. data/lib/arachni/element/ui_form/dom.rb +107 -0
  82. data/lib/arachni/element/ui_input.rb +62 -0
  83. data/lib/arachni/element/xml.rb +2 -1
  84. data/lib/arachni/framework.rb +7 -5
  85. data/lib/arachni/framework/parts/audit.rb +0 -1
  86. data/lib/arachni/framework/parts/check.rb +1 -0
  87. data/lib/arachni/framework/parts/data.rb +4 -0
  88. data/lib/arachni/framework/parts/state.rb +0 -2
  89. data/lib/arachni/http/client.rb +17 -6
  90. data/lib/arachni/http/proxy_server.rb +52 -5
  91. data/lib/arachni/http/request.rb +1 -1
  92. data/lib/arachni/issue.rb +34 -179
  93. data/lib/arachni/issue/severity.rb +2 -0
  94. data/lib/arachni/option_groups/audit.rb +22 -2
  95. data/lib/arachni/option_groups/browser_cluster.rb +15 -0
  96. data/lib/arachni/page.rb +3 -2
  97. data/lib/arachni/parser.rb +24 -5
  98. data/lib/arachni/platform/manager.rb +1 -2
  99. data/lib/arachni/rpc/server/framework.rb +3 -4
  100. data/lib/arachni/rpc/server/framework/multi_instance.rb +2 -1
  101. data/lib/arachni/session.rb +1 -1
  102. data/lib/arachni/trainer.rb +4 -7
  103. data/lib/arachni/watir/element.rb +12 -1
  104. data/lib/version +1 -1
  105. data/spec/arachni/browser/element_locator_spec.rb +43 -43
  106. data/spec/arachni/browser/javascript/dom_monitor_spec.rb +44 -44
  107. data/spec/arachni/browser/javascript/proxy/stub_spec.rb +17 -14
  108. data/spec/arachni/browser/javascript/proxy_spec.rb +24 -24
  109. data/spec/arachni/browser/javascript/taint_tracer/frame/called_function_spec.rb +11 -11
  110. data/spec/arachni/browser/javascript/taint_tracer/frame_spec.rb +7 -7
  111. data/spec/arachni/browser/javascript/taint_tracer/sink/data_flow_spec.rb +13 -13
  112. data/spec/arachni/browser/javascript/taint_tracer/sink/execution_flow_spec.rb +7 -7
  113. data/spec/arachni/browser/javascript/taint_tracer_spec.rb +568 -558
  114. data/spec/arachni/browser/javascript_spec.rb +73 -63
  115. data/spec/arachni/browser_cluster/job/result_spec.rb +3 -3
  116. data/spec/arachni/browser_cluster/job_spec.rb +68 -48
  117. data/spec/arachni/browser_cluster/jobs/resource_exploration/event_trigger/result_spec.rb +2 -2
  118. data/spec/arachni/browser_cluster/jobs/resource_exploration/event_trigger_spec.rb +5 -4
  119. data/spec/arachni/browser_cluster/jobs/resource_exploration/result_spec.rb +2 -2
  120. data/spec/arachni/browser_cluster/jobs/resource_exploration_spec.rb +5 -5
  121. data/spec/arachni/browser_cluster/worker_spec.rb +87 -70
  122. data/spec/arachni/browser_cluster_spec.rb +64 -39
  123. data/spec/arachni/browser_spec.rb +692 -527
  124. data/spec/arachni/check/auditor_spec.rb +177 -147
  125. data/spec/arachni/check/base_spec.rb +33 -33
  126. data/spec/arachni/check/manager_spec.rb +15 -15
  127. data/spec/arachni/component/base_spec.rb +8 -8
  128. data/spec/arachni/component/manager_spec.rb +100 -99
  129. data/spec/arachni/component/options/address_spec.rb +3 -3
  130. data/spec/arachni/component/options/base_spec.rb +7 -7
  131. data/spec/arachni/component/options/bool_spec.rb +9 -9
  132. data/spec/arachni/component/options/float_spec.rb +6 -6
  133. data/spec/arachni/component/options/int_spec.rb +5 -5
  134. data/spec/arachni/component/options/multiple_choice_spec.rb +12 -12
  135. data/spec/arachni/component/options/object_spec.rb +2 -2
  136. data/spec/arachni/component/options/path_spec.rb +3 -3
  137. data/spec/arachni/component/options/port_spec.rb +5 -5
  138. data/spec/arachni/component/options/string_spec.rb +3 -3
  139. data/spec/arachni/component/options/url_spec.rb +4 -4
  140. data/spec/arachni/component/utilities_spec.rb +2 -2
  141. data/spec/arachni/data/framework/rpc_spec.rb +10 -9
  142. data/spec/arachni/data/framework_spec.rb +65 -46
  143. data/spec/arachni/data/issues_spec.rb +39 -77
  144. data/spec/arachni/data/plugins_spec.rb +11 -11
  145. data/spec/arachni/data/session_spec.rb +6 -6
  146. data/spec/arachni/data_spec.rb +8 -8
  147. data/spec/arachni/element/body_spec.rb +10 -10
  148. data/spec/arachni/element/capabilities/analyzable/differential_spec.rb +39 -21
  149. data/spec/arachni/element/capabilities/analyzable/{taint_spec.rb → signature_spec.rb} +63 -63
  150. data/spec/arachni/element/capabilities/analyzable/timeout_spec.rb +51 -51
  151. data/spec/arachni/element/capabilities/with_scope/scope_spec.rb +5 -5
  152. data/spec/arachni/element/cookie/dom_spec.rb +37 -18
  153. data/spec/arachni/element/cookie_spec.rb +206 -139
  154. data/spec/arachni/element/form/dom_spec.rb +36 -19
  155. data/spec/arachni/element/form_spec.rb +210 -187
  156. data/spec/arachni/element/generic_dom_spec.rb +14 -14
  157. data/spec/arachni/element/header_spec.rb +35 -17
  158. data/spec/arachni/element/json_spec.rb +53 -31
  159. data/spec/arachni/element/link/dom_spec.rb +46 -28
  160. data/spec/arachni/element/link_spec.rb +58 -40
  161. data/spec/arachni/element/link_template/dom_spec.rb +47 -29
  162. data/spec/arachni/element/link_template_spec.rb +79 -61
  163. data/spec/arachni/element/path_spec.rb +1 -1
  164. data/spec/arachni/element/server_spec.rb +33 -32
  165. data/spec/arachni/element/ui_form/ui_form_dom_spec.rb +164 -0
  166. data/spec/arachni/element/ui_form_spec.rb +242 -0
  167. data/spec/arachni/element/ui_input/dom_spec.rb +157 -0
  168. data/spec/arachni/element/ui_input_spec.rb +136 -0
  169. data/spec/arachni/element/xml_spec.rb +42 -24
  170. data/spec/arachni/element_filter_spec.rb +49 -48
  171. data/spec/arachni/error_spec.rb +3 -3
  172. data/spec/arachni/framework/parts/audit_spec.rb +64 -63
  173. data/spec/arachni/framework/parts/browser_spec.rb +16 -16
  174. data/spec/arachni/framework/parts/check_spec.rb +3 -3
  175. data/spec/arachni/framework/parts/data_spec.rb +48 -48
  176. data/spec/arachni/framework/parts/platform_spec.rb +3 -3
  177. data/spec/arachni/framework/parts/plugin_spec.rb +7 -6
  178. data/spec/arachni/framework/parts/report_spec.rb +7 -7
  179. data/spec/arachni/framework/parts/scope_spec.rb +16 -16
  180. data/spec/arachni/framework/parts/state_spec.rb +68 -69
  181. data/spec/arachni/framework_spec.rb +39 -31
  182. data/spec/arachni/http/client/dynamic_404_handlers_spec.rb +32 -32
  183. data/spec/arachni/http/client_spec.rb +219 -208
  184. data/spec/arachni/http/cookie_jar_spec.rb +72 -72
  185. data/spec/arachni/http/headers_spec.rb +14 -14
  186. data/spec/arachni/http/proxy_server_spec.rb +43 -42
  187. data/spec/arachni/http/request_spec.rb +105 -103
  188. data/spec/arachni/http/response/scope_spec.rb +24 -24
  189. data/spec/arachni/http/response_spec.rb +50 -49
  190. data/spec/arachni/issue/severity_spec.rb +10 -9
  191. data/spec/arachni/issue_spec.rb +71 -369
  192. data/spec/arachni/option_groups/audit_spec.rb +114 -114
  193. data/spec/arachni/option_groups/browser_cluster_spec.rb +20 -3
  194. data/spec/arachni/option_groups/datastore_spec.rb +6 -6
  195. data/spec/arachni/option_groups/dispatcher_spec.rb +19 -19
  196. data/spec/arachni/option_groups/http_spec.rb +11 -11
  197. data/spec/arachni/option_groups/input_spec.rb +31 -27
  198. data/spec/arachni/option_groups/output_spec.rb +2 -2
  199. data/spec/arachni/option_groups/paths_spec.rb +17 -17
  200. data/spec/arachni/option_groups/rpc_spec.rb +2 -2
  201. data/spec/arachni/option_groups/scope_spec.rb +40 -40
  202. data/spec/arachni/option_groups/session_spec.rb +6 -5
  203. data/spec/arachni/option_groups/snapshot_spec.rb +4 -4
  204. data/spec/arachni/options_spec.rb +46 -45
  205. data/spec/arachni/page/dom/transition_spec.rb +74 -72
  206. data/spec/arachni/page/dom_spec.rb +35 -35
  207. data/spec/arachni/page/scope_spec.rb +15 -15
  208. data/spec/arachni/page_spec.rb +217 -217
  209. data/spec/arachni/parser_spec.rb +106 -104
  210. data/spec/arachni/platform/fingerprinter_spec.rb +17 -14
  211. data/spec/arachni/platform/list_spec.rb +33 -33
  212. data/spec/arachni/platform/manager_spec.rb +67 -64
  213. data/spec/arachni/plugin/base_spec.rb +10 -10
  214. data/spec/arachni/plugin/manager_spec.rb +38 -37
  215. data/spec/arachni/report_spec.rb +43 -40
  216. data/spec/arachni/reporter/base_spec.rb +15 -15
  217. data/spec/arachni/reporter/manager_spec.rb +4 -4
  218. data/spec/arachni/reporter/options_spec.rb +6 -6
  219. data/spec/arachni/rpc/client/base_spec.rb +6 -6
  220. data/spec/arachni/rpc/client/dispatcher_spec.rb +2 -2
  221. data/spec/arachni/rpc/client/instance_spec.rb +6 -6
  222. data/spec/arachni/rpc/server/active_options_spec.rb +11 -8
  223. data/spec/arachni/rpc/server/base_spec.rb +5 -5
  224. data/spec/arachni/rpc/server/checks/manager_spec.rb +8 -8
  225. data/spec/arachni/rpc/server/dispatcher/node_spec.rb +37 -37
  226. data/spec/arachni/rpc/server/dispatcher/service_spec.rb +15 -14
  227. data/spec/arachni/rpc/server/dispatcher_spec.rb +36 -35
  228. data/spec/arachni/rpc/server/framework/distributor_spec.rb +36 -36
  229. data/spec/arachni/rpc/server/framework_multi_spec.rb +340 -336
  230. data/spec/arachni/rpc/server/framework_spec.rb +90 -85
  231. data/spec/arachni/rpc/server/instance_spec.rb +126 -107
  232. data/spec/arachni/rpc/server/output_spec.rb +1 -1
  233. data/spec/arachni/rpc/server/plugin/manager_spec.rb +6 -6
  234. data/spec/arachni/ruby/array_spec.rb +42 -42
  235. data/spec/arachni/ruby/hash_spec.rb +20 -18
  236. data/spec/arachni/ruby/io_spec.rb +2 -2
  237. data/spec/arachni/ruby/object_spec.rb +1 -1
  238. data/spec/arachni/ruby/set_spec.rb +3 -3
  239. data/spec/arachni/ruby/string_spec.rb +30 -30
  240. data/spec/arachni/ruby/webrick_spec.rb +2 -2
  241. data/spec/arachni/scope_spec.rb +1 -1
  242. data/spec/arachni/session_spec.rb +67 -64
  243. data/spec/arachni/snapshot_spec.rb +15 -15
  244. data/spec/arachni/state/audit_spec.rb +11 -11
  245. data/spec/arachni/state/element_filter_spec.rb +6 -6
  246. data/spec/arachni/state/framework/rpc_spec.rb +12 -12
  247. data/spec/arachni/state/framework_spec.rb +125 -121
  248. data/spec/arachni/state/http_spec.rb +7 -7
  249. data/spec/arachni/state/options_spec.rb +7 -7
  250. data/spec/arachni/state/plugins_spec.rb +8 -8
  251. data/spec/arachni/state_spec.rb +10 -10
  252. data/spec/arachni/support/buffer/autoflush_spec.rb +16 -16
  253. data/spec/arachni/support/buffer/base_spec.rb +39 -39
  254. data/spec/arachni/support/cache/least_cost_replacement_spec.rb +18 -18
  255. data/spec/arachni/support/cache/least_recently_pushed_spec.rb +24 -24
  256. data/spec/arachni/support/cache/least_recently_used_spec.rb +20 -20
  257. data/spec/arachni/support/cache/preference_spec.rb +4 -4
  258. data/spec/arachni/support/cache/random_replacement_spec.rb +8 -8
  259. data/spec/arachni/support/crypto/rsa_aes_cbc_spec.rb +1 -1
  260. data/spec/arachni/support/database/hash_spec.rb +44 -43
  261. data/spec/arachni/support/database/queue_spec.rb +27 -27
  262. data/spec/arachni/support/lookup/hash_set_spec.rb +8 -8
  263. data/spec/arachni/support/lookup/moolb_spec.rb +3 -3
  264. data/spec/arachni/support/mixins/observable_spec.rb +6 -6
  265. data/spec/arachni/support/signature_spec.rb +19 -19
  266. data/spec/arachni/trainer_spec.rb +39 -39
  267. data/spec/arachni/typhoeus/hydra_spec.rb +2 -2
  268. data/spec/arachni/uri/scope_spec.rb +66 -66
  269. data/spec/arachni/uri_spec.rb +107 -105
  270. data/spec/arachni/utilities_spec.rb +40 -40
  271. data/spec/components/checks/active/csrf_spec.rb +8 -8
  272. data/spec/components/checks/active/no_sql_injection_spec.rb +1 -1
  273. data/spec/components/checks/active/sql_injection_spec.rb +16 -16
  274. data/spec/components/checks/active/trainer_spec.rb +4 -4
  275. data/spec/components/checks/active/unvalidated_redirect_dom_spec.rb +4 -2
  276. data/spec/components/checks/active/xpath_injection_spec.rb +1 -1
  277. data/spec/components/checks/active/xss_dom_script_context_spec.rb +51 -21
  278. data/spec/components/checks/active/xss_dom_spec.rb +46 -24
  279. data/spec/components/checks/passive/allowed_methods_spec.rb +1 -1
  280. data/spec/components/checks/passive/grep/cookie_set_for_parent_domain_spec.rb +1 -1
  281. data/spec/components/checks/passive/grep/hsts_spec.rb +2 -2
  282. data/spec/components/checks/passive/grep/http_only_cookies_spec.rb +1 -1
  283. data/spec/components/checks/passive/grep/insecure_cookies_spec.rb +1 -1
  284. data/spec/components/checks/passive/grep/insecure_cors_policy_spec.rb +2 -2
  285. data/spec/components/checks/passive/grep/password_autocomplete_spec.rb +1 -1
  286. data/spec/components/checks/passive/grep/private_ip_spec.rb +3 -3
  287. data/spec/components/checks/passive/grep/unencrypted_password_forms_spec.rb +1 -1
  288. data/spec/components/checks/passive/grep/x_frame_options_spec.rb +2 -2
  289. data/spec/components/checks/passive/interesting_responses_spec.rb +2 -2
  290. data/spec/components/checks/passive/webdav_spec.rb +1 -1
  291. data/spec/components/checks/passive/xst_spec.rb +1 -1
  292. data/spec/components/fingerprinters/servers/apache_spec.rb +2 -2
  293. data/spec/components/path_extractors/comments_spec.rb +5 -1
  294. data/spec/components/path_extractors/scripts_spec.rb +5 -2
  295. data/spec/components/plugins/autologin_spec.rb +22 -22
  296. data/spec/components/plugins/autothrottle_spec.rb +6 -5
  297. data/spec/components/plugins/content_types_spec.rb +4 -4
  298. data/spec/components/plugins/cookie_collector_spec.rb +5 -5
  299. data/spec/components/plugins/exec_spec.rb +12 -12
  300. data/spec/components/plugins/form_dicattack_spec.rb +3 -3
  301. data/spec/components/plugins/headers_collector_spec.rb +8 -8
  302. data/spec/components/plugins/healthmap_spec.rb +3 -3
  303. data/spec/components/plugins/http_dicattack_spec.rb +3 -3
  304. data/spec/components/plugins/login_script_spec.rb +79 -22
  305. data/spec/components/plugins/meta/remedies/discovery_spec.rb +3 -2
  306. data/spec/components/plugins/meta/remedies/timing_attacks_spec.rb +3 -3
  307. data/spec/components/plugins/meta/uniformity_spec.rb +2 -2
  308. data/spec/components/plugins/restrict_to_dom_state_spec.rb +1 -1
  309. data/spec/components/plugins/script_spec.rb +1 -1
  310. data/spec/components/plugins/uncommon_headers_spec.rb +2 -2
  311. data/spec/components/plugins/vector_collector_spec.rb +2 -2
  312. data/spec/components/plugins/vector_feed_spec.rb +40 -40
  313. data/spec/components/plugins/waf_detector_spec.rb +6 -6
  314. data/spec/components/reporters/json_spec.rb +4 -4
  315. data/spec/components/reporters/marshal_spec.rb +2 -2
  316. data/spec/components/reporters/yaml_spec.rb +3 -2
  317. data/spec/external/wavsep/active/sqli_spec.rb +1 -3
  318. data/spec/spec_helper.rb +4 -0
  319. data/spec/support/factories/element/ui_form.rb +14 -0
  320. data/spec/support/factories/element/ui_input.rb +13 -0
  321. data/spec/support/factories/issue.rb +0 -13
  322. data/spec/support/fixtures/report.afr +0 -0
  323. data/spec/support/fixtures/{taint_check/taint.rb → signature_check/signature.rb} +2 -2
  324. data/spec/support/helpers/browser_cluster/jobs/taint_tracer.rb +11 -11
  325. data/spec/support/helpers/framework.rb +1 -1
  326. data/spec/support/helpers/pages.rb +2 -2
  327. data/spec/support/servers/arachni/browser.rb +139 -0
  328. data/spec/support/servers/arachni/browser/javascript/taint_tracer.rb +40 -0
  329. data/spec/support/servers/arachni/element/capabilities/analyzable/{taint.rb → signature.rb} +0 -0
  330. data/spec/support/servers/arachni/element/input/input_dom.rb +102 -0
  331. data/spec/support/servers/arachni/element/ui_form/ui_form_dom.rb +238 -0
  332. data/spec/support/servers/checks/active/trainer_check.rb +7 -7
  333. data/spec/support/servers/checks/active/unvalidated_redirect_dom.rb +22 -6
  334. data/spec/support/servers/checks/active/xss_dom.rb +50 -0
  335. data/spec/support/servers/checks/active/xss_dom_script_context.rb +53 -0
  336. data/spec/support/shared/browser/javascript/taint_tracer/sink/base.rb +6 -6
  337. data/spec/support/shared/check.rb +10 -12
  338. data/spec/support/shared/component/options/base.rb +24 -24
  339. data/spec/support/shared/element/base.rb +25 -25
  340. data/spec/support/shared/element/capabilities/auditable.rb +116 -140
  341. data/spec/support/shared/element/capabilities/dom_only.rb +65 -0
  342. data/spec/support/shared/element/capabilities/inputtable.rb +71 -86
  343. data/spec/support/shared/element/capabilities/mutable.rb +122 -111
  344. data/spec/support/shared/element/capabilities/refreshable.rb +10 -10
  345. data/spec/support/shared/element/capabilities/{submitable.rb → submittable.rb} +26 -26
  346. data/spec/support/shared/element/capabilities/with_auditor.rb +10 -10
  347. data/spec/support/shared/element/capabilities/with_dom.rb +8 -8
  348. data/spec/support/shared/element/capabilities/with_node.rb +4 -6
  349. data/spec/support/shared/element/capabilities/with_scope.rb +2 -2
  350. data/spec/support/shared/element/capabilities/with_source.rb +6 -8
  351. data/spec/support/shared/element/dom.rb +144 -0
  352. data/spec/support/shared/element/dom/auditable.rb +42 -0
  353. data/spec/support/shared/element/dom/inputtable.rb +5 -0
  354. data/spec/support/shared/element/dom/mutable.rb +3 -0
  355. data/spec/support/shared/element/dom/submittable.rb +119 -0
  356. data/spec/support/shared/external/wavsep.rb +3 -3
  357. data/spec/support/shared/fingerprinter.rb +2 -2
  358. data/spec/support/shared/framework.rb +1 -1
  359. data/spec/support/shared/http/message.rb +9 -9
  360. data/spec/support/shared/option_group.rb +17 -17
  361. data/spec/support/shared/path_extractor.rb +1 -1
  362. data/spec/support/shared/plugin.rb +2 -2
  363. data/spec/support/shared/support/cache.rb +57 -57
  364. data/spec/support/shared/support/lookup.rb +25 -25
  365. data/ui/cli/framework.rb +22 -11
  366. data/ui/cli/framework/option_parser.rb +15 -0
  367. data/ui/cli/option_parser.rb +8 -1
  368. data/ui/cli/output.rb +2 -1
  369. metadata +54 -20
  370. data/components/checks/active/xss_dom_inputs.rb +0 -236
  371. data/spec/components/checks/active/xss_dom_inputs_spec.rb +0 -30
  372. data/spec/support/servers/checks/active/xss_dom_inputs.rb +0 -59
  373. data/spec/support/shared/element/capabilities/auditable/dom.rb +0 -322
@@ -1,236 +0,0 @@
1
- =begin
2
- Copyright 2010-2015 Tasos Laskos <tasos.laskos@arachni-scanner.com>
3
-
4
- This file is part of the Arachni Framework project and is subject to
5
- redistribution and commercial restrictions. Please see the Arachni Framework
6
- web site for more information on licensing and terms of use.
7
- =end
8
-
9
- # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
10
- # @version 0.2
11
- class Arachni::Checks::XssDomInputs < Arachni::Check::Base
12
-
13
- INPUTS = Set.new([:input, :textarea])
14
-
15
- def tag_name
16
- "some_dangerous_input_#{random_seed}"
17
- end
18
-
19
- def tag
20
- # The trailing space is important, keypress and keyup events are always
21
- # one character short.
22
- "<#{tag_name}></#{tag_name}> "
23
- end
24
-
25
- def run
26
- return if !page.document
27
-
28
- # Everything past this point requires inputs to be present.
29
- return if !page.has_elements?( INPUTS.to_a )
30
-
31
- # Fill in inputs and trigger their associated events.
32
- trigger_inputs
33
-
34
- return if !page.has_elements?( :button )
35
-
36
- # Fill in inputs and hit buttons.
37
- trigger_buttons
38
- end
39
-
40
- def trigger_inputs
41
- with_browser do |browser|
42
- browser.load( page ).each_element_with_events do |locator, events|
43
-
44
- locator_id = "#{page.url}:#{locator.css}"
45
- next if !INPUTS.include?( locator.tag_name ) || audited?( locator_id )
46
- audited locator_id
47
-
48
- filter_events( locator.tag_name, events ).each do |event, _|
49
-
50
- print_status "Scheduling '#{event}' on '#{locator}'"
51
-
52
- # Instead of working with the same browser we do it this way
53
- # in order to distribute the workload via the browser cluster.
54
- with_browser do |b|
55
- print_status "Triggering '#{event}' on '#{locator}'"
56
-
57
- b.javascript.taint = self.tag_name
58
- b.load page
59
-
60
- transition = b.fire_event( locator, event, value: self.tag )
61
- if !transition
62
- print_bad "Could not '#{event}' on '#{locator}'"
63
- next
64
- end
65
-
66
- # Page may be out of scope, some sort of JS redirection.
67
- if !(p = b.to_page)
68
- print_bad "Could not capture page snapshot after '#{event}' on '#{locator}'"
69
- end
70
-
71
- p.dom.transitions << transition
72
-
73
- check_and_log( p )
74
-
75
- print_status "Finished '#{event}' on '#{locator}'"
76
- end
77
- end
78
- end
79
- end
80
- end
81
-
82
- def trigger_buttons
83
- with_browser do |browser|
84
- browser.load( page ).each_element_with_events do |locator, events|
85
-
86
- locator_id = "#{page.url}:#{locator.css}"
87
- next if locator.tag_name != :button || audited?( locator_id )
88
- audited locator_id
89
-
90
- events.each do |event, _|
91
- print_status "Scheduling '#{event}' on '#{locator}' after filling in inputs"
92
-
93
- with_browser do |b|
94
- print_status "Triggering '#{event}' on '#{locator}' after filling in inputs"
95
-
96
- b.javascript.taint = self.tag_name
97
- b.load page
98
-
99
- transitions = fill_in_inputs( b )
100
- if transitions.empty?
101
- print_bad "Could not fill in any inputs for '#{event}' on '#{locator}'"
102
- next
103
- end
104
-
105
- transition = b.fire_event( locator, event )
106
- if !transition
107
- print_bad "Could not '#{event}' on '#{locator}'"
108
- next
109
- end
110
-
111
- transitions << transition
112
-
113
- # Page may be out of scope, some sort of JS redirection.
114
- if !(p = b.to_page)
115
- print_bad "Could not capture page snapshot after '#{event}' on '#{locator}'"
116
- end
117
-
118
- transitions.each do |t|
119
- p.dom.transitions << t
120
- end
121
-
122
- check_and_log( p )
123
-
124
- print_status "Finished '#{event}' on '#{locator}' after filling in inputs"
125
- end
126
- end
127
- end
128
- end
129
- end
130
-
131
- def fill_in_inputs( browser )
132
- transitions = []
133
-
134
- INPUTS.each do |tag|
135
- browser.watir.send("#{tag}s").each do |locator|
136
- print_status "Filling in '#{locator.opening_tag}'"
137
-
138
- transitions << fill_in_input( browser, locator )
139
- end
140
- end
141
-
142
- transitions.compact
143
- end
144
-
145
- def fill_in_input( browser, locator )
146
- browser.fire_event( locator, :input, value: self.tag )
147
- end
148
-
149
- def check_and_log( page )
150
- return if !(proof = find_proof( page ))
151
-
152
- log(
153
- vector: Element::GenericDOM.new(
154
- url: page.url,
155
- transition: page.dom.transitions.last
156
- ),
157
- proof: proof,
158
- page: page
159
- )
160
- end
161
-
162
- def find_proof( page )
163
- return if !page.has_elements?( self.tag_name )
164
-
165
- proof = page.document.css( self.tag_name )
166
- return if proof.empty?
167
-
168
- proof.to_s
169
- end
170
-
171
- def filter_events( element, events )
172
- supported = Set.new( Arachni::Browser::Javascript.events_for( element ) )
173
- events.reject { |name, _| !supported.include? ('on' + name.to_s.gsub( /^on/, '' )).to_sym }
174
- end
175
-
176
- def self.info
177
- {
178
- name: 'DOM XSS via input field',
179
- description: %q{
180
- Injects an HTML element into page text fields, triggers their associated events
181
- and inspects the DOM for proof of vulnerability.
182
- },
183
- author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
184
- version: '0.2',
185
- elements: [Element::GenericDOM],
186
-
187
- issue: {
188
- name: %q{DOM-based Cross-Site Scripting (XSS) via input fields},
189
- description: %q{
190
- Client-side scripts are used extensively by modern web applications.
191
- They perform from simple functions (such as the formatting of text) up to full
192
- manipulation of client-side data and Operating System interaction.
193
-
194
- Unlike traditional Cross-Site Scripting (XSS), where the client is able to inject
195
- scripts into a request and have the server return the script to the client, DOM
196
- XSS does not require that a request be sent to the server and may be abused entirely
197
- within the loaded page.
198
-
199
- This occurs when elements of the DOM (known as the sources) are able to be
200
- manipulated to contain untrusted data, which the client-side scripts (known as the
201
- sinks) use or execute an unsafe way.
202
-
203
- Arachni has discovered that by inserting an HTML element into the pages DOM inputs
204
- (sources) it was possible to then have the HTML element rendered as part of the
205
- page by the sink.
206
- },
207
- references: {
208
- 'WASC' => 'http://projects.webappsec.org/w/page/13246920/Cross%20Site%20Scripting',
209
- 'OWASP' => 'https://www.owasp.org/index.php/DOM_Based_XSS',
210
- 'OWASP - Prevention' => 'https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet'
211
- },
212
- tags: %w(xss dom injection script),
213
- cwe: 79,
214
- severity: Severity::HIGH,
215
- remedy_guidance: %q{
216
- Client-side document rewriting, redirection, or other sensitive action, using
217
- untrusted data, should be avoided wherever possible, as these may not be inspected
218
- by server side filtering.
219
-
220
- To remedy DOM XSS vulnerabilities where these sensitive document actions must be
221
- used, it is essential to:
222
-
223
- 1. Ensure any untrusted data is treated as text, as opposed to being interpreted
224
- as code or mark-up within the page.
225
- 2. Escape untrusted data prior to being used within the page. Escaping methods
226
- will vary depending on where the untrusted data is being used.
227
- (See references for details.)
228
- 3. Use `document.createElement`, `element.setAttribute`, `element.appendChild`,
229
- etc. to build dynamic interfaces as opposed to HTML rendering methods such as
230
- `document.write`, `document.writeIn`, `element.innerHTML`, or `element.outerHTML `etc.
231
- }
232
- }
233
- }
234
- end
235
-
236
- end
@@ -1,30 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe name_from_filename do
4
- include_examples 'check'
5
-
6
- def self.elements
7
- [Element::GenericDOM]
8
- end
9
-
10
- def issue_count_per_element
11
- {
12
- Element::GenericDOM => 9
13
- }
14
- end
15
-
16
- def find_issue( event )
17
- issues.find do |issue|
18
- "on#{issue.vector.method}" == event.to_s
19
- end
20
- end
21
-
22
- easy_test do
23
- issues.select { |i| i.vector.type == :input }.size.should == 8
24
- issues.select { |i| i.vector.type == :button }.size.should == 1
25
-
26
- Arachni::Browser::Javascript::EVENTS_PER_ELEMENT[:input].each do |event|
27
- find_issue( event ).vector.action.should end_with event.to_s
28
- end
29
- end
30
- end
@@ -1,59 +0,0 @@
1
- require 'sinatra'
2
- require 'sinatra/contrib'
3
- require_relative '../../../../../lib/arachni'
4
-
5
- EVENTS = Arachni::Browser::Javascript::EVENTS_PER_ELEMENT[:input]
6
-
7
- get '/' do
8
- html = '<html><body>'
9
-
10
- EVENTS.each do |event|
11
- html << "<a href='/#{event}'>#{event}</a>"
12
- end
13
-
14
- html << "<a href='/with_button'>With button</a>"
15
- html + '</body></html>'
16
- end
17
-
18
- EVENTS.each do |event|
19
- get "/#{event}" do
20
- <<-EOHTML
21
- <html>
22
- <script>
23
- function handle#{event}() {
24
- document.getElementById("container").innerHTML =
25
- document.getElementById("my-input").value;
26
- }
27
- </script>
28
-
29
- <body>
30
- <input #{event}="handle#{event}();" id="my-input" name="my-input" />
31
-
32
- <div id="container">
33
- </div>
34
- </body>
35
- </html>
36
- EOHTML
37
- end
38
- end
39
-
40
- get '/with_button' do
41
- <<-EOHTML
42
- <html>
43
- <body>
44
- <input id="my-input" type="text">
45
- <button id="insert">Insert into DOM</button>
46
-
47
- <div id="container">
48
- </div>
49
-
50
- <script>
51
- document.getElementById('insert').addEventListener('click', function() {
52
- document.getElementById("container").innerHTML =
53
- document.getElementById("my-input").value;
54
- });
55
- </script>
56
- </body>
57
- </html>
58
- EOHTML
59
- end
@@ -1,322 +0,0 @@
1
- shared_examples_for 'element_dom' do |options = {}|
2
- it_should_behave_like 'element', options
3
- it_should_behave_like 'auditable', options.merge( supports_nulls: false )
4
-
5
- before :each do
6
- begin
7
- Arachni::Options.audit.elements described_class.type
8
- rescue Arachni::OptionGroups::Audit::Error
9
- end
10
- end
11
-
12
- def run
13
- auditor.browser_cluster.wait
14
- end
15
-
16
- it "supports #{Arachni::RPC::Serializer}" do
17
- subject.should == Arachni::RPC::Serializer.deep_clone( subject )
18
- end
19
-
20
- describe '#to_rpc_data' do
21
- %w(parent page browser element).each do |attribute|
22
- it "excludes #{attribute}" do
23
- called = false
24
-
25
- # We do this inside a #submit handler to make sure the associations
26
- # which are added during a submit are handled successfully.
27
- subject.submit do
28
- subject.to_rpc_data.should_not include attribute
29
- called = true
30
- end
31
- run
32
-
33
- called.should be_true
34
- end
35
- end
36
- end
37
-
38
- describe '#marshal_dump' do
39
- [:@parent, :@page, :@browser, :@element].each do |ivar|
40
- it "excludes #{ivar}" do
41
- called = false
42
-
43
- # We do this inside a #submit handler to make sure the associations
44
- # which are added during a submit are handled successfully.
45
- subject.submit do
46
- subject.marshal_dump.should_not include ivar
47
- called = true
48
- end
49
- run
50
-
51
- called.should be_true
52
- end
53
- end
54
- end
55
-
56
- describe '#prepare_for_report' do
57
- it 'removes #page' do
58
- subject.page.should be_true
59
- subject.prepare_for_report
60
- subject.page.should be_nil
61
- end
62
- it 'removes #parent' do
63
- subject.parent.should be_true
64
- subject.prepare_for_report
65
- subject.parent.should be_nil
66
- end
67
- it 'removes #browser' do
68
- called = false
69
- subject.with_browser do |browser|
70
- subject.browser = browser
71
-
72
- subject.browser.should be_true
73
- subject.prepare_for_report
74
- subject.browser.should be_nil
75
-
76
- called = true
77
- end
78
- subject.auditor.browser_cluster.wait
79
- called.should be_true
80
- end
81
- end
82
-
83
- describe '#with_browser_cluster' do
84
- context 'when a browser cluster is' do
85
- context 'available' do
86
- it 'passes a BrowserCluster to the given block' do
87
- worker = nil
88
-
89
- subject.with_browser_cluster do |cluster|
90
- worker = cluster
91
- end
92
-
93
- worker.should == subject.auditor.browser_cluster
94
- end
95
- end
96
- end
97
- end
98
-
99
- describe '#with_browser' do
100
- context 'when a browser cluster is' do
101
- context 'available' do
102
- it 'passes a BrowserCluster::Worker to the given block' do
103
- worker = nil
104
-
105
- subject.with_browser do |browser|
106
- worker = browser
107
- end.should be_true
108
- subject.auditor.browser_cluster.wait
109
-
110
- worker.should be_kind_of Arachni::BrowserCluster::Worker
111
- end
112
- end
113
- end
114
- end
115
-
116
- describe '#trigger' do
117
- it 'does not update the page transitions' do
118
- page = nil
119
- pre_transitions = nil
120
- subject.with_browser do |browser|
121
- browser.load subject.page
122
- subject.browser = browser
123
- pre_transitions = browser.transitions.dup
124
-
125
- subject.trigger
126
- page = browser.to_page
127
- end
128
-
129
- subject.auditor.browser_cluster.wait
130
- page.dom.transitions.should == pre_transitions
131
- end
132
- end
133
-
134
- describe '#submit' do
135
- it 'submits the element' do
136
- inputs = { 'param' => 'stuff' }
137
- subject.inputs = inputs
138
-
139
- called = false
140
- subject.submit do |page|
141
- inputs.should == auditable_extract_parameters( page )
142
- called = true
143
- end
144
-
145
- subject.auditor.browser_cluster.wait
146
- called.should be_true
147
- end
148
-
149
- it 'sets the #performer on the returned page' do
150
- called = false
151
- subject.submit do |page|
152
- page.performer.should be_kind_of described_class
153
- called = true
154
- end
155
-
156
- subject.auditor.browser_cluster.wait
157
- called.should be_true
158
- end
159
-
160
- it 'sets the #browser on the #performer' do
161
- called = false
162
- subject.submit do |page|
163
- page.performer.browser.should be_kind_of Arachni::BrowserCluster::Worker
164
- called = true
165
- end
166
-
167
- subject.auditor.browser_cluster.wait
168
- called.should be_true
169
- end
170
-
171
- it 'sets the #element on the #performer', if: !options[:without_node] do
172
- called = false
173
- subject.submit do |page|
174
- page.performer.element.should be_kind_of Watir::HTMLElement
175
- called = true
176
- end
177
-
178
- subject.auditor.browser_cluster.wait
179
- called.should be_true
180
- end
181
-
182
- it 'adds the submission transition to the Page::DOM#transitions' do
183
- transition = nil
184
- subject.with_browser do |browser|
185
- subject.browser = browser
186
- browser.load subject.page
187
- transition = subject.trigger
188
- end
189
- subject.auditor.browser_cluster.wait
190
-
191
- submitted_page = nil
192
- subject.dup.submit do |page|
193
- submitted_page = page
194
- end
195
- subject.auditor.browser_cluster.wait
196
-
197
- subject.page.dom.transitions.should_not include transition
198
- submitted_page.dom.transitions.should include transition
199
- end
200
-
201
- context 'when the element could not be submitted' do
202
- it 'does not call the block' do
203
- subject.stub( :trigger ) { false }
204
-
205
- called = false
206
- subject.submit do
207
- called = true
208
- end
209
- subject.auditor.browser_cluster.wait
210
- called.should be_false
211
- end
212
- end
213
-
214
- describe :options do
215
- describe :custom_code do
216
- it 'injects the given code' do
217
- called = false
218
- title = 'Injected title'
219
-
220
- subject.submit custom_code: "document.title = #{title.inspect}" do |page|
221
- page.document.css('title').text.should == title
222
- called = true
223
- end
224
-
225
- subject.auditor.browser_cluster.wait
226
- called.should be_true
227
- end
228
- end
229
-
230
- describe :taint do
231
- it 'sets the Browser::Javascript#taint' do
232
- taint = Arachni::Utilities.generate_token
233
-
234
- set_taint = nil
235
- subject.submit taint: taint do |page|
236
- set_taint = page.performer.browser.javascript.taint
237
- end
238
-
239
- subject.auditor.browser_cluster.wait
240
- set_taint.should == taint
241
- end
242
- end
243
- end
244
- end
245
-
246
- describe '#audit' do
247
- it 'submits all element mutations' do
248
- called = false
249
- subject.audit 'seed' do |page, element|
250
- auditable_extract_parameters( page ).should == element.inputs
251
- called = true
252
- end
253
-
254
- subject.auditor.browser_cluster.wait
255
- called.should be_true
256
- end
257
- end
258
-
259
- describe '#valid_input_data?' do
260
- it 'returns true' do
261
- subject.valid_input_data?( 'stuff' ).should be_true
262
- end
263
-
264
- described_class::INVALID_INPUT_DATA.each do |invalid_data|
265
- context "when the value contains #{invalid_data.inspect}" do
266
- it 'returns false' do
267
- subject.valid_input_data?( "stuff #{invalid_data}" ).should be_false
268
- end
269
- end
270
- end
271
- end
272
-
273
- describe '#page' do
274
- it 'returns the page containing the element' do
275
- subject.page.should be_kind_of Arachni::Page
276
- end
277
- end
278
-
279
- describe '#node', if: !options[:without_node] do
280
- it 'returns the Nokogiri node of the element' do
281
- subject.node.is_a?( Nokogiri::XML::Element ).should be_true
282
- end
283
- end
284
-
285
- describe '#auditor' do
286
- it 'returns the assigned auditor' do
287
- subject.auditor.should be_kind_of Arachni::Check::Auditor
288
- end
289
- end
290
-
291
- describe '#encode' do
292
- it 'returns the string as is' do
293
- v = 'blah'
294
- subject.encode( v ).object_id.should == v.object_id
295
- end
296
- end
297
- describe '.encode' do
298
- it 'returns the string as is' do
299
- v = 'blah'
300
- subject.class.encode( v ).object_id.should == v.object_id
301
- end
302
- end
303
-
304
- describe '#decode' do
305
- it 'returns the string as is' do
306
- v = 'blah'
307
- subject.decode( v ).object_id.should == v.object_id
308
- end
309
- end
310
- describe '.decode' do
311
- it 'returns the string as is' do
312
- v = 'blah'
313
- subject.class.decode( v ).object_id.should == v.object_id
314
- end
315
- end
316
-
317
- describe '#dup' do
318
- it 'preserves the #parent' do
319
- subject.dup.parent.should == subject.parent
320
- end
321
- end
322
- end