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
@@ -17,7 +17,7 @@ class Arachni::Checks::XFrameOptions < Arachni::Check::Base
17
17
 
18
18
  log(
19
19
  vector: Element::Server.new( page.url ),
20
- proof: page.response.headers_string
20
+ proof: page.response.status_line
21
21
  )
22
22
  end
23
23
 
@@ -54,7 +54,7 @@ embedded into other sites.
54
54
  cwe: 693,
55
55
  severity: Severity::LOW,
56
56
  remedy_guidance: %q{
57
- Configure your web server to include an X-Frame-Options header.
57
+ Configure your web server to include an `X-Frame-Options` header.
58
58
  }
59
59
  }
60
60
  }
@@ -20,7 +20,7 @@ class Arachni::Checks::HttpPut < Arachni::Check::Base
20
20
  end
21
21
 
22
22
  def run
23
- path = get_path( page.url ) + 'Arachni-' + random_seed.to_s[0..4].to_s
23
+ path = "#{get_path( page.url )}Arachni-#{random_seed}"
24
24
  return if audited?( path )
25
25
  audited( path )
26
26
 
@@ -44,7 +44,6 @@ class Arachni::Checks::HttpPut < Arachni::Check::Base
44
44
  response: put_response,
45
45
  proof: put_response.status_line
46
46
  )
47
- print_ok "File has been created: #{response.url}"
48
47
  end
49
48
 
50
49
  def self.info
@@ -53,7 +52,7 @@ class Arachni::Checks::HttpPut < Arachni::Check::Base
53
52
  description: %q{Checks if uploading files is possible using the HTTP PUT method.},
54
53
  elements: [ Element::Server ],
55
54
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
56
- version: '0.2.2',
55
+ version: '0.2.3',
57
56
 
