arachni 1.0.6 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (634) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +193 -0
  3. data/Gemfile +0 -1
  4. data/LICENSE.md +1 -1
  5. data/README.md +23 -18
  6. data/Rakefile +5 -3
  7. data/arachni.gemspec +11 -8
  8. data/bin/arachni +1 -1
  9. data/bin/arachni_console +1 -1
  10. data/bin/arachni_multi +1 -1
  11. data/bin/arachni_reporter +1 -1
  12. data/bin/arachni_restore +1 -1
  13. data/bin/arachni_rpc +1 -1
  14. data/bin/arachni_rpcd +1 -1
  15. data/bin/arachni_rpcd_monitor +1 -1
  16. data/bin/arachni_script +1 -1
  17. data/components/checks/active/code_injection.rb +5 -7
  18. data/components/checks/active/code_injection_php_input_wrapper.rb +1 -1
  19. data/components/checks/active/code_injection_timing.rb +2 -3
  20. data/components/checks/active/csrf.rb +9 -5
  21. data/components/checks/active/file_inclusion.rb +4 -5
  22. data/components/checks/active/ldap_injection.rb +6 -8
  23. data/components/checks/active/no_sql_injection.rb +4 -6
  24. data/components/checks/active/no_sql_injection_differential.rb +1 -1
  25. data/components/checks/active/os_cmd_injection.rb +7 -9
  26. data/components/checks/active/os_cmd_injection_timing.rb +6 -8
  27. data/components/checks/active/path_traversal.rb +6 -7
  28. data/components/checks/active/response_splitting.rb +7 -15
  29. data/components/checks/active/rfi.rb +4 -8
  30. data/components/checks/active/session_fixation.rb +1 -1
  31. data/components/checks/active/source_code_disclosure.rb +9 -7
  32. data/components/checks/active/sql_injection.rb +6 -9
  33. data/components/checks/active/sql_injection_differential.rb +3 -3
  34. data/components/checks/active/sql_injection_timing.rb +6 -8
  35. data/components/checks/active/trainer.rb +4 -4
  36. data/components/checks/active/unvalidated_redirect.rb +7 -6
  37. data/components/checks/active/unvalidated_redirect_dom.rb +97 -0
  38. data/components/checks/active/xpath_injection.rb +7 -8
  39. data/components/checks/active/xss.rb +11 -10
  40. data/components/checks/active/xss_dom.rb +3 -4
  41. data/components/checks/active/xss_dom_inputs.rb +1 -1
  42. data/components/checks/active/xss_dom_script_context.rb +6 -7
  43. data/components/checks/active/xss_event.rb +4 -4
  44. data/components/checks/active/xss_path.rb +1 -1
  45. data/components/checks/active/xss_script_context.rb +11 -4
  46. data/components/checks/active/xss_tag.rb +6 -6
  47. data/components/checks/active/xxe.rb +110 -0
  48. data/components/checks/passive/allowed_methods.rb +1 -1
  49. data/components/checks/passive/backdoors.rb +1 -1
  50. data/components/checks/passive/backup_directories.rb +1 -1
  51. data/components/checks/passive/backup_files.rb +1 -1
  52. data/components/checks/passive/common_directories.rb +1 -1
  53. data/components/checks/passive/common_directories/directories.txt +2 -0
  54. data/components/checks/passive/common_files.rb +1 -1
  55. data/components/checks/passive/directory_listing.rb +1 -1
  56. data/components/checks/passive/grep/captcha.rb +2 -2
  57. data/components/checks/passive/grep/cookie_set_for_parent_domain.rb +1 -1
  58. data/components/checks/passive/grep/credit_card.rb +1 -1
  59. data/components/checks/passive/grep/cvs_svn_users.rb +1 -1
  60. data/components/checks/passive/grep/emails.rb +1 -1
  61. data/components/checks/passive/grep/form_upload.rb +2 -2
  62. data/components/checks/passive/grep/hsts.rb +2 -2
  63. data/components/checks/passive/grep/html_objects.rb +4 -4
  64. data/components/checks/passive/grep/http_only_cookies.rb +1 -1
  65. data/components/checks/passive/grep/insecure_cookies.rb +1 -1
  66. data/components/checks/passive/grep/insecure_cors_policy.rb +66 -0
  67. data/components/checks/passive/grep/mixed_resource.rb +1 -1
  68. data/components/checks/passive/grep/password_autocomplete.rb +2 -2
  69. data/components/checks/passive/grep/private_ip.rb +1 -1
  70. data/components/checks/passive/grep/ssn.rb +1 -1
  71. data/components/checks/passive/grep/unencrypted_password_forms.rb +2 -2
  72. data/components/checks/passive/grep/x_frame_options.rb +61 -0
  73. data/components/checks/passive/htaccess_limit.rb +1 -1
  74. data/components/checks/passive/http_put.rb +10 -3
  75. data/components/checks/passive/insecure_client_access_policy.rb +91 -0
  76. data/components/checks/passive/insecure_cross_domain_policy_access.rb +91 -0
  77. data/components/checks/passive/insecure_cross_domain_policy_headers.rb +91 -0
  78. data/components/checks/passive/interesting_responses.rb +1 -1
  79. data/components/checks/passive/localstart_asp.rb +1 -1
  80. data/components/checks/passive/origin_spoof_access_restriction_bypass.rb +1 -1
  81. data/components/checks/passive/webdav.rb +1 -1
  82. data/components/checks/passive/xst.rb +1 -1
  83. data/components/fingerprinters/frameworks/rack.rb +1 -1
  84. data/components/fingerprinters/languages/asp.rb +1 -1
  85. data/components/fingerprinters/languages/aspx.rb +1 -1
  86. data/components/fingerprinters/languages/jsp.rb +1 -1
  87. data/components/fingerprinters/languages/php.rb +1 -1
  88. data/components/fingerprinters/languages/python.rb +1 -1
  89. data/components/fingerprinters/languages/ruby.rb +1 -1
  90. data/components/fingerprinters/os/bsd.rb +1 -1
  91. data/components/fingerprinters/os/linux.rb +1 -1
  92. data/components/fingerprinters/os/solaris.rb +1 -1
  93. data/components/fingerprinters/os/unix.rb +1 -1
  94. data/components/fingerprinters/os/windows.rb +1 -1
  95. data/components/fingerprinters/servers/apache.rb +1 -1
  96. data/components/fingerprinters/servers/iis.rb +1 -1
  97. data/components/fingerprinters/servers/jetty.rb +1 -1
  98. data/components/fingerprinters/servers/nginx.rb +1 -1
  99. data/components/fingerprinters/servers/tomcat.rb +1 -1
  100. data/components/path_extractors/anchors.rb +1 -1
  101. data/components/path_extractors/areas.rb +1 -1
  102. data/components/path_extractors/comments.rb +5 -5
  103. data/components/path_extractors/forms.rb +1 -1
  104. data/components/path_extractors/frames.rb +1 -1
  105. data/components/path_extractors/generic.rb +1 -1
  106. data/components/path_extractors/links.rb +1 -1
  107. data/components/path_extractors/meta_refresh.rb +1 -1
  108. data/components/path_extractors/scripts.rb +1 -1
  109. data/components/plugins/autologin.rb +6 -6
  110. data/components/plugins/beep_notify.rb +1 -1
  111. data/components/plugins/content_types.rb +1 -1
  112. data/components/plugins/cookie_collector.rb +1 -1
  113. data/components/plugins/defaults/autothrottle.rb +1 -1
  114. data/components/plugins/defaults/healthmap.rb +1 -1
  115. data/components/plugins/defaults/meta/remedies/discovery.rb +2 -4
  116. data/components/plugins/defaults/meta/remedies/timing_attacks.rb +1 -1
  117. data/components/plugins/defaults/meta/uniformity.rb +1 -1
  118. data/components/plugins/email_notify.rb +24 -12
  119. data/components/plugins/exec.rb +153 -0
  120. data/components/plugins/form_dicattack.rb +4 -4
  121. data/components/plugins/headers_collector.rb +102 -0
  122. data/components/plugins/http_dicattack.rb +4 -4
  123. data/components/plugins/login_script.rb +4 -5
  124. data/components/plugins/proxy.rb +19 -7
  125. data/components/plugins/proxy/template_scope.rb +1 -1
  126. data/components/plugins/script.rb +1 -1
  127. data/components/plugins/uncommon_headers.rb +9 -2
  128. data/components/plugins/vector_collector.rb +73 -0
  129. data/components/plugins/vector_feed.rb +3 -5
  130. data/components/plugins/waf_detector.rb +3 -3
  131. data/components/reporters/ap.rb +1 -1
  132. data/components/reporters/html.rb +138 -14
  133. data/components/reporters/html/default.erb +1 -1
  134. data/components/reporters/html/default/configuration.erb +2 -2
  135. data/components/reporters/html/default/issue/page.erb +1 -1
  136. data/components/reporters/html/default/issue/vector.erb +2 -2
  137. data/components/reporters/html/default/js/charts.js.erb +7 -4
  138. data/components/reporters/html/default/js/helpers.js +2 -0
  139. data/components/reporters/html/default/summary.erb +7 -0
  140. data/components/reporters/html/default/summary/charts.erb +3 -3
  141. data/components/reporters/html/default/summary/issues.erb +1 -91
  142. data/components/reporters/html/default/summary/issues/by_name.erb +90 -0
  143. data/components/reporters/html/default/summary/owasp_top_10.erb +43 -0
  144. data/components/reporters/json.rb +1 -1
  145. data/components/reporters/marshal.rb +1 -1
  146. data/components/reporters/plugin_formatters/html/autologin.rb +1 -1
  147. data/components/reporters/plugin_formatters/html/content_types.rb +1 -1
  148. data/components/reporters/plugin_formatters/html/cookie_collector.rb +1 -1
  149. data/components/reporters/plugin_formatters/html/exec.rb +63 -0
  150. data/components/reporters/plugin_formatters/html/form_dicattack.rb +1 -1
  151. data/components/reporters/plugin_formatters/html/healthmap.rb +1 -1
  152. data/components/reporters/plugin_formatters/html/http_dicattack.rb +1 -1
  153. data/components/reporters/plugin_formatters/html/login_script.rb +1 -1
  154. data/components/reporters/plugin_formatters/html/uncommon_headers.rb +1 -1
  155. data/components/reporters/plugin_formatters/html/uniformity.rb +1 -1
  156. data/components/reporters/plugin_formatters/html/vector_collector.rb +59 -0
  157. data/components/reporters/plugin_formatters/html/waf_detector.rb +1 -1
  158. data/components/reporters/plugin_formatters/stdout/autologin.rb +1 -1
  159. data/components/reporters/plugin_formatters/stdout/content_types.rb +1 -1
  160. data/components/reporters/plugin_formatters/stdout/cookie_collector.rb +1 -1
  161. data/components/reporters/plugin_formatters/stdout/exec.rb +26 -0
  162. data/components/reporters/plugin_formatters/stdout/form_dicattack.rb +1 -1
  163. data/components/reporters/plugin_formatters/stdout/healthmap.rb +1 -1
  164. data/components/reporters/plugin_formatters/stdout/http_dicattack.rb +1 -1
  165. data/components/reporters/plugin_formatters/stdout/login_script.rb +1 -1
  166. data/components/reporters/plugin_formatters/stdout/uncommon_headers.rb +1 -1
  167. data/components/reporters/plugin_formatters/stdout/uniformity.rb +1 -1
  168. data/components/reporters/plugin_formatters/stdout/vector_collector.rb +40 -0
  169. data/components/reporters/plugin_formatters/stdout/waf_detector.rb +1 -1
  170. data/components/reporters/plugin_formatters/xml/autologin.rb +1 -1
  171. data/components/reporters/plugin_formatters/xml/content_types.rb +1 -1
  172. data/components/reporters/plugin_formatters/xml/cookie_collector.rb +1 -1
  173. data/components/reporters/plugin_formatters/xml/exec.rb +26 -0
  174. data/components/reporters/plugin_formatters/xml/form_dicattack.rb +1 -1
  175. data/components/reporters/plugin_formatters/xml/healthmap.rb +1 -1
  176. data/components/reporters/plugin_formatters/xml/http_dicattack.rb +1 -1
  177. data/components/reporters/plugin_formatters/xml/login_script.rb +1 -1
  178. data/components/reporters/plugin_formatters/xml/uncommon_headers.rb +1 -1
  179. data/components/reporters/plugin_formatters/xml/uniformity.rb +1 -1
  180. data/components/reporters/plugin_formatters/xml/vector_collector.rb +44 -0
  181. data/components/reporters/plugin_formatters/xml/waf_detector.rb +1 -1
  182. data/components/reporters/stdout.rb +1 -1
  183. data/components/reporters/txt.rb +1 -1
  184. data/components/reporters/xml.rb +18 -9
  185. data/components/reporters/xml/schema.xsd +73 -8
  186. data/components/reporters/yaml.rb +1 -1
  187. data/config/write_paths.yml +15 -0
  188. data/lib/arachni.rb +1 -1
  189. data/lib/arachni/banner.rb +1 -1
  190. data/lib/arachni/browser.rb +221 -77
  191. data/lib/arachni/browser/element_locator.rb +7 -2
  192. data/lib/arachni/browser/javascript.rb +40 -24
  193. data/lib/arachni/browser/javascript/dom_monitor.rb +1 -1
  194. data/lib/arachni/browser/javascript/proxy.rb +1 -1
  195. data/lib/arachni/browser/javascript/proxy/stub.rb +1 -1
  196. data/lib/arachni/browser/javascript/scripts/dom_monitor.js +8 -3
  197. data/lib/arachni/browser/javascript/scripts/taint_tracer.js +57 -39
  198. data/lib/arachni/browser/javascript/taint_tracer.rb +12 -8
  199. data/lib/arachni/browser/javascript/taint_tracer/frame.rb +1 -1
  200. data/lib/arachni/browser/javascript/taint_tracer/frame/called_function.rb +1 -1
  201. data/lib/arachni/browser/javascript/taint_tracer/sink/base.rb +1 -1
  202. data/lib/arachni/browser/javascript/taint_tracer/sink/data_flow.rb +1 -1
  203. data/lib/arachni/browser/javascript/taint_tracer/sink/execution_flow.rb +1 -1
  204. data/lib/arachni/browser_cluster.rb +5 -3
  205. data/lib/arachni/browser_cluster/job.rb +1 -1
  206. data/lib/arachni/browser_cluster/job/result.rb +1 -1
  207. data/lib/arachni/browser_cluster/jobs/browser_provider.rb +2 -1
  208. data/lib/arachni/browser_cluster/jobs/resource_exploration.rb +2 -1
  209. data/lib/arachni/browser_cluster/jobs/resource_exploration/event_trigger.rb +1 -1
  210. data/lib/arachni/browser_cluster/jobs/resource_exploration/event_trigger/result.rb +1 -1
  211. data/lib/arachni/browser_cluster/jobs/resource_exploration/result.rb +1 -1
  212. data/lib/arachni/browser_cluster/jobs/taint_trace.rb +2 -1
  213. data/lib/arachni/browser_cluster/jobs/taint_trace/event_trigger.rb +1 -1
  214. data/lib/arachni/browser_cluster/jobs/taint_trace/event_trigger/result.rb +1 -1
  215. data/lib/arachni/browser_cluster/jobs/taint_trace/result.rb +1 -1
  216. data/lib/arachni/browser_cluster/worker.rb +16 -16
  217. data/lib/arachni/check.rb +1 -1
  218. data/lib/arachni/check/auditor.rb +40 -17
  219. data/lib/arachni/check/base.rb +1 -1
  220. data/lib/arachni/check/manager.rb +1 -1
  221. data/lib/arachni/component.rb +1 -1
  222. data/lib/arachni/component/base.rb +1 -1
  223. data/lib/arachni/component/manager.rb +1 -1
  224. data/lib/arachni/component/options.rb +1 -1
  225. data/lib/arachni/component/options/address.rb +1 -1
  226. data/lib/arachni/component/options/base.rb +1 -1
  227. data/lib/arachni/component/options/bool.rb +1 -1
  228. data/lib/arachni/component/options/float.rb +1 -1
  229. data/lib/arachni/component/options/int.rb +1 -1
  230. data/lib/arachni/component/options/multiple_choice.rb +1 -1
  231. data/lib/arachni/component/options/object.rb +1 -1
  232. data/lib/arachni/component/options/path.rb +1 -1
  233. data/lib/arachni/component/options/port.rb +1 -1
  234. data/lib/arachni/component/options/string.rb +1 -1
  235. data/lib/arachni/component/options/url.rb +1 -1
  236. data/lib/arachni/component/output.rb +1 -1
  237. data/lib/arachni/component/utilities.rb +1 -1
  238. data/lib/arachni/data.rb +1 -1
  239. data/lib/arachni/data/framework.rb +1 -1
  240. data/lib/arachni/data/framework/rpc.rb +1 -1
  241. data/lib/arachni/data/issues.rb +1 -1
  242. data/lib/arachni/data/plugins.rb +1 -1
  243. data/lib/arachni/data/session.rb +1 -1
  244. data/lib/arachni/element/base.rb +10 -4
  245. data/lib/arachni/element/body.rb +1 -6
  246. data/lib/arachni/element/capabilities/analyzable.rb +1 -1
  247. data/lib/arachni/element/capabilities/analyzable/differential.rb +41 -6
  248. data/lib/arachni/element/capabilities/analyzable/taint.rb +10 -2
  249. data/lib/arachni/element/capabilities/analyzable/timeout.rb +61 -8
  250. data/lib/arachni/element/capabilities/auditable.rb +9 -2
  251. data/lib/arachni/element/capabilities/auditable/dom.rb +6 -7
  252. data/lib/arachni/element/capabilities/inputtable.rb +5 -3
  253. data/lib/arachni/element/capabilities/mutable.rb +182 -67
  254. data/lib/arachni/element/capabilities/refreshable.rb +1 -1
  255. data/lib/arachni/element/capabilities/submittable.rb +3 -3
  256. data/lib/arachni/element/capabilities/with_auditor.rb +1 -1
  257. data/lib/arachni/element/capabilities/with_auditor/output.rb +1 -1
  258. data/lib/arachni/element/capabilities/with_dom.rb +17 -5
  259. data/lib/arachni/element/capabilities/with_node.rb +6 -31
  260. data/lib/arachni/element/capabilities/with_scope.rb +1 -1
  261. data/lib/arachni/element/capabilities/with_scope/scope.rb +8 -2
  262. data/lib/arachni/element/capabilities/with_source.rb +55 -0
  263. data/lib/arachni/element/cookie.rb +39 -112
  264. data/lib/arachni/element/cookie/capabilities/inputtable.rb +53 -0
  265. data/lib/arachni/element/cookie/capabilities/mutable.rb +95 -0
  266. data/lib/arachni/element/cookie/capabilities/with_dom.rb +31 -0
  267. data/lib/arachni/element/cookie/dom.rb +2 -2
  268. data/lib/arachni/element/form.rb +65 -153
  269. data/lib/arachni/element/form/capabilities/auditable.rb +45 -0
  270. data/lib/arachni/element/form/capabilities/mutable.rb +126 -0
  271. data/lib/arachni/element/form/capabilities/submittable.rb +36 -0
  272. data/lib/arachni/element/form/capabilities/with_dom.rb +32 -0
  273. data/lib/arachni/element/form/dom.rb +13 -4
  274. data/lib/arachni/element/generic_dom.rb +5 -3
  275. data/lib/arachni/element/header.rb +16 -11
  276. data/lib/arachni/element/json.rb +145 -0
  277. data/lib/arachni/element/json/capabilities/inputtable.rb +139 -0
  278. data/lib/arachni/element/json/capabilities/mutable.rb +121 -0
  279. data/lib/arachni/element/link.rb +14 -40
  280. data/lib/arachni/element/link/capabilities/auditable.rb +27 -0
  281. data/lib/arachni/element/link/capabilities/submittable.rb +37 -0
  282. data/lib/arachni/element/link/capabilities/with_dom.rb +43 -0
  283. data/lib/arachni/element/link/dom.rb +9 -2
  284. data/lib/arachni/element/link_template.rb +23 -51
  285. data/lib/arachni/element/link_template/capabilities/auditable.rb +27 -0
  286. data/lib/arachni/element/link_template/capabilities/inputtable.rb +47 -0
  287. data/lib/arachni/element/link_template/capabilities/with_dom.rb +42 -0
  288. data/lib/arachni/element/link_template/dom.rb +3 -2
  289. data/lib/arachni/element/path.rb +1 -1
  290. data/lib/arachni/element/server.rb +99 -18
  291. data/lib/arachni/element/xml.rb +195 -0
  292. data/lib/arachni/element/xml/capabilities/inputtable.rb +34 -0
  293. data/lib/arachni/element/xml/capabilities/mutable.rb +39 -0
  294. data/lib/arachni/element_filter.rb +54 -3
  295. data/lib/arachni/error.rb +1 -1
  296. data/lib/arachni/ethon/easy.rb +1 -1
  297. data/lib/arachni/framework.rb +20 -1
  298. data/lib/arachni/framework/parts/audit.rb +29 -22
  299. data/lib/arachni/framework/parts/browser.rb +53 -5
  300. data/lib/arachni/framework/parts/check.rb +11 -2
  301. data/lib/arachni/framework/parts/data.rb +8 -6
  302. data/lib/arachni/framework/parts/platform.rb +1 -1
  303. data/lib/arachni/framework/parts/plugin.rb +1 -1
  304. data/lib/arachni/framework/parts/report.rb +1 -1
  305. data/lib/arachni/framework/parts/scope.rb +1 -1
  306. data/lib/arachni/framework/parts/state.rb +5 -4
  307. data/lib/arachni/http.rb +1 -1
  308. data/lib/arachni/http/client.rb +13 -242
  309. data/lib/arachni/http/client/dynamic_404_handler.rb +474 -0
  310. data/lib/arachni/http/cookie_jar.rb +1 -1
  311. data/lib/arachni/http/headers.rb +11 -2
  312. data/lib/arachni/http/message.rb +1 -1
  313. data/lib/arachni/http/message/scope.rb +1 -1
  314. data/lib/arachni/http/proxy_server.rb +7 -4
  315. data/lib/arachni/http/request.rb +39 -8
  316. data/lib/arachni/http/request/scope.rb +1 -1
  317. data/lib/arachni/http/response.rb +10 -4
  318. data/lib/arachni/http/response/scope.rb +1 -1
  319. data/lib/arachni/issue.rb +17 -7
  320. data/lib/arachni/issue/severity.rb +1 -1
  321. data/lib/arachni/issue/severity/base.rb +1 -1
  322. data/lib/arachni/option_group.rb +1 -1
  323. data/lib/arachni/option_groups.rb +1 -1
  324. data/lib/arachni/option_groups/audit.rb +74 -6
  325. data/lib/arachni/option_groups/browser_cluster.rb +2 -2
  326. data/lib/arachni/option_groups/datastore.rb +1 -1
  327. data/lib/arachni/option_groups/dispatcher.rb +1 -1
  328. data/lib/arachni/option_groups/http.rb +143 -7
  329. data/lib/arachni/option_groups/input.rb +1 -1
  330. data/lib/arachni/option_groups/output.rb +1 -1
  331. data/lib/arachni/option_groups/paths.rb +1 -1
  332. data/lib/arachni/option_groups/rpc.rb +1 -1
  333. data/lib/arachni/option_groups/scope.rb +9 -9
  334. data/lib/arachni/option_groups/session.rb +1 -1
  335. data/lib/arachni/option_groups/snapshot.rb +1 -1
  336. data/lib/arachni/options.rb +1 -1
  337. data/lib/arachni/page.rb +81 -45
  338. data/lib/arachni/page/dom.rb +13 -3
  339. data/lib/arachni/page/dom/transition.rb +1 -1
  340. data/lib/arachni/page/scope.rb +1 -1
  341. data/lib/arachni/parser.rb +11 -1
  342. data/lib/arachni/platform.rb +1 -1
  343. data/lib/arachni/platform/fingerprinter.rb +1 -1
  344. data/lib/arachni/platform/list.rb +1 -1
  345. data/lib/arachni/platform/manager.rb +1 -1
  346. data/lib/arachni/plugin.rb +1 -1
  347. data/lib/arachni/plugin/base.rb +11 -4
  348. data/lib/arachni/plugin/formatter.rb +1 -1
  349. data/lib/arachni/plugin/manager.rb +13 -5
  350. data/lib/arachni/processes.rb +1 -1
  351. data/lib/arachni/processes/dispatchers.rb +1 -1
  352. data/lib/arachni/processes/helpers.rb +1 -1
  353. data/lib/arachni/processes/helpers/dispatchers.rb +1 -1
  354. data/lib/arachni/processes/helpers/instances.rb +1 -1
  355. data/lib/arachni/processes/helpers/processes.rb +1 -1
  356. data/lib/arachni/processes/instances.rb +1 -1
  357. data/lib/arachni/processes/manager.rb +8 -3
  358. data/lib/arachni/report.rb +12 -2
  359. data/lib/arachni/reporter.rb +1 -1
  360. data/lib/arachni/reporter/base.rb +1 -1
  361. data/lib/arachni/reporter/formatter_manager.rb +1 -1
  362. data/lib/arachni/reporter/manager.rb +1 -1
  363. data/lib/arachni/reporter/options.rb +1 -1
  364. data/lib/arachni/rpc/client/base.rb +1 -1
  365. data/lib/arachni/rpc/client/dispatcher.rb +1 -1
  366. data/lib/arachni/rpc/client/instance.rb +1 -1
  367. data/lib/arachni/rpc/client/instance/framework.rb +1 -1
  368. data/lib/arachni/rpc/client/instance/service.rb +1 -1
  369. data/lib/arachni/rpc/serializer.rb +3 -1
  370. data/lib/arachni/rpc/server/active_options.rb +1 -25
  371. data/lib/arachni/rpc/server/base.rb +1 -1
  372. data/lib/arachni/rpc/server/check/manager.rb +1 -1
  373. data/lib/arachni/rpc/server/dispatcher.rb +1 -1
  374. data/lib/arachni/rpc/server/dispatcher/node.rb +1 -1
  375. data/lib/arachni/rpc/server/dispatcher/service.rb +1 -1
  376. data/lib/arachni/rpc/server/framework.rb +1 -1
  377. data/lib/arachni/rpc/server/framework/distributor.rb +2 -6
  378. data/lib/arachni/rpc/server/framework/master.rb +1 -1
  379. data/lib/arachni/rpc/server/framework/multi_instance.rb +1 -1
  380. data/lib/arachni/rpc/server/framework/slave.rb +1 -1
  381. data/lib/arachni/rpc/server/instance.rb +9 -1
  382. data/lib/arachni/rpc/server/output.rb +1 -1
  383. data/lib/arachni/rpc/server/plugin/manager.rb +1 -1
  384. data/lib/arachni/ruby.rb +1 -1
  385. data/lib/arachni/ruby/array.rb +1 -1
  386. data/lib/arachni/ruby/hash.rb +1 -1
  387. data/lib/arachni/ruby/io.rb +1 -1
  388. data/lib/arachni/ruby/object.rb +1 -1
  389. data/lib/arachni/ruby/set.rb +1 -1
  390. data/lib/arachni/ruby/string.rb +1 -1
  391. data/lib/arachni/ruby/webrick.rb +1 -1
  392. data/lib/arachni/ruby/webrick/cookie.rb +1 -1
  393. data/lib/arachni/ruby/webrick/httprequest.rb +1 -1
  394. data/lib/arachni/scope.rb +1 -1
  395. data/lib/arachni/selenium/webdriver/remote/http/typhoeus.rb +19 -2
  396. data/lib/arachni/session.rb +8 -3
  397. data/lib/arachni/snapshot.rb +1 -1
  398. data/lib/arachni/state.rb +1 -1
  399. data/lib/arachni/state/audit.rb +1 -1
  400. data/lib/arachni/state/element_filter.rb +12 -20
  401. data/lib/arachni/state/framework.rb +1 -1
  402. data/lib/arachni/state/framework/rpc.rb +1 -1
  403. data/lib/arachni/state/http.rb +1 -1
  404. data/lib/arachni/state/options.rb +1 -1
  405. data/lib/arachni/state/plugins.rb +1 -1
  406. data/lib/arachni/support.rb +1 -1
  407. data/lib/arachni/support/buffer.rb +1 -1
  408. data/lib/arachni/support/buffer/autoflush.rb +1 -1
  409. data/lib/arachni/support/buffer/base.rb +1 -1
  410. data/lib/arachni/support/cache.rb +1 -1
  411. data/lib/arachni/support/cache/base.rb +1 -1
  412. data/lib/arachni/support/cache/least_cost_replacement.rb +1 -1
  413. data/lib/arachni/support/cache/least_recently_used.rb +1 -1
  414. data/lib/arachni/support/cache/preference.rb +1 -1
  415. data/lib/arachni/support/cache/random_replacement.rb +1 -1
  416. data/lib/arachni/support/crypto.rb +1 -1
  417. data/lib/arachni/support/crypto/rsa_aes_cbc.rb +1 -1
  418. data/lib/arachni/support/database.rb +1 -1
  419. data/lib/arachni/support/database/base.rb +1 -1
  420. data/lib/arachni/support/database/hash.rb +1 -1
  421. data/lib/arachni/support/database/queue.rb +1 -1
  422. data/lib/arachni/support/lookup.rb +1 -1
  423. data/lib/arachni/support/lookup/base.rb +1 -1
  424. data/lib/arachni/support/lookup/hash_set.rb +1 -1
  425. data/lib/arachni/support/lookup/moolb.rb +1 -1
  426. data/lib/arachni/support/mixins.rb +1 -1
  427. data/lib/arachni/support/mixins/observable.rb +1 -1
  428. data/lib/arachni/support/mixins/terminal.rb +1 -1
  429. data/lib/arachni/support/profiler.rb +1 -1
  430. data/lib/arachni/support/signature.rb +1 -1
  431. data/lib/arachni/trainer.rb +8 -1
  432. data/lib/arachni/ui/foo/output.rb +1 -1
  433. data/lib/arachni/uri.rb +79 -57
  434. data/lib/arachni/uri/scope.rb +17 -6
  435. data/lib/arachni/utilities.rb +8 -3
  436. data/lib/arachni/version.rb +1 -1
  437. data/lib/arachni/watir/element.rb +22 -1
  438. data/lib/version +1 -1
  439. data/spec/arachni/browser/element_locator_spec.rb +38 -1
  440. data/spec/arachni/browser/javascript/dom_monitor_spec.rb +21 -6
  441. data/spec/arachni/browser/javascript/taint_tracer_spec.rb +351 -216
  442. data/spec/arachni/browser/javascript_spec.rb +26 -6
  443. data/spec/arachni/browser_spec.rb +205 -53
  444. data/spec/arachni/check/auditor_spec.rb +36 -12
  445. data/spec/arachni/element/capabilities/analyzable/differential_spec.rb +84 -42
  446. data/spec/arachni/element/capabilities/analyzable/taint_spec.rb +2 -0
  447. data/spec/arachni/element/capabilities/analyzable/timeout_spec.rb +87 -19
  448. data/spec/arachni/element/capabilities/with_scope/scope_spec.rb +9 -0
  449. data/spec/arachni/element/cookie/dom_spec.rb +2 -2
  450. data/spec/arachni/element/cookie_spec.rb +28 -7
  451. data/spec/arachni/element/form/dom_spec.rb +2 -2
  452. data/spec/arachni/element/form_spec.rb +39 -7
  453. data/spec/arachni/element/generic_dom_spec.rb +13 -6
  454. data/spec/arachni/element/header_spec.rb +2 -2
  455. data/spec/arachni/element/json_spec.rb +522 -0
  456. data/spec/arachni/element/link/dom_spec.rb +2 -2
  457. data/spec/arachni/element/link_spec.rb +12 -12
  458. data/spec/arachni/element/link_template/dom_spec.rb +1 -1
  459. data/spec/arachni/element/link_template_spec.rb +13 -13
  460. data/spec/arachni/element/server_spec.rb +50 -8
  461. data/spec/arachni/element/xml_spec.rb +247 -0
  462. data/spec/arachni/framework/parts/audit_spec.rb +13 -6
  463. data/spec/arachni/framework/parts/browser_spec.rb +276 -10
  464. data/spec/arachni/framework/parts/state_spec.rb +20 -2
  465. data/spec/arachni/http/client/dynamic_404_handlers_spec.rb +274 -0
  466. data/spec/arachni/http/client_spec.rb +4 -241
  467. data/spec/arachni/http/proxy_server_spec.rb +8 -0
  468. data/spec/arachni/http/request_spec.rb +129 -1
  469. data/spec/arachni/http/response_spec.rb +20 -0
  470. data/spec/arachni/issue_spec.rb +3 -3
  471. data/spec/arachni/option_groups/audit_spec.rb +32 -0
  472. data/spec/arachni/option_groups/http_spec.rb +70 -4
  473. data/spec/arachni/options_spec.rb +6 -6
  474. data/spec/arachni/page_spec.rb +89 -1
  475. data/spec/arachni/report_spec.rb +17 -0
  476. data/spec/arachni/session_spec.rb +3 -14
  477. data/spec/arachni/trainer_spec.rb +24 -5
  478. data/spec/arachni/uri/scope_spec.rb +97 -7
  479. data/spec/arachni/uri_spec.rb +41 -0
  480. data/spec/arachni/utilities_spec.rb +2 -1
  481. data/spec/components/checks/active/code_injection_spec.rb +47 -7
  482. data/spec/components/checks/active/code_injection_timing_spec.rb +4 -2
  483. data/spec/components/checks/active/file_inclusion_spec.rb +16 -6
  484. data/spec/components/checks/active/ldap_injection_spec.rb +13 -4
  485. data/spec/components/checks/active/no_sql_injection_spec.rb +4 -2
  486. data/spec/components/checks/active/os_cmd_injection_spec.rb +15 -11
  487. data/spec/components/checks/active/os_cmd_injection_timing_spec.rb +4 -2
  488. data/spec/components/checks/active/path_traversal_spec.rb +11 -5
  489. data/spec/components/checks/active/response_splitting_spec.rb +4 -2
  490. data/spec/components/checks/active/rfi_spec.rb +5 -2
  491. data/spec/components/checks/active/source_code_disclosure_spec.rb +6 -4
  492. data/spec/components/checks/active/sql_injection_spec.rb +52 -26
  493. data/spec/components/checks/active/sql_injection_timing_spec.rb +29 -5
  494. data/spec/components/checks/active/unvalidated_redirect_dom_spec.rb +19 -0
  495. data/spec/components/checks/active/unvalidated_redirect_spec.rb +5 -2
  496. data/spec/components/checks/active/xpath_injection_spec.rb +11 -3
  497. data/spec/components/checks/active/xss_dom_script_context_spec.rb +4 -4
  498. data/spec/components/checks/active/xss_script_context_spec.rb +5 -5
  499. data/spec/components/checks/active/xss_tag_spec.rb +1 -1
  500. data/spec/components/checks/active/xxe_spec.rb +19 -0
  501. data/spec/components/checks/passive/grep/hsts_spec.rb +10 -2
  502. data/spec/components/checks/passive/grep/insecure_cors_policy_spec.rb +25 -0
  503. data/spec/components/checks/passive/grep/x_frame_options_spec.rb +25 -0
  504. data/spec/components/checks/passive/insecure_client_access_policy_spec.rb +15 -0
  505. data/spec/components/checks/passive/insecure_cross_domain_policy_access_spec.rb +15 -0
  506. data/spec/components/checks/passive/insecure_cross_domain_policy_headers_spec.rb +15 -0
  507. data/spec/components/plugins/exec_spec.rb +56 -0
  508. data/spec/components/plugins/headers_collector_spec.rb +126 -0
  509. data/spec/components/plugins/vector_collector_spec.rb +55 -0
  510. data/spec/spec_helper.rb +2 -1
  511. data/spec/support/factories/element/form.rb +1 -1
  512. data/spec/support/factories/element/json.rb +5 -0
  513. data/spec/support/factories/element/link.rb +1 -1
  514. data/spec/support/factories/element/link_template.rb +1 -1
  515. data/spec/support/factories/element/xml.rb +5 -0
  516. data/spec/support/factories/page.rb +11 -2
  517. data/spec/support/fixtures/check_with_invalid_platforms/with_invalid_platforms.rb +1 -1
  518. data/spec/support/fixtures/checks/test.rb +1 -1
  519. data/spec/support/fixtures/checks/test2.rb +1 -1
  520. data/spec/support/fixtures/checks/test3.rb +1 -1
  521. data/spec/support/fixtures/fingerprinters/test.rb +1 -1
  522. data/spec/support/fixtures/plugins/bad.rb +1 -1
  523. data/spec/support/fixtures/plugins/defaults/default.rb +1 -1
  524. data/spec/support/fixtures/plugins/distributable.rb +1 -1
  525. data/spec/support/fixtures/plugins/loop.rb +1 -1
  526. data/spec/support/fixtures/plugins/suspendable.rb +1 -1
  527. data/spec/support/fixtures/plugins/wait.rb +1 -1
  528. data/spec/support/fixtures/plugins/with_options.rb +1 -1
  529. data/spec/support/fixtures/plugins_with_priorities/p0.rb +1 -1
  530. data/spec/support/fixtures/plugins_with_priorities/p00.rb +1 -1
  531. data/spec/support/fixtures/plugins_with_priorities/p1.rb +1 -1
  532. data/spec/support/fixtures/plugins_with_priorities/p2.rb +1 -1
  533. data/spec/support/fixtures/plugins_with_priorities/p22.rb +1 -1
  534. data/spec/support/fixtures/plugins_with_priorities/p222.rb +1 -1
  535. data/spec/support/fixtures/plugins_with_priorities/p_nil.rb +1 -1
  536. data/spec/support/fixtures/plugins_with_priorities/p_nil2.rb +1 -1
  537. data/spec/support/fixtures/report.afr +0 -0
  538. data/spec/support/fixtures/reporters/base_spec/plugin_formatters/with_formatters/foobar.rb +1 -1
  539. data/spec/support/fixtures/reporters/base_spec/with_formatters.rb +1 -1
  540. data/spec/support/fixtures/reporters/base_spec/with_outfile.rb +1 -1
  541. data/spec/support/fixtures/reporters/base_spec/without_outfile.rb +1 -1
  542. data/spec/support/fixtures/reporters/manager_spec/afr.rb +1 -1
  543. data/spec/support/fixtures/reporters/manager_spec/foo.rb +1 -1
  544. data/spec/support/fixtures/run_check/body.rb +1 -1
  545. data/spec/support/fixtures/run_check/cookies.rb +1 -1
  546. data/spec/support/fixtures/run_check/empty.rb +1 -1
  547. data/spec/support/fixtures/run_check/flch.rb +1 -1
  548. data/spec/support/fixtures/run_check/forms.rb +1 -1
  549. data/spec/support/fixtures/run_check/headers.rb +1 -1
  550. data/spec/support/fixtures/run_check/links.rb +1 -1
  551. data/spec/support/fixtures/run_check/nil.rb +1 -1
  552. data/spec/support/fixtures/run_check/path.rb +1 -1
  553. data/spec/support/fixtures/run_check/server.rb +1 -1
  554. data/spec/support/fixtures/taint_check/taint.rb +1 -1
  555. data/spec/support/fixtures/wait_check/wait.rb +1 -1
  556. data/spec/support/helpers/framework.rb +1 -1
  557. data/spec/support/helpers/misc.rb +1 -1
  558. data/spec/support/helpers/pages.rb +23 -14
  559. data/spec/support/helpers/paths.rb +1 -1
  560. data/spec/support/helpers/requires.rb +1 -1
  561. data/spec/support/helpers/resets.rb +1 -1
  562. data/spec/support/helpers/web_server.rb +1 -1
  563. data/spec/support/lib/factory.rb +1 -1
  564. data/spec/support/lib/web_server_client.rb +1 -1
  565. data/spec/support/lib/web_server_dispatcher.rb +1 -1
  566. data/spec/support/lib/web_server_manager.rb +1 -1
  567. data/spec/support/servers/arachni/browser.rb +77 -3
  568. data/spec/support/servers/arachni/browser/javascript/angular-1.2.8.js +1 -1
  569. data/spec/support/servers/arachni/browser/javascript/angular-route.js +1 -1
  570. data/spec/support/servers/arachni/browser/javascript/dom_monitor.rb +24 -1
  571. data/spec/support/servers/arachni/browser/javascript/jquery.cookie.js +117 -0
  572. data/spec/support/servers/arachni/browser/javascript/taint_tracer.rb +58 -1
  573. data/spec/support/servers/arachni/element/capabilities/analyzable/timeout.rb +6 -0
  574. data/spec/support/servers/arachni/element/json.rb +5 -0
  575. data/spec/support/servers/arachni/element/xml.rb +5 -0
  576. data/spec/support/servers/arachni/http/client.rb +0 -22
  577. data/spec/support/servers/arachni/http/client/dynamic_404_handler.rb +47 -0
  578. data/spec/support/servers/arachni/trainer.rb +10 -0
  579. data/spec/support/servers/checks/active/code_injection.rb +69 -42
  580. data/spec/support/servers/checks/active/code_injection_timing.rb +115 -0
  581. data/spec/support/servers/checks/active/file_inclusion.rb +117 -2
  582. data/spec/support/servers/checks/active/ldap_injection.rb +114 -0
  583. data/spec/support/servers/checks/active/no_sql_injection.rb +81 -0
  584. data/spec/support/servers/checks/active/os_cmd_injection.rb +116 -0
  585. data/spec/support/servers/checks/active/os_cmd_injection_timing.rb +77 -5
  586. data/spec/support/servers/checks/active/path_traversal.rb +154 -2
  587. data/spec/support/servers/checks/active/response_splitting.rb +117 -0
  588. data/spec/support/servers/checks/active/rfi.rb +117 -0
  589. data/spec/support/servers/checks/active/source_code_disclosure.rb +109 -0
  590. data/spec/support/servers/checks/active/sql_injection.rb +125 -0
  591. data/spec/support/servers/checks/active/sql_injection_timing.rb +114 -0
  592. data/spec/support/servers/checks/active/unvalidated_redirect.rb +117 -1
  593. data/spec/support/servers/checks/active/unvalidated_redirect_dom.rb +115 -0
  594. data/spec/support/servers/checks/active/xpath_injection.rb +117 -0
  595. data/spec/support/servers/checks/active/xss_script_context.rb +16 -32
  596. data/spec/support/servers/checks/active/xss_tag.rb +12 -12
  597. data/spec/support/servers/checks/active/xxe.rb +85 -0
  598. data/spec/support/servers/checks/passive/grep/insecure_cors_policy.rb +8 -0
  599. data/spec/support/servers/checks/passive/grep/x_frame_options.rb +9 -0
  600. data/spec/support/servers/checks/passive/insecure_client_access_policy.rb +9 -0
  601. data/spec/support/servers/checks/passive/insecure_cross_domain_policy_access.rb +13 -0
  602. data/spec/support/servers/checks/passive/insecure_cross_domain_policy_headers.rb +13 -0
  603. data/spec/support/servers/plugins/headers_collector.rb +16 -0
  604. data/spec/support/servers/plugins/vector_collector.rb +13 -0
  605. data/spec/support/shared/check.rb +6 -1
  606. data/spec/support/shared/element/base.rb +16 -9
  607. data/spec/support/shared/element/capabilities/auditable.rb +22 -15
  608. data/spec/support/shared/element/capabilities/auditable/dom.rb +7 -14
  609. data/spec/support/shared/element/capabilities/inputtable.rb +46 -61
  610. data/spec/support/shared/element/capabilities/mutable.rb +159 -64
  611. data/spec/support/shared/element/capabilities/with_dom.rb +52 -3
  612. data/spec/support/shared/element/capabilities/with_node.rb +2 -44
  613. data/spec/support/shared/element/capabilities/with_scope.rb +1 -1
  614. data/spec/support/shared/element/capabilities/with_source.rb +55 -0
  615. data/ui/cli/framework.rb +9 -9
  616. data/ui/cli/framework/option_parser.rb +75 -3
  617. data/ui/cli/option_parser.rb +1 -1
  618. data/ui/cli/output.rb +1 -1
  619. data/ui/cli/reporter.rb +1 -1
  620. data/ui/cli/reporter/option_parser.rb +1 -1
  621. data/ui/cli/restored_framework.rb +1 -1
  622. data/ui/cli/restored_framework/option_parser.rb +1 -1
  623. data/ui/cli/rpc/client/dispatcher_monitor.rb +1 -1
  624. data/ui/cli/rpc/client/dispatcher_monitor/option_parser.rb +1 -1
  625. data/ui/cli/rpc/client/instance.rb +5 -4
  626. data/ui/cli/rpc/client/local.rb +1 -1
  627. data/ui/cli/rpc/client/local/option_parser.rb +1 -1
  628. data/ui/cli/rpc/client/remote.rb +1 -1
  629. data/ui/cli/rpc/client/remote/option_parser.rb +1 -1
  630. data/ui/cli/rpc/server/dispatcher.rb +1 -1
  631. data/ui/cli/rpc/server/dispatcher/option_parser.rb +1 -1
  632. data/ui/cli/utilities.rb +4 -1
  633. metadata +129 -19
  634. data/lib/arachni/nokogiri/xml/node.rb +0 -42
