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
@@ -13,16 +13,14 @@ module Check
13
13
  #
14
14
  # There are 3 main types of audit and analysis techniques available:
15
15
  #
16
- # * {Arachni::Element::Capabilities::Analyzable::Taint Taint analysis}
16
+ # * {Arachni::Element::Capabilities::Analyzable::Signature Signature analysis}
17
17
  # -- {#audit}
18
18
  # * {Arachni::Element::Capabilities::Analyzable::Timeout Timeout analysis}
19
19
  # -- {#audit_timeout}
20
20
  # * {Arachni::Element::Capabilities::Analyzable::Differential Differential analysis}
21
21
  # -- {#audit_differential}
22
22
  #
23
- # It should be noted that actual analysis takes place at the element level,
24
- # and to be more specific, the {Arachni::Element::Capabilities::Auditable}
25
- # element level.
23
+ # It should be noted that actual analysis takes place at the {Arachni::Element element} level.
26
24
  #
27
25
  # It also provides:
28
26
  #
@@ -119,6 +117,12 @@ module Auditor
119
117
  proc { audit.jsons? && page.jsons.find { |e| e.inputs.any? } },
120
118
  Element::XML =>
121
119
  proc { audit.xmls? && page.xmls.find { |e| e.inputs.any? } },
120
+ Element::UIInput => false,
121
+ Element::UIInput::DOM =>
122
+ proc { audit.ui_inputs? && page.ui_inputs.any? },
123
+ Element::UIForm => false,
124
+ Element::UIForm::DOM =>
125
+ proc { audit.ui_forms? && page.ui_forms.any? },
122
126
  Element::Body => !page.body.empty?,
123
127
  Element::GenericDOM => page.has_script?,
124
128
  Element::Path => true,
@@ -189,7 +193,7 @@ module Auditor
189
193
  # Auditable DOM elements.
190
194
  DOM_ELEMENTS_WITH_INPUTS = [
191
195
  Element::Link::DOM, Element::Form::DOM, Element::Cookie::DOM,
192
- Element::LinkTemplate::DOM
196
+ Element::LinkTemplate::DOM, Element::UIInput::DOM, Element::UIForm::DOM
193
197
  ]
194
198
 
195
199
  # Default audit options.
@@ -523,6 +527,12 @@ module Auditor
523
527
  when Element::LinkTemplate::DOM.type
524
528
  prepare_each_dom_element( page.link_templates, &block )
525
529
 
530
+ when Element::UIInput::DOM.type
531
+ prepare_each_dom_element( page.ui_inputs, &block )
532
+
533
+ when Element::UIForm::DOM.type
534
+ prepare_each_dom_element( page.ui_forms, &block )
535
+
526
536
  else
527
537
  fail ArgumentError, "Unknown DOM element: #{elem}"
528
538
  end
@@ -530,17 +540,17 @@ module Auditor
530
540
  end
531
541
 
532
542
  # If a block has been provided it calls {Arachni::Element::Capabilities::Auditable#audit}
533
- # for every element, otherwise, it defaults to {#audit_taint}.
543
+ # for every element, otherwise, it defaults to {#audit_signature}.
534
544
  #
535
545
  # Uses {#each_candidate_element} to decide which elements to audit.
536
546
  #
537
547
  # @see OPTIONS
538
548
  # @see Arachni::Element::Capabilities::Auditable#audit
539
- # @see #audit_taint
549
+ # @see #audit_signature
540
550
  def audit( payloads, opts = {}, &block )
541
551
  opts = OPTIONS.merge( opts )
542
552
  if !block_given?
543
- audit_taint( payloads, opts )
553
+ audit_signature( payloads, opts )
544
554
  else
545
555
  each_candidate_element( opts[:elements] ) do |e|
546
556
  e.audit( payloads, opts, &block )
@@ -549,17 +559,17 @@ module Auditor
549
559
  end
550
560
  end
551
561
 
552
- # Provides easy access to element auditing using simple taint analysis
562
+ # Provides easy access to element auditing using simple signature analysis
553
563
  # and automatically logs results.
554
564
  #
555
565
  # Uses {#each_candidate_element} to decide which elements to audit.
556
566
  #
557
567
  # @see OPTIONS