58
57
  issue: {
59
58
  name: %q{Publicly writable directory},
@@ -9,15 +9,15 @@
9
9
  # Extract paths from HTML comments.
10
10
  #
11
11
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
12
- # @version 0.2
12
+ # @version 0.2.1
13
13
  class Arachni::Parser::Extractors::Comments < Arachni::Parser::Extractors::Base
14
14
 
15
15
  def run
16
16
  return [] if !includes?( '<!--' )
17
17
 
18
18
  document.xpath( '//comment()' ).map do |comment|
19
- comment.text.scan( /(\/[\/a-zA-Z0-9%._-]+)/ )
20
- end.flatten.select { |s| s.include? '/' }
19
+ comment.text.scan( /(^|\s)(\/[\/a-zA-Z0-9%._-]+)/ )
20
+ end.flatten.select { |s| s.start_with? '/' }
21
21
  end
22
22
 
23
23
  end
@@ -19,7 +19,16 @@ class Arachni::Parser::Extractors::Scripts < Arachni::Parser::Extractors::Base
19
19
  document.search( '//script[@src]' ).map { |a| a['src'] } |
20
20
  document.xpath( '//script' ).map(&:text).join.
21
21
  scan( /[\/a-zA-Z0-9%._-]+/ ).
22
- select { |s| s.include?( '.' ) && s.include?( '/' ) }
22
+ select do |s|
23
+ # String looks like a path, but don't get fooled by comments.
24
+ s.include?( '.' ) && s.include?( '/' ) &&
25
+ !s.include?( '*' ) && !s.start_with?( '//' ) &&
26
+
27
+ # Require absolute paths, otherwise we may get caught in
28
+ # a loop, this context isn't the most reliable for extracting
29
+ # real paths.
30
+ s.start_with?( '/' )
31
+ end
23
32
  end
24
33
 
25
34
  end
@@ -9,20 +9,21 @@
9
9
  # Auto adjusts HTTP throughput for maximum network utilization.
10
10
  #
11
11
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
12
- # @version 0.1.5
13
12
  class Arachni::Plugins::AutoThrottle < Arachni::Plugin::Base
14
13
 
15
14
  is_distributable
16
15
 
17
16
  # Will decrease concurrency if the average response time for each burst is
18
17
  # above this threshold.
19
- THRESHOLD = 0.9
18
+ #
19
+ # One second per response does not exactly say healthy server.
20
+ THRESHOLD = 1
20
21
 
21
22
  # Easy on the throttle.
22
23
  STEP_UP = 1
23
24
 
24
25
  # Hard on the breaks.
25
- STEP_DOWN = -3
26
+ STEP_DOWN = -2
26
27
 
27
28
  # Don't drop bellow this.
28
29
  MIN_CONCURRENCY = 2
@@ -30,29 +31,37 @@ class Arachni::Plugins::AutoThrottle < Arachni::Plugin::Base
30
31
  def prepare
31
32
  http = framework.http
32
33
 
33
- # run for each response as it arrives
34
+ # Run for each response as it arrives
34
35
  http.on_complete do
35
- # adjust on a per-burst basis
36
+ # Adjust on a per-burst basis.
36
37
  next if http.burst_response_count == 0 ||
37
38
  http.burst_response_count % http.max_concurrency != 0
38
39
 
39
- if( http.max_concurrency > MIN_CONCURRENCY &&
40
- http.burst_average_response_time > THRESHOLD ) ||
41
- http.max_concurrency > framework.options.http.request_concurrency
40
+ response_time = http.burst_average_response_time
42
41
 
43
- step = http.max_concurrency + STEP_DOWN < MIN_CONCURRENCY ?
44
- MIN_CONCURRENCY - http.max_concurrency : STEP_DOWN
42
+ if http.max_concurrency > MIN_CONCURRENCY &&
43
+ response_time >= THRESHOLD
45
44
 
46
- http.max_concurrency = http.max_concurrency + step
47
- print_info "Decreasing HTTP request concurrency to #{http.max_concurrency} (#{step})."
48
- print_info "Average response time for this burst: #{http.burst_average_response_time}"
45
+ # No-matter what, don't fall bellow the minimum concurrency.
46
+ http.max_concurrency = [
47
+ http.max_concurrency + STEP_DOWN,
48
+ MIN_CONCURRENCY
49
+ ].max
49
50
 
50
- elsif http.burst_average_response_time < THRESHOLD &&
51
- http.max_concurrency < framework.options.http.request_concurrency
51
+ print_info "Decreasing HTTP request concurrency to #{http.max_concurrency}."
52
+ print_info "Average response time for this burst: #{response_time}"
53
+
54
+ elsif http.max_concurrency < http.original_max_concurrency &&
55
+ response_time < THRESHOLD
56
+
57
+ # No-matter what, don't exceed the original maximum concurrency.
58
+ http.max_concurrency = [
59
+ http.max_concurrency + STEP_UP,
60
+ http.original_max_concurrency
61
+ ].min
52
62
 
53
- http.max_concurrency = http.max_concurrency + STEP_UP
54
63
  print_info "Increasing HTTP request concurrency to #{http.max_concurrency} (+#{STEP_UP})."
55
- print_info "Average response time for this burst: #{http.burst_average_response_time}"
64
+ print_info "Average response time for this burst: #{response_time}"
56
65
  end
57
66
  end
58
67
  end
@@ -66,7 +75,7 @@ in order to maintain stability and avoid from killing the server.
66
75
  },
67
76
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
68
77
  tags: %w(meta http throttle),
69
- version: '0.1.5'
78
+ version: '0.1.6'
70
79
  }
71
80
  end
72
81
 
@@ -16,7 +16,6 @@
16
16
  # This is a sort of baseline implementation/anomaly detection.
17
17
  #
18
18
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
19
- # @version 0.3.1
20
19
  class Arachni::Plugins::Discovery < Arachni::Plugin::Base
21
20
 
22
21
  def run
@@ -36,37 +35,35 @@ class Arachni::Plugins::Discovery < Arachni::Plugin::Base
36
35
  Data.issues.each do |issue|
37
36
  next if !issue.tags.includes_tags?( :discovery )
38
37
 