@@ -1,5 +1,5 @@
1
1
  =begin
2
- Copyright 2010-2014 Tasos Laskos <tasos.laskos@arachni-scanner.com>
2
+ Copyright 2010-2015 Tasos Laskos <tasos.laskos@arachni-scanner.com>
3
3
 
4
4
  This file is part of the Arachni Framework project and is subject to
5
5
  redistribution and commercial restrictions. Please see the Arachni Framework
@@ -0,0 +1,15 @@
1
+ # Sets default locations for writing files.
2
+ #
3
+ # * '~' will be expanded to $HOME.
4
+ # * Directories will be created if they don't already exist.
5
+
6
+ cli:
7
+ # Default directory for AFR reports generated by CLI interfaces, either
8
+ # local or RPC clients.
9
+ report_path:
10
+ framework:
11
+ # Error and RPC logs.
12
+ logs:
13
+ # Default directory for scan snapshots generated either by the CLI
14
+ # or by RPC Instances.
15
+ snapshots:
@@ -1,5 +1,5 @@
1
1
  =begin
2
- Copyright 2010-2014 Tasos Laskos <tasos.laskos@arachni-scanner.com>
2
+ Copyright 2010-2015 Tasos Laskos <tasos.laskos@arachni-scanner.com>
3
3
 