558
- # @see Arachni::Element::Capabilities::Analyzable::Taint
559
- def audit_taint( payloads, opts = {} )
568
+ # @see Arachni::Element::Capabilities::Analyzable::Signature
569
+ def audit_signature( payloads, opts = {} )
560
570
  opts = OPTIONS.merge( opts )
561
571
  each_candidate_element( opts[:elements] )do |e|
562
- e.taint_analysis( payloads, opts )
572
+ e.signature_analysis( payloads, opts )
563
573
  audited( e.coverage_id )
564
574
  end
565
575
  end
@@ -89,7 +89,19 @@ class Framework
89
89
  # @param [Page] page
90
90
  # Page with which to update the {#sitemap}.
91
91
  def add_page_to_sitemap( page )
92
- sitemap[page.dom.url] = page.code
92
+ update_sitemap( page.dom.url => page.code )
93
+ end
94
+
95
+ def update_sitemap( entries )
96
+ entries.each do |url, code|
97
+ # Feedback from the trainer or whatever, don't include it in the
98
+ # sitemap, it'll just add noise.
99
+ next if url.include?( Utilities.random_seed )
100
+
101
+ @sitemap[url] = code
102
+ end
103
+
104
+ @sitemap
93
105
  end
94
106
 
95
107
  def dump( directory )
@@ -34,8 +34,7 @@ class Issues
34
34
  def initialize
35
35
  super
36
36
 
37
- # Stores all issues with Issue#digest as the key as a way to deduplicate
38
- # and group variations.
37
+ # Stores all issues with Issue#digest as the key as a way to deduplicate.
39
38
  @collection = {}
40
39
 
41
40
  # We also use this Set for deduplication in case #do_not_store has been
@@ -92,24 +91,11 @@ class Issues
92
91
  end
93
92
 
94
93
  # @return [Array<Issue>]
95
- # All logged issues grouped as variations.
94
+ # All logged issues.
96
95
  def all
97
96
  @collection.values
98
97
  end
99
98
 
100
- # @return [Array<Issue>]
101
- # First variation of all issues (as solo issues) sorted by severity.
102
- def summary
103
- all.map { |issue| issue.variations.first.to_solo issue }.flatten.
104
- sort_by(&:severity).reverse
105
- end
106
-
107
- # @return [Array<Issue>]
108
- # All logged issues as solo objects, without variations.
109
- def flatten
110
- all.map { |issue| issue.variations.map { |v| v.to_solo issue } }.flatten
111
- end
112
-
113
99
  def each( &block )
114
100
  all.each( &block )
115
101
  end
@@ -124,7 +110,7 @@ class Issues
124
110
  @digests.include? issue.digest
125
111
  end
126
112
 
127
- # @note Will deduplicate and group issues as variations.
113
+ # @note Will deduplicate issues.
128
114
  #
129
115
  # @param [Issue] issue
130
116
  # Issue to push to the collection.
@@ -133,18 +119,16 @@ class Issues
133
119
  def <<( issue )
134
120
  notify_on_new_pre_deduplication( issue )
135
121
 
136
- # Only allow passive issues to have variations.
137
- return self if include?( issue ) && issue.active?
122
+ return self if include?( issue )
138
123
 
139
- @digests << issue.digest
124
+ digest = issue.digest
125
+ @digests << digest
140
126
 
141
127
  synchronize do
142
128
  notify_on_new( issue )
143
129
 
144
130
  if store?
145
- id = issue.digest
146
- @collection[id] ||= issue.with_variations
147
- @collection[id].variations << issue.as_variation
131
+ @collection[digest] = issue
148
132
  end
149
133
  end
150
134
 
@@ -165,11 +149,11 @@ class Issues
165
149
  end
166
150
 
167
151
  def first
168
- @collection.values.first
152
+ all.first
169
153
  end
170
154
 
171
155
  def last
172
- @collection.values.last
156
+ all.last
173
157
  end
174
158
 
175
159
  def any?
@@ -24,9 +24,13 @@ module Capabilities
24
24
  end
25
25
  end
26
26
 
