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
@@ -20,6 +20,8 @@ module HTTP
20
20
  #
21
21
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
22
22
  class ProxyServer < WEBrick::HTTPProxyServer
23
+ include Arachni::UI::Output
24
+ personalize_output
23
25
 
24
26
  CACHE = {
25
27
  format_field_name: Support::Cache::LeastRecentlyPushed.new( 100 )
@@ -59,9 +61,9 @@ class ProxyServer < WEBrick::HTTPProxyServer
59
61
  ssl_certificate_name: [ [ 'CN', 'Arachni' ] ]
60
62
  }.merge( options )
61
63
 
62
- @logger = WEBrick::Log.new( Arachni.null_device, 7 )
64
+ @logger = WEBrick::Log.new( $stderr, 5 )
63
65
  # Will force the proxy to stfu.
64
- @logger.close
66
+ @logger.close if !Arachni::UI::Output.debug?( 3 )
65
67
 
66
68
  @interceptor_ports = {}
67
69
  @interceptors = {}
@@ -86,8 +88,12 @@ class ProxyServer < WEBrick::HTTPProxyServer
86
88
  # Starts the server without blocking, it'll only block until the server is
87
89
  # up and running and ready to accept connections.
88
90
  def start_async
91
+ print_debug_level_2 'Starting'
92
+
89
93
  Thread.new { start }
90
94
  sleep 0.1 while !running?
95
+
96
+ print_debug_level_2 'Started'
91
97
  nil
92
98
  end
93
99
 
@@ -115,11 +121,17 @@ class ProxyServer < WEBrick::HTTPProxyServer
115
121
  end
116
122
 
117
123
  def shutdown
124
+ print_debug_level_2 'Shutting down..'
125
+
126
+ print_debug_level_2 "-- Interceptors: #{@interceptors.size}"
118
127
  @interceptors.each do |_, interceptor|
128
+ print_debug_level_2 "---- Interceptor: #{interceptor}"
119
129
  interceptor.shutdown
120
130
  end
121
131
 
122
132
  super
133
+
134
+ print_debug_level_2 'Shutdown.'
123
135
  end
124
136
 
125
137
  private
@@ -185,13 +197,20 @@ class ProxyServer < WEBrick::HTTPProxyServer
185
197
  # @see #service
186
198
  # @see Webrick::HTTPProxyServer#service
187
199
  def do_CONNECT( req, res )
200
+ print_debug_level_2 "[#{__method__}] Start: #{req.unparsed_uri}"
201
+
188
202
  host = req.unparsed_uri.split(':').first
189
203
 
190
204
  req.instance_variable_set( :@unparsed_uri, "127.0.0.1:#{interceptor_port( host )}" )
191
205
 
206
+ print_debug_level_2 "[#{__method__}] Intercepting via: #{req.unparsed_uri}"
192
207
  start_ssl_interceptor( host )
193
208
 
194
- super( req, res )
209
+ r = super( req, res )
210
+
211
+ print_debug_level_2 "[#{__method__}] Done: #{req.unparsed_uri}"
212
+
213
+ r
195
214
  end
196
215
 
197
216
  # @param [Hash] options
@@ -222,7 +241,24 @@ class ProxyServer < WEBrick::HTTPProxyServer
222
241
  #
223
242
  # The interceptor will listen on {#interceptor_port}.
224
243
  def start_ssl_interceptor( host )
225
- return @interceptors[host] if @interceptors[host]
244
+ if @interceptors[host]
245
+ print_debug_level_2 "[#{__method__}] [#{host}] Already started."
246
+ return @interceptors[host]
247
+ end
248
+
249
+ if @interceptors[host] == :pending
250
+ print_debug_level_2 "[#{__method__}] [#{host}] Another is already starting, waiting."
251
+
252
+ sleep 0.1 while @interceptors[host] == :pending
253
+
254
+ print_debug_level_2 "[#{__method__}] [#{host}] Started."
255
+
256
+ return @interceptors[host]
257
+ end
258
+
259
+ print_debug_level_2 "[#{__method__}] [#{host}] No interceptor available, starting new one."
260
+
261
+ @interceptors[host] = :pending
226
262
 
227
263
  ca = OpenSSL::X509::Certificate.new( File.read( INTERCEPTOR_CA_CERTIFICATE ) )
228
264
  ca_key = OpenSSL::PKey::RSA.new( File.read( INTERCEPTOR_CA_KEY ) )