4
4
  This file is part of the Arachni Framework project and is subject to
5
5
  redistribution and commercial restrictions. Please see the Arachni Framework
@@ -1,5 +1,5 @@
1
1
  =begin
2
- Copyright 2010-2014 Tasos Laskos <tasos.laskos@arachni-scanner.com>
2
+ Copyright 2010-2015 Tasos Laskos <tasos.laskos@arachni-scanner.com>
3
3
 
4
4
  This file is part of the Arachni Framework project and is subject to
5
5
  redistribution and commercial restrictions. Please see the Arachni Framework
@@ -1,5 +1,5 @@
1
1
  =begin
2
- Copyright 2010-2014 Tasos Laskos <tasos.laskos@arachni-scanner.com>
2
+ Copyright 2010-2015 Tasos Laskos <tasos.laskos@arachni-scanner.com>
3
3
 
4
4
  This file is part of the Arachni Framework project and is subject to
5
5
  redistribution and commercial restrictions. Please see the Arachni Framework
@@ -190,6 +190,17 @@ class Browser
190
190
  ensure_open_window
191
191
  end
192
192
 
193
+ def clear_buffers
194
+ synchronize do
195
+ @preloads.clear
196
+ @cache.clear
197
+ @captured_pages.clear
198
+ @page_snapshots.clear
199
+ @page_snapshots_with_sinks.clear
200
+ @window_responses.clear
201
+ end
202
+ end
203
+
193
204
  # @return [String]