27
- # load and include all available capabilities
28
- lib = File.dirname( __FILE__ ) + '/capabilities/*.rb'
29
- Dir.glob( lib ).each { |f| require f }
27
+ file = File.dirname( __FILE__ )
28
+ # Need to be loaded in order.
29
+ %w(inputtable submittable mutable auditable analyzable).each do |name|
30
+ require_relative "#{file}/capabilities/#{name}.rb"
31
+ end
32
+ # Load the rest automatically.
33
+ Dir.glob( "#{file}/capabilities/*.rb" ).each { |f| require f }
30
34
 
31
35
  # Base class for all element types.
32
36
  #
@@ -166,6 +170,8 @@ class Base
166
170
  data.delete 'scope'
167
171
  data['class'] = self.class.to_s
168
172
 
173
+ data['initialization_options'] = initialization_options
174
+
169
175
  if data['initialization_options'].is_a? Hash
170
176
  data['initialization_options'] =
171
177
  data['initialization_options'].my_stringify_keys(false)
@@ -6,19 +6,15 @@
6
6
  web site for more information on licensing and terms of use.
7
7
  =end
8
8
 
9
- require_relative 'auditable'
10
-
11
9
  module Arachni
12
10
  module Element::Capabilities
13
11
 
14
12
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
15
13
  module Analyzable
16
- include Auditable
17
-
18
- # Load and include all available analysis/audit techniques.
14
+ # Load all available analysis techniques.
19
15
  Dir.glob( File.dirname( __FILE__ ) + '/analyzable/*.rb' ).each { |f| require f }
20
16
 
21
- include Taint
17
+ include Signature
22
18
  include Timeout
23
19
  include Differential
24
20
 
@@ -6,6 +6,8 @@
6
6
  web site for more information on licensing and terms of use.
7
7
  =end
8
8
 
9
+ require_relative '../mutable'
10
+
9
11
  module Arachni
10
12
  module Element::Capabilities
11
13
  module Analyzable
@@ -28,7 +30,7 @@ module Differential
28
30
  end
29
31
 
