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
@@ -32,3 +32,5 @@ module Severity
32
32
  end
33
33
  end
34
34
  end
35
+
36
+ Arachni::Severity = Arachni::Issue::Severity
@@ -147,6 +147,22 @@ class Audit < Arachni::OptionGroup
147
147
  # Audit XML request inputs.
148
148
  attr_accessor :xmls
149
149
 
150
+ # @note Default is `false`.
151
+ #
152
+ # @return [Bool]
153
+ # Audit DOM inputs.
154
+ attr_accessor :ui_inputs
155
+ alias :ui_input_doms :ui_inputs
156
+ alias :ui_input_doms= :ui_inputs=
157
+
158
+ # @note Default is `false`.
159
+ #
160
+ # @return [Bool]
161
+ # Audit DOM UI forms -- i.e. combination or orphan inputs and buttons.
162
+ attr_accessor :ui_forms
163
+ alias :ui_form_doms :ui_forms
164
+ alias :ui_form_doms= :ui_forms=
165
+
150
166
  set_defaults(
151
167
  parameter_values: true,
152
168
  exclude_vector_patterns: [],
@@ -235,6 +251,10 @@ class Audit < Arachni::OptionGroup
235
251
  # * `:forms`
236
252
  # * `:cookies`
237
253
  # * `:headers`
254
+ # * `:ui_inputs`
255
+ # * `:ui_forms`
256
+ # * `:xmls`
257
+ # * `:jsons`
238
258
  #
239
259
  # @return [Bool]
240
260
  #
@@ -250,8 +270,8 @@ class Audit < Arachni::OptionGroup
250
270
 
251
271
  [:links, :forms, :cookies, :headers, :cookies_extensively,
252
272
  :with_both_http_methods, :link_doms, :form_doms, :cookie_doms,
253
- :jsons, :xmls, :parameter_values, :parameter_names, :with_extra_parameter
254
- ].each do |attribute|
273
+ :jsons, :xmls, :ui_inputs, :ui_input_doms, :ui_forms, :ui_form_doms,
274
+ :parameter_values, :parameter_names, :with_extra_parameter].each do |attribute|
255
275
  define_method "#{attribute}?" do
256
276
  !!send( attribute )
257
277
  end
@@ -13,6 +13,10 @@ module Arachni::OptionGroups
13
13
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
14
14
  class BrowserCluster < Arachni::OptionGroup
15
15
 
16
+ # @return [Hash]
17
+ # Data to be set in the browser's `localStorage`.
18
+ attr_accessor :local_storage
19
+
16
20
  # @return [Hash<Regexp,String>]
17
21
  # When the page URL matched the key `Regexp`, wait until the `String` CSS
18
22
  # selector in the value matches an element.
@@ -43,6 +47,7 @@ class BrowserCluster < Arachni::OptionGroup
43
47
  attr_accessor :screen_height
44
48
 
45
49
  set_defaults(
50
+ local_storage: {},
46
51
  wait_for_elements: {},
47
52
  pool_size: 6,
48
53
  job_timeout: 25,
@@ -52,6 +57,16 @@ class BrowserCluster < Arachni::OptionGroup
52
57
  screen_height: 1200
53
58
  )
54
59
 
60
+ def local_storage=( data )
61
+ data ||= {}
62
+
63
+ if !data.is_a?( Hash )
64
+ fail ArgumentError, "Expected data to be Hash, got #{data.class} instead."
65
+ end
66
+
67
+ @local_storage = data
68
+ end
69
+
55
70
  def css_to_wait_for( url )
56
71
  wait_for_elements.map do |pattern, css|
57
72
  next if !(url =~ pattern)
@@ -101,7 +101,8 @@ class Page
101
101
  end
102
102
 
103
103
  ELEMENTS = [
104
- :links, :forms, :cookies, :headers, :link_templates, :jsons, :xmls
104
+ :links, :forms, :cookies, :headers, :link_templates, :jsons, :xmls,
105
+ :ui_inputs, :ui_forms
105
106
  ]
106
107
 
107
108
  METADATA = [ :nonce_name, :skip_dom ]
@@ -274,7 +275,7 @@ class Page
274
275
  @has_javascript = nil
275
276
  clear_cache
276
277
 