194
205
  # Prefixes each source line with a number.
195
206
  def source_with_line_numbers
@@ -337,7 +348,12 @@ class Browser
337
348
  end
338
349
 
339
350
  def shutdown
340
- watir.close if browser_alive?
351
+ begin
352
+ watir.close if browser_alive?
353
+ rescue Selenium::WebDriver::Error::WebDriverError,
354
+ Watir::Exception::Error
355
+ end
356
+
341
357
  kill_process
342
358
  @proxy.shutdown
343
359
  end
@@ -397,7 +413,7 @@ class Browser
397
413
  href = attributes['href'].to_s
398
414
 
399
415
  if !href.empty?
400
- if href.start_with?( 'javascript:' )
416
+ if href.downcase.start_with?( 'javascript:' )
401
417
  events << [ :click, href ]
402
418
  else
403
419
  next if skip_path?( to_absolute( href, current_url ) )
@@ -413,7 +429,7 @@ class Browser
413
429
  action = attributes['action'].to_s
414
430
 
415
431
  if !action.empty?
416
- if action.start_with?( 'javascript:' )
432
+ if action.downcase.start_with?( 'javascript:' )
417
433
  events << [ :submit, action ]
418
434
  else
419
435
  next if skip_path?( to_absolute( action, current_url ) )