30
32
  DIFFERENTIAL_OPTIONS = {
31
- format: [Mutable::Format::STRAIGHT],
33
+ format: [Arachni::Element::Capabilities::Mutable::Format::STRAIGHT],
32
34
 
33
35
  # Amount of refinement operations to remove context-irrelevant dynamic
34
36
  # content -- like banners etc.
@@ -104,6 +106,12 @@ module Differential
104
106
  def differential_analysis( opts = {} )
105
107
  return if self.inputs.empty?
106
108
 
109
+ with_missing_values = Set.new( self.inputs.select { |k, v| v.to_s.empty? }.keys )
110
+ if self.inputs.size == with_missing_values.size
111
+ print_debug 'Differential analysis: Inputs are missing default values.'
112
+ return false
113
+ end
114
+
107
115
  return false if audited? audit_id
108
116
  audited audit_id
109
117
 
@@ -115,6 +123,9 @@ module Differential
115
123
 
116
124
  @differential_analysis_options = opts.dup
117
125
  opts = self.class::MUTATION_OPTIONS.merge( DIFFERENTIAL_OPTIONS.merge( opts ) )
126
+ opts[:skip_like] = proc do |mutation|
127
+ with_missing_values.include? mutation.affected_input_name
128
+ end
118
129
 
119
130
  mutations_size = 0
120
131
  each_mutation( opts[:false], opts ) { mutations_size += 1 }
@@ -196,13 +207,15 @@ module Differential
196
207
  @data_gathering[:controls][altered_hash] = true
197
208
  end
198
209
 
210
+ body = res.body.gsub( elem.seed, '' )
211
+
199
212
  # Create a signature from the response body and refine it with
200
213
  # subsequent ones to remove noise (like context-irrelevant dynamic
201
214
  # content such as banners etc.).
202
215
  signatures[:controls][altered_hash] =
203
216
  signatures[:controls][altered_hash] ?
204
- signatures[:controls][altered_hash].refine!(res.body) :
205
- Support::Signature.new(res.body)
217
+ signatures[:controls][altered_hash].refine!(body) :
218
+ Support::Signature.new(body)
206
219
 
207
220
  increase_received_responses( opts, signatures )
208
221
  end
@@ -264,13 +277,15 @@ module Differential
264
277
 
265
278
  signatures[pair_hash][altered_hash][:injected_string] ||= expr
266
279
 
280
+ body = res.body.gsub( elem.seed, '' )
281
+
267
282
  # Create a signature from the response body and refine it with
268
283
  # subsequent ones to remove noise (like context-irrelevant dynamic
269
284
  # content such as banners etc.).
270
285
  signatures[pair_hash][altered_hash][bool] =
271
286
  signatures[pair_hash][altered_hash][bool] ?
272
- signatures[pair_hash][altered_hash][bool].refine!(res.body) :
273
- Support::Signature.new(res.body)
287
+ signatures[pair_hash][altered_hash][bool].refine!(body) :
288
+ Support::Signature.new(body)
274
289
 
275
290
  signature_sieve( altered_hash, signatures, pair_hash )
276
291
 
@@ -326,13 +341,15 @@ module Differential
326
341
  " action '#{elem.action}'."
327
342
  end
328
343
 
344
+ body = res.body.gsub( elem.seed, '' )
345
+
329
346
  # Create a signature from the response body and refine it with
330
347
  # subsequent ones to remove noise (like context-irrelevant dynamic
331
348
  # content such as banners etc.).
332
349
  signatures[:controls_verification][altered_hash] =
333
350
  signatures[:controls_verification][altered_hash] ?
334
- signatures[:controls_verification][altered_hash].refine!(res.body) :
335
- Support::Signature.new(res.body)
351
+ signatures[:controls_verification][altered_hash].refine!(body) :
352
+ Support::Signature.new(body)
336
353
 
337
354
  received_responses += 1
338
355
  next if received_responses != @data_gathering[:mutations_size]
@@ -13,13 +13,13 @@ module Analyzable
13
13
  # Looks for specific substrings or patterns in response bodies.
14
14
  #
15
15
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
16
- module Taint
16
+ module Signature
17
17
 
18
- TAINT_CACHE = {
18
+ SIGNATURE_CACHE = {
19
19
  match: Support::Cache::LeastRecentlyPushed.new( 10_000 )
20
20
  }
21
21
 
22
- TAINT_OPTIONS = {
22
+ SIGNATURE_OPTIONS = {
23
23
  # The regular expression to match against the response body.
24
24
  #
25
25
  # Alternatively, you can use the :substring option.
@@ -43,13 +43,13 @@ module Taint
43
43
  longest_word_optimization: false
44
44
  }
45
45
 
46
- # Performs taint analysis and logs an issue should there be one.
46
+ # Performs signatures analysis and logs an issue should there be one.
47
47
  #
48
48
  # It logs an issue when:
49
49
  #
50
50
  # * `:match` == nil AND `:regexp` matches the response body
51
- # * `:match`` == not nil AND `:regexp` match == `:match`
52
- # * `:substring`exists in the response body
51
+ # * `:match` != nil AND `:regexp` match == `:match`
52
+ # * `:substring` exists in the response body
53
53
  #
54
54
  # @param [String, Array<String>, Hash{Symbol => <String, Array<String>>}] payloads
55
55
  # Payloads to inject, if given:
@@ -63,16 +63,16 @@ module Taint
63
63
  # for the {Element::Capabilities::Submittable#action resource} to be audited.
64
64
  # @param [Hash] opts
65
65
  # Options as described in {Arachni::Check::Auditor::OPTIONS} and
66
- # {TAINT_OPTIONS}.
66
+ # {SIGNATURE_OPTIONS}.
67
67
  #
68
68
  # @return [Bool]
69
69
  # `true` if the audit was scheduled successfully, `false` otherwise (like
70
70
  # if the resource is out of scope).
71
- def taint_analysis( payloads, opts = { } )
71
+ def signature_analysis( payloads, opts = { } )
72
72
  return false if self.inputs.empty?
73
73
 
74
74
  if scope.out?
75
- print_debug 'Taint analysis: Element is out of scope,' <<
75
+ print_debug 'Signature analysis: Element is out of scope,' <<
76
76
  " skipping: #{audit_id}"
77
77
  return false
78
78
  end
@@ -81,8 +81,8 @@ module Taint
81
81
  # we've evaluated our control response.
82
82
  @candidate_issues = []
83
83
 
84
- # Perform the taint analysis.
85
- opts = self.class::OPTIONS.merge( TAINT_OPTIONS.merge( opts ) )
84
+ # Perform the analysis.
85
+ opts = self.class::OPTIONS.merge( SIGNATURE_OPTIONS.merge( opts ) )
86
86
  audit( payloads, opts ) { |response| get_matches( response ) }
87
87
  end
88
88
 
@@ -104,7 +104,7 @@ module Taint
104
104
 
105
105
  def match_patterns( patterns, matcher, response, opts )
106
106
  k = [patterns, response.body]
107
- return if TAINT_CACHE[:match][k] == false
107
+ return if SIGNATURE_CACHE[:match][k] == false
108
108
 
109
109
  if opts[:longest_word_optimization]
110
110
  opts[:downcased_body] = response.body.downcase
@@ -114,7 +114,7 @@ module Taint
114
114
  when Regexp, String, Array
115
115
  [patterns].flatten.compact.each do |pattern|
116
116
  res = matcher.call( pattern, response, opts )
117
- TAINT_CACHE[:match][k] ||= !!res
117
+ SIGNATURE_CACHE[:match][k] ||= !!res
118
118
  end
119
119
 
120
120
  when Hash
@@ -122,7 +122,7 @@ module Taint
122
122
  [patterns[opts[:platform]]].flatten.compact.each do |p|
123
123
  [p].flatten.compact.each do |pattern|
124
124
  res = matcher.call( pattern, response, opts )
125
- TAINT_CACHE[:match][k] ||= !!res
125
+ SIGNATURE_CACHE[:match][k] ||= !!res
126
126
  end
127
127
  end
128
128
 
@@ -133,7 +133,7 @@ module Taint
133
133
 
134
134
  [p].flatten.compact.each do |pattern|
135
135
  res = matcher.call( pattern, response, dopts )
136
- TAINT_CACHE[:match][k] ||= !!res
136
+ SIGNATURE_CACHE[:match][k] ||= !!res
137
137
  end
138
138
  end
139
139
  end
@@ -149,7 +149,7 @@ module Taint
149
149
 
150
150
  [p].flatten.compact.each do |pattern|
151
151
  res = matcher.call( pattern, response, dopts )
152
- TAINT_CACHE[:match][k] ||= !!res
152
+ SIGNATURE_CACHE[:match][k] ||= !!res
153
153
  end
154
154
  end
155
155
  end
@@ -159,9 +159,9 @@ module Taint
159
159
  return if substring.to_s.empty?
160
160
 
161
161
  k = [substring, response.body]
162
- return if TAINT_CACHE[:match][k] == false
162
+ return if SIGNATURE_CACHE[:match][k] == false
163
163
 
164
- TAINT_CACHE[:match][k] = includes = response.body.include?( substring )
164
+ SIGNATURE_CACHE[:match][k] = includes = response.body.include?( substring )
165
165
  return if !includes || ignore?( response, opts )
166
166
 
167
167
  @candidate_issues << {
@@ -178,7 +178,7 @@ module Taint
178
178
 
179
179
  def match_regexp_and_log( regexp, response, opts )
180
180
  k = [regexp, response.body]
181
- return if TAINT_CACHE[:match][k] == false
181
+ return if SIGNATURE_CACHE[:match][k] == false
182
182
 
183
183
  regexp = regexp.is_a?( Regexp ) ? regexp :
184
184
  Regexp.new( regexp.to_s, Regexp::IGNORECASE )
@@ -192,7 +192,7 @@ module Taint
192
192
 
193
193
  match_data = match_data[0].to_s
194
194
 
195
- TAINT_CACHE[:match][k] = !match_data.empty?
195
+ SIGNATURE_CACHE[:match][k] = !match_data.empty?
196
196
 
197
197
  return if match_data.empty? || ignore?( response, opts )
198
198
 
@@ -220,13 +220,13 @@ module Taint
220
220
  return if @setup_verification_callbacks
221
221
  @setup_verification_callbacks = true
222
222
 
223
- # Go over the issues and flag them as untrusted if the pattern that
224
- # caused them to be logged matches the untainted response.
223
+ # Go over the issues to ensure that the signature that identified them
224
+ # does not match by default.
225
225
  http.after_run do
226
226
  @setup_verification_callbacks = false
227
227
  next if @candidate_issues.empty?
228
228
 
229
- # Grab an untainted response.
229
+ # Grab the default response.
230
230
  submit do |response|
231
231
  # Something has gone wrong, timed-out request or closed connection.
232
232
  # If we can't verify the issue bail out...