277
- @body = string.to_s.dup.freeze
278
+ @body = string.to_s.dup.recode.freeze
278
279
  end
279
280
 
280
281
  ELEMENTS.each do |type|
@@ -244,6 +244,16 @@ class Parser
244
244
  @link_vars ||= parsed.rewrite.query_parameters.freeze
245
245
  end
246
246
 
247
+ # Dummy method, only the {Browser#to_page browser} can fill this in.
248
+ def ui_inputs
249
+ []
250
+ end
251
+
252
+ # Dummy method, only the {Browser#to_page browser} can fill this in.
253
+ def ui_forms
254
+ []
255
+ end
256
+
247
257
  # @return [Array<Element::Cookie>]
248
258
  # Cookies from HTTP headers and response body.
249
259
  def cookies
@@ -320,16 +330,25 @@ class Parser
320
330
  # Paths.
321
331
  def run_extractors
322
332
  begin
323
- self.class.extractors.available.map do |name|
333
+ unsanitized_paths = Set.new
334
+ self.class.extractors.available.each do |name|
324
335
  exception_jail false do
325
- self.class.extractors[name].new(
336
+ unsanitized_paths.merge self.class.extractors[name].new(
326
337
  document: document,
327
338
  html: body
328
339
  ).run
329
340
  end
330
- end.flatten.uniq.compact.
331
- map { |path| to_absolute( path ) }.compact.uniq.
332
- reject { |path| skip?( path ) }
341
+ end
342
+
343
+ sanitized_paths = Set.new
344
+ unsanitized_paths.map do |path|
345
+ abs = to_absolute( path )
346
+ next if !abs || skip?( abs )
347
+
348
+ sanitized_paths << abs
349
+ end
350
+
351
+ sanitized_paths.to_a
333
352
  rescue => e
334
353
  print_exception e
335
354
  []
@@ -167,7 +167,7 @@ class Manager
167
167
  rack: 'Rack',
168
168
  django: 'Django',
169
169
  cakephp: 'CakePHP',
170
- nette: 'Nette Framework',
170
+ nette: 'Nette',
171
171
  symfony: 'Symfony',
172
172
  rails: 'Ruby on Rails',
173
173
  aspx_mvc: 'ASP.NET MVC',
@@ -175,7 +175,6 @@ class Manager
175
175
  cherrypy: 'CherryPy'
176
176
  }
177
177
 
178
- # Amount of
179
178
  PLATFORM_CACHE_SIZE = 1000
180
179
 
181
180
  def self.synchronize( &block )
@@ -206,12 +206,11 @@ class Framework < ::Arachni::Framework
206
206
  end
207
207
 
208
208
  # @return [Array<Hash>]
209
- # First variations of all discovered issues with generic info filled in
210
- # from the parent as {Arachni::Issue#to_rpc_data RPC data}.
209
+ # Issues as {Arachni::Issue#to_rpc_data RPC data}.
211
210
  #
212
211
  # @private
213
212
  def issues
214
- Data.issues.map { |issue| issue.variations.first.to_solo( issue ).to_rpc_data }
213
+ Data.issues.sort.map(&:to_rpc_data)
215
214
  end
216
215
 
217
216
  # @return [Array<Hash>]
@@ -219,7 +218,7 @@ class Framework < ::Arachni::Framework
219
218
  #
220
219
  # @see #issues
221
220
  def issues_as_hash
222
- Data.issues.map { |issue| issue.variations.first.to_solo( issue ).to_h }
221
+ Data.issues.sort.map(&:to_h)
223
222
  end
224
223
 
225
224
  # @return [String]
@@ -100,7 +100,8 @@ module MultiInstance
100
100
 
101
101
  data = {
102
102
  status: status,
103
- busy: running?
103
+ busy: running?,
104
+ seed: Utilities.random_seed
104
105
  }
105
106
 
106
107
  if include_issues
@@ -278,7 +278,7 @@ class Session
278
278
  http.get( Options.session.check_url, http_options ) do |response|
279
279
  bool = !!response.body.match( Options.session.check_pattern )
280
280
 
281
- print_debug "Login check done: #{bool}"
281
+ print_debug "Login check done: #{bool}\n#{response}"
282
282
  block.call( bool ) if block
283
283
  end
284
284
 
@@ -127,18 +127,15 @@ class Trainer
127
127
 