@@ -421,9 +437,13 @@ class Browser
421
437
  end
422
438
  end
423
439
 
424
- state = "#{tag_name}#{attributes}#{events}"
425
- next if events.empty? || (mark_state && skip_state?( state ))
426
- skip_state state if mark_state
440
+ next if events.empty?
441
+
442
+ if mark_state
443
+ state = "#{tag_name}#{attributes}#{events}"
444
+ next if skip_state?( state )
445
+ skip_state state
446
+ end
427
447
 
428
448
  yield ElementLocator.new( tag_name: tag_name, attributes: attributes ),
429
449
  events
@@ -445,33 +465,38 @@ class Browser
445
465
  javascript.dom_elements_with_events.each do |element|
446
466
  tag_name = element['tag_name']
447
467
  attributes = element['attributes']
448
- events = element['events']
468
+ events = element['events'] +
469
+ Javascript.select_event_attributes( attributes ).to_a
470
+ element_id = attributes['id'].to_s
449
471
 
450
472
  case tag_name
451
473
  when 'a'
452
- href = attributes['href'].to_s
474
+ href = attributes['href'].to_s
475
+ element_id << href
453
476
 
454
477
  if !href.empty?
455
- if href.start_with?( 'javascript:' )
478
+ if href.downcase.start_with?( 'javascript:' )
456
479
  events << [ :click, href ]