39
- issue.variations.each do |variation|
40
- # Skip it if already flagged as untrusted.
41
- next if variation.untrusted?
42
-
43
- processed_issues += 1
44
-
45
- # We'll do this per path since 404 handlers and such operate per
46
- # directory...usually...probably...hopefully.
47
- path = File.dirname( uri_parse( variation.vector.action ).path )
48
-
49
- # Gather total response sizes per path.
50
- response_size_per_path[path] ||= 0
51
- response_size_per_path[path] += variation.response.body.size
52
-
53
- # Categorize issues per path as well.
54
- issue_digests_per_path[path] ||= []
55
- issue_digests_per_path[path] << variation.digest
56
-
57
- # Extract the static parts of the responses in order to determine
58
- # how much of them doesn't change between requests.
59
- #
60
- # Large deviations between responses are good because it means that
61
- # we're not dealing with some custom not-found response (or something
62
- # similar) as these types of responses stay pretty similar.
63
- #
64
- # On the other hand, valid responses will be dissimilar since the
65
- # discovery checks look for different things.
66
- diffs_per_path[path] = !diffs_per_path[path] ?
67
- variation.response.body :
68
- diffs_per_path[path].rdiff( variation.response.body )
69
- end
38
+ # Skip it if already flagged as untrusted.
39
+ next if issue.untrusted?
40
+
41
+ processed_issues += 1
42
+
43
+ # We'll do this per path since 404 handlers and such operate per
44
+ # directory...usually...probably...hopefully.
45
+ path = File.dirname( uri_parse( issue.vector.action ).path )
46
+
47
+ # Gather total response sizes per path.
48
+ response_size_per_path[path] ||= 0
49
+ response_size_per_path[path] += issue.response.body.size
50
+
51
+ # Categorize issues per path as well.
52
+ issue_digests_per_path[path] ||= []
53
+ issue_digests_per_path[path] << issue.digest
54
+
55
+ # Extract the static parts of the responses in order to determine
56
+ # how much of them doesn't change between requests.
57
+ #
58
+ # Large deviations between responses are good because it means that
59
+ # we're not dealing with some custom not-found response (or something
60
+ # similar) as these types of responses stay pretty similar.
61
+ #
62
+ # On the other hand, valid responses will be dissimilar since the
63
+ # discovery checks look for different things.
64
+ diffs_per_path[path] = !diffs_per_path[path] ?
65
+ issue.response.body :
66
+ diffs_per_path[path].rdiff( issue.response.body )
70
67
  end
71
68
 
72
69
  # Not a lot of sense in comparing a single issue with itself.
@@ -94,7 +91,7 @@ while the server responses were exhibiting an anomalous factor of similarity.
94
91
  There's a good chance that these issues are false positives.
95
92
  },
96
93
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
97
- version: '0.3.1',
94
+ version: '0.3.2',
98
95
  tags: %w(anomaly discovery file directories meta)
99
96
  }
100
97
  end
@@ -10,8 +10,6 @@
10
10
  # pages returned unusually high response times to begin with.
11
11
  #
12
12
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
13
- #
14
- # @version 0.3
15
13
  class Arachni::Plugins::TimingAttacks < Arachni::Plugin::Base
16
14
 
17
15
  is_distributable
@@ -61,16 +59,14 @@ class Arachni::Plugins::TimingAttacks < Arachni::Plugin::Base
61
59
  @times.each_pair { |url, time| avg[url] = time / @counter[url] }
62
60
 
63
61
  Data.issues.each do |issue|
64
- issue.variations.each do |variation|
65
- response_time = avg[uri_parse( variation.vector.action ).up_to_path.persistent_hash]
66
- next if !issue.tags.includes_tags?( TAG ) || !response_time ||
67
- response_time < TIME_THRESHOLD
62
+ response_time = avg[uri_parse( issue.vector.action ).up_to_path.persistent_hash]
63
+ next if !issue.tags.includes_tags?( TAG ) || !response_time ||
64
+ response_time < TIME_THRESHOLD
68
65
 
69
- variation.add_remark :meta_analysis, REMARK
66
+ issue.add_remark :meta_analysis, REMARK
70
67
 
71
- # Requires manual verification.
72
- variation.trusted = false
73
- end
68
+ # Requires manual verification.
69
+ issue.trusted = false
74
70
  end
75
71
  end
76
72
 