128
128
  [ :forms, :links ].each { |type| has_new_elements ||= has_new?( incoming_page, type ) }
129
129
 
130
+ incoming_page.paths.each do |path|
131
+ @framework.push_to_url_queue( path )
132
+ end
133
+
130
134
  if has_new_elements
131
135
  @trainings_per_url[incoming_page.url] += 1
132
136
 
133
137
  notify_on_new_page incoming_page
134
138
  @framework.push_to_page_queue( incoming_page )
135
-
136
- # If the page is pushed, paths will be extracted eventually, if not, we
137
- # need to do it now.
138
- else
139
- incoming_page.paths.each do |path|
140
- @framework.push_to_url_queue( path )
141
- end
142
139
  end
143
140
 
144
141
  incoming_page.clear_cache
@@ -10,7 +10,18 @@ module Watir
10
10
  class Element
11
11
 
12
12
  def opening_tag
13
- html.match( /<#{tag_name}.*?>/im )[0]
13
+ browser.execute_script(
14
+ %Q[
15
+ var s = '<' + arguments[0].tagName.toLowerCase();
16
+ var attrs = arguments[0].attributes;
17
+ for( var l = 0; l < attrs.length; ++l ) {
18
+ s += ' ' + attrs[l].name + '="' + attrs[l].value.replace( '"', '\"' ) + '"';
19
+ }
20
+ s += '>'
21
+ return s;
22
+ ],
23
+ self
24
+ )
14
25
  end
15
26
 
16
27
  def events
@@ -1 +1 @@
1
- 1.2.1
1
+ 1.3
@@ -25,7 +25,7 @@ describe Arachni::Browser::ElementLocator do
25
25
  subject { described_class.new options }
26
26
 
27
27
  it "supports #{Arachni::RPC::Serializer}" do
28
- subject.should == Arachni::RPC::Serializer.deep_clone( subject )
28
+ expect(subject).to eq(Arachni::RPC::Serializer.deep_clone( subject ))
29
29
  end
30
30
 
31
31
  describe '#to_rpc_data' do
@@ -33,7 +33,7 @@ describe Arachni::Browser::ElementLocator do
33
33
 
34
34
  %w(tag_name attributes).each do |attribute|
35
35
  it "includes '#{attribute}'" do
36
- data[attribute].should == subject.send( attribute )
36
+ expect(data[attribute]).to eq(subject.send( attribute ))
37
37
  end
38
38
  end
39
39
  end
@@ -44,7 +44,7 @@ describe Arachni::Browser::ElementLocator do
44
44
 
45
45
  %w(tag_name attributes).each do |attribute|
46
46
  it "restores '#{attribute}'" do
47
- restored.send( attribute ).should == subject.send( attribute )
47
+ expect(restored.send( attribute )).to eq(subject.send( attribute ))
48
48
  end
49
49
  end
50
50
  end
@@ -52,10 +52,10 @@ describe Arachni::Browser::ElementLocator do
52
52
  describe '.from_html' do
53
53
  it 'fills in locator data from HTML code' do
54
54
  l = described_class.from_html( '<a href="/test/">Click me</a>' )
55
- l.tag_name.should == :a
56
- l.attributes.should == {
55
+ expect(l.tag_name).to eq(:a)
56
+ expect(l.attributes).to eq({
57
57
  'href' => '/test/'
58
- }
58
+ })
59
59
  end
60
60
  end
61
61
 
@@ -64,27 +64,27 @@ describe Arachni::Browser::ElementLocator do
64
64
  l = described_class.from_node(
65
65
  Nokogiri::HTML.fragment( '<a href="/test/">Click me</a>' ).children.first
66
66
  )
67
- l.tag_name.should == :a
68
- l.attributes.should == {
67
+ expect(l.tag_name).to eq(:a)
68
+ expect(l.attributes).to eq({
69
69
  'href' => '/test/'
70
- }
70
+ })
71
71
  end
72
72
  end
73
73
 
74
74
  describe '#initialize' do
75
75
  describe :tag_name do
76
76
  it 'sets #tag_name' do
77
- described_class.new( tag_name: :a ).tag_name.should == :a
77
+ expect(described_class.new( tag_name: :a ).tag_name).to eq(:a)
78
78
  end
79
79
 
80
80
  it 'converts it to a Sybmol' do
81
- described_class.new( tag_name: 'a' ).tag_name.should == :a
81
+ expect(described_class.new( tag_name: 'a' ).tag_name).to eq(:a)
82
82
  end
83
83
  end
84
84
 
85
85
  describe :attributes do
86
86
  it 'sets #attributes' do
87
- described_class.new( attributes: attributes ).attributes.should == attributes
87
+ expect(described_class.new( attributes: attributes ).attributes).to eq(attributes)
88
88
  end
89
89
  end
90
90
  end
@@ -95,14 +95,14 @@ describe Arachni::Browser::ElementLocator do
95
95
 
96
96
  l = described_class.new( tag_name: :a, attributes: { href: '#stuff'} )
97
97
  element = l.locate( browser )
98
- element.should be_kind_of Watir::HTMLElement
99
- element.exists?.should be_true
98
+ expect(element).to be_kind_of Watir::HTMLElement
99
+ expect(element.exists?).to be_truthy
100
100
  end
101
101
 
102
102
  context 'when the element cannot be located' do
103
103
  it "returns a #{Watir} locator" do
104
104
  browser.load "#{url}/digest"
105
- subject.locate( browser ).exists?.should be_false
105
+ expect(subject.locate( browser ).exists?).to be_falsey
106
106
  end
107
107
  end
108
108
  end
@@ -110,30 +110,30 @@ describe Arachni::Browser::ElementLocator do
110
110
  describe '#css' do
111
111
  context 'when there are no attributes' do
112
112
  it 'returns a CSS locator with just the tag name' do
113
- described_class.new( tag_name: :a ).css.should == 'a'
113
+ expect(described_class.new( tag_name: :a ).css).to eq('a')
114
114
  end
115
115
  end
116
116
 
117
117
  context 'when there is an attribute' do
118
118
  it 'returns a CSS locator with the attribute' do
119
- described_class.new(
119
+ expect(described_class.new(
120
120
  tag_name: :a,
121
121
  attributes: {
122
122
  stuff: 'blah'
123
123
  }
124
- ).css.should == 'a[stuff="blah"]'
124
+ ).css).to eq('a[stuff="blah"]')
125
125
  end
126
126
  end
127
127
 
128
128
  context 'when there are multiple attributes' do
129
129
  it 'returns a CSS locator with the attributes' do
130
- described_class.new(
130
+ expect(described_class.new(
131
131
  tag_name: :a,
132
132
  attributes: {
133
133
  stuff: 'blah',
134
134
  stuff2: 'blah2'
135
135
  }
136
- ).css.should == 'a[stuff="blah"][stuff2="blah2"]'
136
+ ).css).to eq('a[stuff="blah"][stuff2="blah2"]')
137
137
  end
138
138
  end
139
139
  end
@@ -142,13 +142,13 @@ describe Arachni::Browser::ElementLocator do
142
142
  it 'sets #tag_name' do
143
143
  l = described_class.new
144
144
  l.tag_name = tag_name
145
- l.tag_name.should == tag_name
145
+ expect(l.tag_name).to eq(tag_name)
146
146
  end
147
147
 
148
148
  it 'converts the arguments to a Symbol' do
149
149
  l = described_class.new
150
150
  l.tag_name = tag_name.to_s
151
- l.tag_name.should == tag_name.to_sym
151
+ expect(l.tag_name).to eq(tag_name.to_sym)
152
152
  end
153
153
  end
154
154
 
@@ -156,71 +156,71 @@ describe Arachni::Browser::ElementLocator do
156
156
  it 'sets #attributes' do
157
157
  l = described_class.new
158
158
  l.attributes = attributes
159
- l.attributes.should == attributes
159
+ expect(l.attributes).to eq(attributes)
160
160
  end
161
161
 
162
162
  it 'converts the keys and values to strings' do
163
163
  l = described_class.new
164
164
  l.attributes = attributes.
165
165
  inject({}) { |h, (k,v)| h[k.to_sym] = v.to_sym; h }
166
- l.attributes.should == attributes
166
+ expect(l.attributes).to eq(attributes)
167
167
  end
168
168
 
169
169
  it 'freezes the keys and values' do
170
170
  l = described_class.new
171
171
  l.attributes = attributes
172
172
  l.attributes.each do |k, v|
173
- k.should be_frozen
174
- v.should be_frozen
173
+ expect(k).to be_frozen
174
+ expect(v).to be_frozen
175
175
  end
176
176
  end
177
177
 
178
178
  it 'freezes the hash' do
179
179
  l = described_class.new
180
180
  l.attributes = attributes
181
- l.attributes.should be_frozen
181
+ expect(l.attributes).to be_frozen
182
182
  end
183
183
  end
184
184
 
185
185
  describe '#locatable_attributes' do
186
186
  it 'returns attributes that can be used to locate the element' do
187
- described_class.new(
187
+ expect(described_class.new(
188
188
  tag_name: :a,
189
189
  attributes: attributes.merge(
190
190
  'custom-attr' => 'blah',
191
191
  'data-id' => 'blah'
192
192
  )
193
- ).locatable_attributes.should == { id: 'my-id', data_id: 'blah' }
193
+ ).locatable_attributes).to eq({ id: 'my-id', data_id: 'blah' })
194
194
  end
195
195
  end
196
196
 
197
197
  describe '#to_s' do
198
198
  it 'converts it to an HTML opening tag' do
199
- subject.to_s.should == '<a id="my-id" class="my-class">'
200
- described_class.new( tag_name: tag_name ).to_s.should == '<a>'
199
+ expect(subject.to_s).to eq('<a id="my-id" class="my-class">')
200
+ expect(described_class.new( tag_name: tag_name ).to_s).to eq('<a>')
201
201
  end
202
202
  end
203
203
 
204
204
  describe '#inspect' do
205
205
  it 'is aliased to #to_s' do
206
- subject.to_s.should == subject.inspect
206
+ expect(subject.to_s).to eq(subject.inspect)
207
207
  end
208
208
  end
209
209
 
210
210
  describe '#to_hash' do
211
211
  it 'converts it to a Hash' do
212
- subject.to_hash.should == options
212
+ expect(subject.to_hash).to eq(options)
213
213
  end
214
214
 
215
215
  it 'is aliased to #to_h' do
216
- subject.to_h.should == subject.to_hash
216
+ expect(subject.to_h).to eq(subject.to_hash)
217
217
  end
218
218
  end
219
219
 
220
220
  describe '#dup' do
221
221
  it 'duplicates self' do
222
- subject.dup.should == subject
223
- subject.dup.object_id.should_not == subject.object_id
222
+ expect(subject.dup).to eq(subject)
223
+ expect(subject.dup.object_id).not_to eq(subject.object_id)
224
224
  end
225
225
  end
226
226
 
@@ -228,20 +228,20 @@ describe Arachni::Browser::ElementLocator do
228
228
  context 'when the #tag_name changes' do
229
229
  it 'changes' do
230
230
  hash = subject.hash
231
- hash.should == subject.hash
231
+ expect(hash).to eq(subject.hash)
232
232
 
233
233
  subject.tag_name = 'stuff'
234
- hash.should_not == subject.hash
234
+ expect(hash).not_to eq(subject.hash)
235
235
  end
236
236
  end
237
237
 
238
238
  context 'when the #attributes change' do
239
239
  it 'changes' do
240
240
  hash = subject.hash
241
- hash.should == subject.hash
241
+ expect(hash).to eq(subject.hash)
242
242
 
243
243
  subject.attributes = { 1 => 2 }
244
- hash.should_not == subject.hash
244
+ expect(hash).not_to eq(subject.hash)
245
245
  end
246
246
  end
247
247
  end
@@ -249,8 +249,8 @@ describe Arachni::Browser::ElementLocator do
249
249
  describe '#==' do
250
250
  context 'when the objects are equal' do
251
251
  it 'returns true' do
252
- subject.should == subject
253
- subject.dup.should == subject
252
+ expect(subject).to eq(subject)
253
+ expect(subject.dup).to eq(subject)
254
254
  end
255
255
  end
256
256
 
@@ -258,7 +258,7 @@ describe Arachni::Browser::ElementLocator do
258
258
  it 'returns false' do
259
259
  dup = subject.dup
260
260
  dup.tag_name = 'stuff'
261
- dup.should_not == subject
261
+ expect(dup).not_to eq(subject)
262
262
  end
263
263
  end
264
264
  end