457
480
  else
458
481
  absolute = to_absolute( href, current_url )
459
- if !skip_path?( absolute )
460
- events << [ :click, absolute ]
461
- end
482
+ next if skip_path?( absolute )
483
+
484
+ events << [ :click, href ]
462
485
  end
463
486
  else
464
487
  events << [ :click, current_url ]
465
488
  end
466
489
 
467
490
  when 'input', 'textarea', 'select'
468
- events << [ tag_name.to_sym ]
491
+ events << [ tag_name.to_sym ]
492
+ element_id << attributes['name'].to_s
469
493
 
470
494
  when 'form'
471
- action = attributes['action'].to_s
495
+ action = attributes['action'].to_s
496
+ element_id << "#{action}#{attributes['name']}"
472
497
 
473
498
  if !action.empty?
474
- if action.start_with?( 'javascript:' )
499
+ if action.downcase.start_with?( 'javascript:' )
475
500
  events << [ :submit, action ]
476
501
  else
477
502
  absolute = to_absolute( action, current_url )
@@ -485,10 +510,11 @@ class Browser
485
510
  end
486
511
 
487
512
  next if events.empty?
488
- id << "#{tag_name}#{attributes}#{events}".hash
513
+
514
+ id << "#{tag_name}:#{element_id}:#{events}"
489
515
  end