@@ -90,7 +86,7 @@ Pages with high response times usually include heavy-duty processing which makes
90
86
  them prime targets for Denial-of-Service attacks.
91
87
  },
92
88
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
93
- version: '0.3',
89
+ version: '0.3.1',
94
90
  tags: %w(anomaly timing attacks meta)
95
91
  }
96
92
  end
@@ -14,7 +14,7 @@ class Arachni::Plugins::LoginScript < Arachni::Plugin::Base
14
14
  STATUSES = {
15
15
  success: 'Login was successful.',
16
16
  failure: 'The script was executed successfully, but the login check failed.',
17
- error: 'A runtime error was encountered while executing the login script.',
17
+ error: 'An error was encountered while executing the login script.',
18
18
  missing_browser: 'A browser is required for this operation but is not available.',
19
19
  missing_check: 'No session check was provided, either via interface options or the script.'
20
20
  }
@@ -43,12 +43,18 @@ class Arachni::Plugins::LoginScript < Arachni::Plugin::Base
43
43
  session.record_login_sequence do |browser|
44
44
  print_info 'Running the script.'
45
45
  @script.call browser ? browser.watir : nil
46
+
47
+ # JS run async so we need to wait for the page to settle after
48
+ # execution.
49
+ session.browser.wait_till_ready if javascript?
50
+
46
51
  print_info 'Execution completed.'
47
52
  end
48
53
 
49
54
  begin
50
55
  session.login( true )
51
- rescue => e
56
+ rescue Exception => e
57
+ print_exception e
52
58
  set_status :error
53
59
  return
54
60
  end
@@ -171,7 +177,7 @@ in the browser, within the page of the target URL.
171
177
 
172
178
  },