@@ -264,7 +300,7 @@ class ProxyServer < WEBrick::HTTPProxyServer
264
300
 
265
301
  # The interceptor is only used for SSL decryption/encryption, the actual
266
302
  # proxy functionality is forwarded to the plain proxy server.
267
- @interceptors[host] = interceptor = self.class.new(
303
+ interceptor = self.class.new(
268
304
  address: '127.0.0.1',
269
305
  port: interceptor_port( host ),
270
306
  ssl_certificate: cert,
@@ -277,6 +313,9 @@ class ProxyServer < WEBrick::HTTPProxyServer
277
313
  end
278
314
 
279
315
  interceptor.start_async
316
+
317
+ @interceptors[host] = interceptor
318
+ print_debug_level_2 "[#{__method__}] [#{host}] Started."
280
319
  end
281
320
 
282
321
  # @return [Integer]
@@ -288,6 +327,8 @@ class ProxyServer < WEBrick::HTTPProxyServer
288
327
  # Communicates with the endpoint webapp and forwards its responses to the
289
328
  # proxy which then sends it to the browser.
290
329
  def perform_proxy_request( req, res )
330
+ print_debug_level_2 "[#{__method__}] Starting: #{req.request_line.strip}"
331
+
291
332
  request = yield( req.request_uri.to_s, setup_proxy_header( req, res ) )
292
333
  response = nil
293
334
 
@@ -317,6 +358,8 @@ class ProxyServer < WEBrick::HTTPProxyServer
317
358
  @options[:response_handler].call( request, response )
318
359
  end
319
360
 
361
+ print_debug_level_2 "[#{__method__}] Completed: #{req.request_line.strip}"
362
+
320
363
  # Disable persistent connections since they're not supported by the
321
364
  # server.
322
365
  res['proxy-connection'] = 'close'
@@ -348,6 +391,10 @@ class ProxyServer < WEBrick::HTTPProxyServer
348
391
  key = key.downcase
349
392
  next if SKIP_HEADERS.include?( key ) || connections.include?( key )
350
393
 
394
+ if key == 'cache-control' && value.is_a?( Array )
395
+ value = value.join( ', ' )
396
+ end
397
+
351
398
  dst[self.class.format_field_name( key )] = value
352
399
  end
353
400
  end
@@ -512,7 +512,7 @@ class Request < Message
512
512
  headers.each { |k, v| headers[k] = Header.encode( v ) if v }
513
513
 
514
514
  headers['Cookie'] = effective_cookies.
515
- map { |k, v| "#{Cookie.encode( k )}=#{Cookie.encode( v )}" }.
515
+ map { |k, v| "#{Cookie.encode( k, true )}=#{Cookie.encode( v )}" }.
516
516
  join( ';' )
517
517
  headers.delete( 'Cookie' ) if headers['Cookie'].empty?
518
518
 
@@ -15,12 +15,6 @@ require Options.paths.lib + 'issue/severity'
15
15
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
16
16
  class Issue
17
17
 
18
- # Attributes removed from a parent issue (i.e. an issue with variations)
19
- # and solely populating variations.
20
- VARIATION_ATTRIBUTES = Set.new([
21
- :@page, :@referring_page, :@proof, :@signature, :@remarks, :@trusted
22
- ])
23
-
24
18
  # @return [String]
25
19
  # Name.
26
20
  attr_accessor :name
@@ -108,10 +102,6 @@ class Issue
108
102
  # made the remark, value is an `Array` of remarks.
109
103
  attr_accessor :remarks
110
104
 
111
- # @return [Array<Issue>]
112
- # Variations of this issue.
113
- attr_accessor :variations
114
-
115
105
  # @return [Issue,nil]
116
106
  # Parent of variation.
117
107
  attr_accessor :parent
@@ -132,9 +122,6 @@ class Issue
132
122
  @trusted = true if @trusted.nil?
133
123
  @references ||= {}
134
124
  @tags ||= []
135
- @variations ||= []
136
- @variation = nil
137
- @parent = nil
138
125
  end
139
126
 
140
127
  # @note The whole environment needs to be fresh.
@@ -213,10 +200,6 @@ class Issue
213
200
  #
214
201
  # @see #passive?
215
202
  def active?
216
- if variations && variations.any?
217
- return variations.first.active?
218
- end
219
-
220
203
  !!(vector.respond_to?( :affected_input_name ) && vector.affected_input_name)
221
204
  end
222
205
 
@@ -226,11 +209,6 @@ class Issue
226
209
  # @see #passive?
227
210
  def affected_input_name
228
211
  return if !active?
229
-
230
- if variations && variations.any?
231
- return variations.first.vector.affected_input_name
232
- end
233
-
234
212
  vector.affected_input_name
235
213
  end
236
214
 
@@ -314,60 +292,40 @@ class Issue
314
292
  h[:vector] = vector.to_h
315
293
  h.delete( :unique_id )
316
294
 
317
- if solo?
318
- h.delete( :variation )
319
- else
320
- if variation?
321
- h[:vector].delete :source
322
- h[:vector].delete :type
323
- h[:vector].delete :url
324
- h[:vector].delete :action
325
- h[:vector].delete :default_inputs
326
- h[:vector].delete :affected_input_name
327
- else
328
- h[:vector][:inputs] = h[:vector].delete( :default_inputs )
329
- h[:vector][:affected_input_name] = affected_input_name
330
- end
331
- end
332
-
333
- if !variation? || solo?
334
- h[:digest] = digest
335
- h[:severity] = severity.to_sym
336
- h[:cwe_url] = cwe_url if cwe_url
337
-
338
- # Since we're doing the whole cross-platform hash thing better switch
339
- # the Element classes in the check's info data to symbols.
340
- h[:check][:elements] ||= []
341
- h[:check][:elements] = h[:check][:elements].map(&:type)
295
+ h[:vector][:affected_input_name] = affected_input_name
342
296
 
343
- h[:variations] = @variations.map(&:to_h)
344
- end
297
+ h[:digest] = digest
298
+ h[:severity] = severity.to_sym
299
+ h[:cwe_url] = cwe_url if cwe_url
345
300
 
346
- if variation? || solo?
347
- if page
348
- dom_h = page.dom.to_h
349
- dom_h.delete(:skip_states)
301
+ # Since we're doing the whole cross-platform hash thing better switch
302
+ # the Element classes in the check's info data to symbols.
303
+ h[:check][:elements] ||= []
304
+ h[:check][:elements] = h[:check][:elements].map(&:type)
350
305
 
351
- h[:page] = {
352
- body: page.body,
353
- dom: dom_h
354
- }
355
- end
306
+ if page
307
+ dom_h = page.dom.to_h
308
+ dom_h.delete(:skip_states)
356
309
 
357
- if referring_page
358
- referring_page_dom_h = referring_page.dom.to_h
359
- referring_page_dom_h.delete(:skip_states)
310
+ h[:page] = {
311
+ body: page.body,
312
+ dom: dom_h
313
+ }
314
+ end
360
315
 
361
- h[:referring_page] = {
362
- body: referring_page.body,
363
- dom: referring_page_dom_h
364
- }
365
- end
316
+ if referring_page
317
+ referring_page_dom_h = referring_page.dom.to_h
318
+ referring_page_dom_h.delete(:skip_states)
366
319
 
367
- h[:response] = response.to_h if response
368
- h[:request] = request.to_h if request
320
+ h[:referring_page] = {
321
+ body: referring_page.body,
322
+ dom: referring_page_dom_h
323
+ }
369
324
  end
370
325
 
326
+ h[:response] = response.to_h if response
327
+ h[:request] = request.to_h if request
328
+
371
329
  h.delete :parent
372
330
 
373
331
  h
@@ -378,7 +336,11 @@ class Issue
378
336
  # A string uniquely identifying this issue.
379
337
  def unique_id
380
338
  return @unique_id if @unique_id
381
- vector_info = active? ? "#{vector.method}:#{vector.affected_input_name}:" : nil
339
+
340
+ vector_info = active? ?
341
+ "#{vector.method}:#{vector.affected_input_name}:" :
342
+ "#{proof}:"
343
+
382
344
  "#{name}:#{vector_info}#{vector.action.split( '?' ).first}"
383
345
  end
384
346
 
@@ -390,90 +352,6 @@ class Issue
390
352
  unique_id.persistent_hash
391
353
  end
392
354
 
393
- # @return [Bool]
394
- # `true` if the issue neither has nor is a variation, `false` otherwise.
395
- def solo?
396
- @variation.nil?
397
- end
398
-
399
- # @return [Bool]
400
- # `true` if `self` is a variation.
401
- def variation?
402
- !!@variation
403
- end
404
-
405
- # @return [Issue]
406
- # A copy of `self` **without** {VARIATION_ATTRIBUTES specific} details
407
- # and an empty array of {#variations} to be populated.
408
- #
409
- # Also, the {#vector} attribute will hold the original, non-mutated vector.
410
- def with_variations
411
- issue = self.deep_clone
412
-
413
- instance_variables.each do |k|
414
- next if k == :@trusted || !VARIATION_ATTRIBUTES.include?( k ) ||
415
- !issue.instance_variable_defined?( k )
416
-
417
- issue.remove_instance_variable k
418
- end
419
-
420
- issue.vector.reset
421
-
422
- issue.unique_id = unique_id
423
- issue.variation = false
424
- issue.parent = nil
425
- issue
426
- end
427
-
428
- # @return [Issue]
429
- # A copy of `self` with {VARIATION_ATTRIBUTES specific} details **only**
430
- # and the mutated {#vector}.
431
- def as_variation
432
- issue = self.deep_clone
433
-
434
- instance_variables.each do |k|
435
- next if k == :@vector || VARIATION_ATTRIBUTES.include?( k ) ||
436
- !issue.instance_variable_defined?( k )
437
-
438
- issue.remove_instance_variable k
439
- end
440
-
441
- issue.unique_id = unique_id
442
- issue.variation = true
443
- issue.parent = self
444
- issue
445
- end
446
-
447
- # Converts `self` to a solo issue, in place.
448
- #
449
- # @param [Issue] issue
450
- # Parent issue.
451
- # @return [Issue]
452
- # Solo issue, with generic vulnerability data filled in from `issue`.
453
- def to_solo!( issue )
454
- issue.instance_variables.each do |k|
455
- next if k == :@variations || k == :@vector || k == :@trusted
456
- next if (val = issue.instance_variable_get(k)).nil?
457
- instance_variable_set( k, val )
458
- end
459
-
460
- @variations = []
461
- @variation = nil
462
- @parent = nil
463
-
464
- self
465
- end
466
-
467
- # Copy of `self` as a solo issue.
468
- #
469
- # @param [Issue] issue
470
- # Parent issue.
471
- # @return [Issue]
472
- # Solo issue, with generic vulnerability data filled in from `issue`.
473
- def to_solo( issue )
474
- deep_clone.to_solo!( issue )
475
- end
476
-
477
355
  def ==( other )
478
356
  hash == other.hash
479
357
  end
@@ -491,8 +369,6 @@ class Issue
491
369
  def to_rpc_data
492
370
  data = {}
493
371
  instance_variables.each do |ivar|
494
- next if ivar == :@parent
495
-
496
372
  data[ivar.to_s.gsub('@','')] =
497
373
  instance_variable_get( ivar ).to_rpc_data_or_self
498
374
  end
@@ -502,15 +378,9 @@ class Issue
502
378
  data['check'][:elements] = data['check'][:elements].map(&:to_s)
503
379
  end
504
380
 
505
- if data['variations']
506
- data['variations'] = data['variations'].map(&:to_rpc_data)
507
- end
508
-
509
- if !variation?
510
- data['digest'] = digest
511
- end
512
-
513
- data['severity'] = data['severity'].to_s
381
+ data['unique_id'] = unique_id
382
+ data['digest'] = digest
383
+ data['severity'] = data['severity'].to_s
514
384
 
515
385
  data
516
386
  end
@@ -535,9 +405,6 @@ class Issue
535
405
 
536
406
  value.my_symbolize_keys(false)
537
407
 
538
- when 'variations'
539
- value.map { |i| from_rpc_data i }
540
-
541
408
  when 'remarks'
542
409
  value.my_symbolize_keys
543
410
 
@@ -559,12 +426,6 @@ class Issue
559
426
  instance.instance_variable_set( "@#{name}", value )
560
427
  end
561
428
 
562
- if instance.variations
563
- instance.variations.each do |v|
564
- v.parent = instance
565
- end
566
- end
567
-
568
429
  instance
569
430
  end
570
431
 
@@ -582,10 +443,6 @@ class Issue
582
443
  @unique_id = id
583
444
  end
584
445
 
585
- def variation=( bool )
586
- @variation = bool
587
- end
588
-
589
446
  private
590
447
 
591
448
  def normalize_name( name )
@@ -599,5 +456,3 @@ class Issue
599
456
  protected :remove_instance_variable
600
457
  end
601
458
  end
602
-
603
- Arachni::Severity = Arachni::Issue::Severity