490
516
 
491
- id.sort.to_s
517
+ id.uniq.sort.to_s
492
518
  end
493
519
 
494
520
  # Triggers all events on all elements (**once**) and captures
@@ -571,10 +597,11 @@ class Browser
571
597
 
572
598
  begin
573
599
  element = element.locate( self )
574
- rescue Selenium::WebDriver::Error::UnknownError,
575
- Watir::Exception::UnknownObjectException => e
600
+ rescue Selenium::WebDriver::Error::WebDriverError,
601
+ Watir::Exception::Error => e
576
602
 
577
- print_debug "Element '#{locator}' could not be located for triggering '#{event}'."
603
+ print_debug "Element '#{element.inspect}' could not be " <<
604
+ "located for triggering '#{event}'."
578
605
  print_debug
579
606
  print_debug_exception e
580
607
  return
@@ -588,12 +615,13 @@ class Browser
588
615
  sleep 0.1 while !element.exists?
589
616
  end
590
617
  rescue Timeout::Error
591
- print_debug_level_2 "#{locator} did not appear in #{ELEMENT_APPEARANCE_TIMEOUT}."
618
+ print_debug_level_2 "#{element.inspect} did not appear in " <<
619
+ "#{ELEMENT_APPEARANCE_TIMEOUT}."
592
620
  return
593
621
  end
594
622
 
595
623
  if !element.visible?
596
- print_debug_level_2 "#{locator} is not visible, skipping..."
624
+ print_debug_level_2 "#{element.inspect} is not visible, skipping..."
597
625
  return
598
626
  end
599
627
 
@@ -606,7 +634,7 @@ class Browser
606
634
  locator = ElementLocator.from_html( opening_tag )
607
635
  end
608
636
 
609
- print_debug_level_2 "#{__method__}: #{event} (#{options}) #{locator}"
637
+ print_debug_level_2 "#{__method__} [start]: #{event} (#{options}) #{locator}"
610
638
 
611
639
  tag_name = tag_name.to_sym
612
640
 
@@ -621,15 +649,14 @@ class Browser
621
649
  fill_in_form_inputs( element, options[:inputs] )
622
650
 
623
651
  if event == :submit
652
+ element.to_subtype.submit
624
653
  had_special_trigger = true
625
- element.submit
626
654
  end
627
-
628
655
  elsif tag_name == :input && event == :click &&
629
656
  element.attribute_value(:type) == 'image'
630
657
 
658
+ element.to_subtype.click
631
659
  had_special_trigger = true
632
- watir.button( type: 'image' ).click
633
660
 
634
661
  elsif [:keyup, :keypress, :keydown, :change, :input, :focus, :blur, :select].include? event
635
662
 
@@ -640,11 +667,16 @@ class Browser
640
667
  end
641
668
 
642
669
  element.fire_event( event ) if !had_special_trigger
670
+
671
+ print_debug_level_2 "#{__method__} [waiting for requests]: #{event} (#{options}) #{locator}"
643
672
  wait_for_pending_requests
673
+ print_debug_level_2 "#{__method__} [done waiting for requests]: #{event} (#{options}) #{locator}"
674
+
675
+ # puts source_with_line_numbers
676
+ print_debug_level_2 "#{__method__} [done]: #{event} (#{options}) #{locator}"
644
677
  end
645
- rescue Selenium::WebDriver::Error::InvalidElementStateError,
646
- Selenium::WebDriver::Error::UnknownError,
647
- Watir::Exception::UnknownObjectException => e
678
+ rescue Selenium::WebDriver::Error::WebDriverError,
679
+ Watir::Exception::Error => e
648
680
 
649
681
  sleep 0.1
650
682
 
@@ -714,11 +746,20 @@ class Browser
714
746
  # @return [Page]
715
747
  # Converts the current browser window to a {Page page}.
716
748
  def to_page
717
- return if !(r = response)
718
-
719
- page = r.to_page
720
- page.body = source
749
+ if !(r = response)
750
+ return Page.from_data(
751
+ dom: {
752
+ url: watir.url
753
+ },
754
+ response: {
755
+ code: 0,
756
+ url: url
757
+ }
758
+ )
759
+ end
721
760
 
761
+ page = r.to_page
762
+ page.body = source
722
763
  page.dom.url = watir.url
723
764
  page.dom.digest = @javascript.dom_digest
724
765
  page.dom.execution_flow_sinks = @javascript.execution_flow_sinks
@@ -726,6 +767,38 @@ class Browser
726
767
  page.dom.transitions = @transitions.dup
727
768
  page.dom.skip_states = skip_states.dup
728
769
 
770
+ # Go through auditable DOM forms and cookies and remove the DOM from
771
+ # them if no events are associated with it.
772
+ #
773
+ # This can save **A LOT** of time during the audit.
774
+ if Options.audit.form_doms? && @javascript.supported?
775
+ page.forms.each do |form|
776
+ next if !form.node || !form.dom
777
+
778
+ action = form.node['action'].to_s
779
+ form.dom.browser = self
780
+
781
+ next if action.downcase.start_with?( 'javascript:' ) ||
782
+ form.dom.locate.events.any?
783
+
784
+ form.skip_dom = true
785
+ end
786
+
787
+ page.update_metadata
788
+ end
789
+
790
+ if Options.audit.cookie_doms? && @javascript.supported?
791
+ sinks = @javascript.taint_tracer.data_flow_sinks
792
+ page.cookies.each do |cookie|
793
+ next if sinks.include?( cookie.name ) ||
794
+ sinks.include?( cookie.value )
795
+
796
+ cookie.skip_dom = true
797
+ end
798
+
799
+ page.update_metadata
800
+ end
801
+
729
802
  page
730
803
  end
731
804
 
@@ -750,7 +823,7 @@ class Browser
750
823
 
751
824
  capture_snapshot_with_sink( page )
752
825
 
753
- unique_id = self.snapshot_id
826
+ unique_id = self.snapshot_id
754
827
  next if skip_state? unique_id
755
828
  skip_state unique_id
756
829
 
@@ -808,7 +881,7 @@ class Browser
808
881
  # this out ourselves, by checking for JS visibility.
809
882
  javascript.run( 'return document.cookie' )
810
883
  # We may not have a page.
811
- rescue Selenium::WebDriver::Error::UnknownError
884
+ rescue Selenium::WebDriver::Error::WebDriverError
812
885
  ''
813
886
  end
814
887
 
@@ -887,6 +960,14 @@ class Browser
887
960
  )
888
961
  end
889
962
 
963
+ def inspect
964
+ s = "#<#{self.class} "
965
+ s << "pid=#{@pid} "
966
+ s << "last-url=#{@last_url.inspect} "
967
+ s << "transitions=#{@transitions.size}"
968
+ s << '>'
969
+ end
970
+
890
971
  private
891
972
 
892
973
  def fill_in_form_inputs( form, inputs = nil )
@@ -895,11 +976,10 @@ class Browser
895
976
  value = inputs ? inputs[name_or_id] : value_for( input )
896
977
 
897
978
  begin
898
- input.set( value.to_s )
979
+ input.set( value.to_s.recode )
899
980
  # Disabled inputs and such...
900
- rescue Watir::Exception::ObjectDisabledException,
901
- Watir::Exception::ObjectReadOnlyException,
902
- Selenium::WebDriver::Error::InvalidElementStateError => e
981
+ rescue Selenium::WebDriver::Error::WebDriverError,
982
+ Watir::Exception::Error => e
903
983
  print_debug_level_2 "Could not fill in form input '#{name_or_id}'" <<
904
984
  " because: #{e} [#{e.class}"
905
985
  end
@@ -910,12 +990,10 @@ class Browser
910
990
  value = inputs ? inputs[name_or_id] : value_for( input )
911
991
 
912
992
  begin
913
- input.select_value( value.to_s )
993
+ input.select_value( value.to_s.recode )
914
994
  # Disabled inputs and such...
915
- rescue Watir::Exception::ObjectDisabledException,
916
- Watir::Exception::ObjectReadOnlyException,
917
- Watir::Exception::NoValueFoundException,
918
- Selenium::WebDriver::Error::InvalidElementStateError => e
995
+ rescue Selenium::WebDriver::Error::WebDriverError,
996
+ Watir::Exception::Error => e
919
997
  print_debug_level_2 "Could not fill in form select '#{name_or_id}'" <<
920
998
  " because: #{e} [#{e.class}"
921
999
  end
@@ -995,8 +1073,10 @@ class Browser
995
1073
  "--webdriver=#{port}",
996
1074
  "--proxy=http://#{@proxy.address}/",
997
1075
  '--ignore-ssl-errors=true',