173
179
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
174
- version: '0.2',
180
+ version: '0.2.2',
175
181
  options: [
176
182
  Options::Path.new( :script,
177
183
  required: true,
@@ -78,10 +78,11 @@ class Arachni::Plugins::Proxy < Arachni::Plugin::Base
78
78
  end
79
79
 
80
80
  wait_while_framework_running
81
- @server.shutdown
82
81
  end
83
82
 
84
83
  def clean_up
84
+ @server.shutdown
85
+
85
86
  @pages.each { |p| framework.push_to_page_queue( p, true ) }
86
87
  framework_resume
87
88
  end
@@ -191,7 +192,7 @@ class Arachni::Plugins::Proxy < Arachni::Plugin::Base
191
192
  if shutdown?( url )
192
193
  print_status 'Shutting down...'
193
194
  set_response_body( res, erb( :shutdown_message ) )
194
- @server.shutdown
195
+ clean_up
195
196
  return
196
197
  end
197
198
 
@@ -497,7 +498,7 @@ a way to restrict usage enough to avoid users unwittingly interfering with each
497
498
  others' sessions.
498
499
  },
499
500
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
500
- version: '0.3.4',
501
+ version: '0.3.5',
501
502
  options: [
502
503
  Options::Port.new( :port,
503
504
  description: 'Port to bind to.',
@@ -271,14 +271,9 @@ access unauthorized pages.
271
271
  end
272
272
 
273
273
  def issue_id( issue )
274
- # Trust evaluation needs to come from variations.
275
- untrusted = issue.variation? ?
276
- issue.untrusted? : issue.variations.first.untrusted?
274
+ issue = report.issue_by_digest( issue.digest )
277
275
 
278
- # Generic issue data needs to come from the parent.
279
- issue = report.issue_by_digest( issue.digest ) if issue.variation?
280
-
281
- "issues-#{'un' if untrusted}trusted-severity-" <<
276
+ "issues-#{'un' if issue.untrusted?}trusted-severity-" <<
282
277
  "#{issue.severity}-#{issue.check[:shortname]}-#{issue.digest}"
283
278
  end
284
279
 
@@ -367,7 +362,7 @@ access unauthorized pages.
367
362
 
368
363
  grouped_issues[:trusted][by_severity.first.severity] =
369
364
  by_name.inject({}) do |h, (name, issues)|
370
- i = issues.select { |i| !i.variations.find(&:untrusted?) }
365
+ i = issues.select(&:trusted?)
371
366
  next h if i.empty?
372
367
 
373
368
  h[name] = i
@@ -376,7 +371,7 @@ access unauthorized pages.
376
371
 
377
372
  grouped_issues[:untrusted][by_severity.first.severity] =
378
373
  by_name.inject({}) do |h, (name, issues)|
379
- i = issues.select { |i| i.variations.find(&:untrusted?) }
374
+ i = issues.select(&:untrusted?)
380
375
  next h if i.empty?
381
376
 
382
377
  h[name] = i
@@ -445,7 +440,7 @@ access unauthorized pages.
445
440
  description: %q{Exports the audit results as a compressed HTML report.},
446
441
  content_type: 'application/zip',
447
442
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
448
- version: '0.4.1',
443
+ version: '0.4.2',
449
444
  options: [
450
445
  Options.outfile( '.html.zip' ),
451
446
  Options.skip_responses
@@ -501,9 +496,11 @@ access unauthorized pages.
501
496
  Element::Body.type => 0,
502
497
  Element::Path.type => 0,
503
498
  Element::Server.type => 0,
504
- Element::GenericDOM.type => 0,
505
- Element::JSON.type => 0,
506
- Element::XML.type => 0
499
+ Element::GenericDOM.type => 0,
500
+ Element::JSON.type => 0,
501
+ Element::XML.type => 0,
502
+ Element::UIInput::DOM.type => 0,
503
+ Element::UIForm::DOM.type => 0
507
504
  },
508
505
  verification: {
509
506
  'Yes' => 0,
@@ -564,7 +561,7 @@ access unauthorized pages.
564
561
  graph_data[:severity_index_for_issue][issue.name] =
565
562
  Issue::Severity::ORDER.reverse.index( issue.severity.to_sym ) + 1
566
563
 
567
- if issue.variations.first.trusted?
564
+ if issue.trusted?
568
565
  has_trusted_issues = true
569
566
  graph_data[:trust]['Trusted'] += 1
570
567
  graph_data[:trusted_severities][issue.severity.to_sym] += 1
@@ -17,9 +17,9 @@
17
17
  <% end.join( ', ') %>
18
18
  <% end %>
19
19
 
20
- <% if issue.variations.first.request %>
20
+ <% if issue.request %>
21
21
  using
22
- <code><%= issue.variations.first.request.method.to_s.upcase %></code>
22
+ <code><%= issue.request.method.to_s.upcase %></code>
23
23
  <% end %>
24
24
  </a>
25
25
 
@@ -37,45 +37,20 @@
37
37
  </div>
38
38
 
39
39
  <div class="panel-body">
40
- <% if issue.variations.size == 1 %>
41
- <div class="row">
42
- <div class="col-md-12">
43
- <%=
44
- erb 'issue/info.erb',
45
- issue: issue.variations.first,
46
- parent_issue: issue,
47
- id: issue_id( issue )
48
- %>
49
- </div>
50
- </div>
51
- <% else %>
52
- <% issue.variations.each.with_index do |v, i| %>
53
- <div class="row">
54
- <div class="col-md-12">
55
- <strong>
56
- <a
57
- id="<%= issue_id(issue) %>-variation-<%= i %>"
58
- href="<%= issue_location(issue) %>/variation/<%= i %>">
59
- Variation <%= i %>
60
- </a>
61
- </strong>
62
-
63
- <%=
64
- erb 'issue/info.erb',
65
- issue: v,
66
- parent_issue: issue,
67
- id: issue_id( v )
68
- %>
69
- </div>
70
- </div>
71
- <% end %>
72
- <% end %>
40
+ <div class="row">
41
+ <div class="col-md-12">
42
+ <%=
43
+ erb 'issue/info.erb',
44
+ issue: issue,
45
+ id: issue_id( issue )
46
+ %>
47
+ </div>
48
+ </div>
73
49
 
74
50
  <%=
75
51
  erb 'issue/details.erb',
76
- issue: issue.variations.first,
77
- parent_issue: issue,
78
- id: issue_id( issue )
52
+ issue: issue,
53
+ id: issue_id( issue )
79
54
  %>
80
55
  </div>
81
56
  </div>