1076
+ '--disk-cache=true',
998
1077
  "--debug=#{!!debug?}"
999
1078
  )
1079
+ # @process.leader = true
1000
1080
  @process.detach = true
1001
1081
 
1002
1082
  @process.io.stdout = Tempfile.new( 'phantomjs-out' )
@@ -1058,13 +1138,18 @@ class Browser
1058
1138
  end
1059
1139
 
1060
1140
  def kill_process
1061
- if browser_alive?
1062
- @process.stop
1063
- @process.io.close rescue nil
1141
+ begin
1142
+ if @process && @process.alive?
1143
+ @process.stop
1144
+ @process.io.close rescue nil
1145
+ end
1146
+ rescue Errno::ECHILD
1147
+ false
1064
1148
  end
1065
1149
 
1066
1150
  @process = nil
1067
1151
  @watir = nil
1152
+ @selenium = nil
1068
1153
  @pid = nil
1069
1154
  @browser_url = nil
1070
1155
  end
@@ -1198,6 +1283,8 @@ class Browser
1198
1283
  end
1199
1284
 
1200
1285
  def request_handler( request, response )
1286
+ request.performer = self
1287
+
1201
1288
  return if request.headers['X-Arachni-Browser-Auth'] != auth_token
1202
1289
  request.headers.delete( 'X-Arachni-Browser-Auth' )
1203
1290
 
@@ -1215,10 +1302,16 @@ class Browser
1215
1302
  # preloaded or cached response for it.
1216
1303
  return if from_preloads( request, response ) || from_cache( request, response )
1217
1304
 
1218
- # Capture the request as elements of pages -- let's us grab AJAX and
1219
- # other browser requests and convert them into elements we can analyze
1220
- # and audit.
1221
- capture( request )
1305
+ begin
1306
+ # Capture the request as elements of pages -- let's us grab AJAX and
1307
+ # other browser requests and convert them into elements we can analyze
1308
+ # and audit.
1309
+ capture( request )
1310
+ rescue => e
1311
+ print_debug "Could not capture: #{request.url}"
1312
+ print_debug request.body.to_s
1313
+ print_debug_exception e
1314
+ end
1222
1315
 
1223
1316
  request.headers['user-agent'] = Options.http.user_agent
1224
1317
 
@@ -1234,10 +1327,15 @@ class Browser
1234
1327
  transition.complete
1235
1328
  end
1236
1329
 
1330
+ # No-matter the scope, don't store resources for external domains.
1331
+ return if !response.scope.in_domain?
1332
+
1237
1333
  return if enforce_scope? && response.scope.out?
1238
1334
 
1239
1335
  intercept response
1240
1336
  save_response response
1337
+
1338
+ nil
1241
1339
  end
1242
1340
 
1243
1341
  def intercept( response )
@@ -1247,12 +1345,37 @@ class Browser
1247
1345
 
1248
1346
  def intercept?( response )
1249
1347
  return false if response.body.empty?
1250
- return false if !response.headers.content_type.to_s.start_with?( 'text/html' )
1251
1348
 
1349
+ # We only care about HTML.
1350
+ return false if !response.headers.content_type.to_s.downcase.start_with?( 'text/html' )
1351
+
1352
+ # Let's check that the response at least looks like it contains HTML
1353
+ # code of interest.
1252
1354
  body = response.body.downcase
1253
- HTML_IDENTIFIERS.each { |tag| return true if body.include? tag.downcase }
1355
+ return false if !HTML_IDENTIFIERS.find { |tag| body.include? tag.downcase }
1254
1356
 
1255
- false
1357
+ # The last check isn't fool-proof, so don't do it when loading the page
1358
+ # for the first time, but only when the page loads stuff via AJAX and whatnot.
1359
+ #
1360
+ # Well, we can be pretty sure that the root page will be HTML anyways.
1361
+ return true if @last_url == response.url
1362
+
1363
+ # Finally, verify that we're really working with markup (hopefully HTML)
1364
+ # and that the previous checks weren't just flukes matching some other
1365
+ # kind of document.
1366
+ #
1367
+ # For example, it may have been JSON with the wrong content-type that
1368
+ # includes HTML -- it happens.
1369
+ begin
1370
+ return false if Nokogiri::XML( response.body ).children.empty?
1371
+ rescue => e
1372
+ print_debug "Javascript injection failed for: #{response.url}"
1373
+ print_debug "\n#{response.body}"
1374
+ print_debug_exception e
1375
+ return false
1376
+ end
1377
+
1378
+ true
1256
1379
  end
1257
1380
 
1258
1381
  def ignore_request?( request )
@@ -1260,19 +1383,36 @@ class Browser
1260
1383
 
1261
1384
  # Only allow CSS and JS resources to be loaded from out-of-scope domains.
1262
1385
  !['css', 'js'].include?( request.parsed_url.resource_extension ) &&
1263
- request.scope.out? || request.scope.redundant?
1386
+ (request.scope.out? || request.scope.redundant?)
1264
1387
  end
1265
1388
 
1266
1389
  def capture( request )
1267
1390
  return if !@last_url || !capture?
1268
1391
 
1392
+ elements = {
1393
+ forms: [],
1394
+ jsons: [],
1395
+ xmls: []
1396
+ }
1397
+
1398
+ found_element = false
1399
+
1400
+ if (json = JSON.from_request( @last_url, request ))
1401
+ elements[:jsons] << json
1402
+ found_element = true
1403
+ end
1404
+
1405
+ if !found_element && (xml = XML.from_request( @last_url, request ))
1406
+ elements[:xmls] << xml
1407
+ found_element = true
1408
+ end
1409
+
1269
1410
  case request.method
1270
1411
  when :get
1271
- inputs = request.parsed_url.query_parameters
1412
+ inputs = request.parsed_url.query_parameters
1272
1413
  return if inputs.empty?
1273
1414
 
1274
- # Make this a Link.
1275
- form = Form.new(
1415
+ elements[:forms] << Form.new(
1276
1416
  url: @last_url,
1277
1417
  action: request.url,
1278
1418
  method: request.method,
@@ -1280,32 +1420,33 @@ class Browser
1280
1420
  )
1281
1421
 
1282
1422
  when :post
1283
- inputs = request.body_parameters
1284
- return if inputs.empty?
1285
-
1286
- form = Form.new(
1287
- url: @last_url,
1288
- action: request.url,
1289
- method: request.method,
1290
- inputs: inputs
1291
- )
1423
+ if !found_element && (inputs = request.body_parameters).any?
1424
+ elements[:forms] << Form.new(
1425
+ url: @last_url,
1426
+ action: request.url,
1427
+ method: request.method,
1428
+ inputs: inputs
1429
+ )
1430
+ end
1292
1431
 
1293
1432
  else
1294
1433
  return
1295
1434
  end
1296
1435
 
1297
- # Don't bother if the system in general has already seen the vector.
1298
- return if ElementFilter.include?( form )
1436
+ el = elements.values.flatten
1437
+
1438
+ # Don't bother if the system in general has already seen the vectors.
1439
+ return if el.empty? || !el.find { |e| !ElementFilter.include?( e ) }
1299
1440
 
1300
1441
  begin
1301
- return if skip_state?( form.id )
1302
- skip_state form.id
1442
+ return if !el.find { |e| !skip_state?( e ) }
1443
+ el.each { |e| skip_state e.id }
1303
1444
  # This could be an orphaned HTTP request, without a job, if running in
1304
1445
  # BrowserCluster::Worker.
1305
1446
  rescue NoMethodError
1306
1447
  end
1307
1448
 
1308
- page = Page.from_data( url: request.url, forms: [form] )
1449
+ page = Page.from_data( elements.merge( url: request.url ) )
1309
1450
  page.response.request = request
1310
1451
  page.dom.push_transition Page::DOM::Transition.new( request.url, :request )
1311
1452
 
@@ -1342,10 +1483,12 @@ class Browser
1342
1483
  end
1343
1484
 
1344
1485
  def save_response( response )
1345
- notify_on_response response
1346
- return response if !response.text?
1486
+ synchronize do
1487
+ notify_on_response response
1488
+ return response if !response.text?
1347
1489
 
1348
- @window_responses[response.url] = response
1490
+ @window_responses[response.url] = response
1491
+ end
1349
1492
  end
1350
1493
 
1351
1494
  def get_response( url )
@@ -1354,7 +1497,8 @@ class Browser
1354
1497
  # everything after ';' by treating it as a path parameter.
1355
1498
  # Rightly so...but we need to bypass it when auditing LinkTemplate
1356
1499
  # elements.
1357
- @window_responses[normalize_watir_url( url )] ||
1500
+ @window_responses[url] ||
1501
+ @window_responses[normalize_watir_url( url )] ||
1358
1502
  @window_responses[normalize_url( url )]
1359
1503
  end
1360
1504
  end