arachni 1.1 → 1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (287) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +159 -0
  3. data/LICENSE.md +126 -196
  4. data/README.md +32 -24
  5. data/arachni.gemspec +7 -7
  6. data/components/checks/active/code_injection_timing.rb +3 -3
  7. data/components/checks/active/csrf.rb +2 -2
  8. data/components/checks/active/file_inclusion.rb +6 -7
  9. data/components/checks/active/os_cmd_injection.rb +3 -3
  10. data/components/checks/active/path_traversal.rb +7 -7
  11. data/components/checks/active/response_splitting.rb +9 -4
  12. data/components/checks/active/session_fixation.rb +7 -3
  13. data/components/checks/active/source_code_disclosure.rb +5 -5
  14. data/components/checks/active/unvalidated_redirect.rb +12 -3
  15. data/components/checks/active/unvalidated_redirect_dom.rb +3 -3
  16. data/components/checks/active/xss.rb +23 -10
  17. data/components/checks/active/xss_dom_inputs.rb +113 -11
  18. data/components/checks/active/xxe.rb +3 -3
  19. data/components/checks/passive/backdoors.rb +6 -5
  20. data/components/checks/passive/backup_directories.rb +6 -6
  21. data/components/checks/passive/backup_files.rb +6 -6
  22. data/components/checks/passive/common_admin_interfaces.rb +58 -0
  23. data/components/checks/passive/common_admin_interfaces/admin-panels.txt +49 -0
  24. data/components/checks/passive/common_directories/directories.txt +0 -16
  25. data/components/checks/passive/common_files.rb +6 -5
  26. data/components/checks/passive/common_files/filenames.txt +0 -2
  27. data/components/checks/passive/directory_listing.rb +6 -6
  28. data/components/checks/passive/grep/cookie_set_for_parent_domain.rb +3 -3
  29. data/components/checks/passive/grep/hsts.rb +6 -3
  30. data/components/checks/passive/grep/http_only_cookies.rb +3 -3
  31. data/components/checks/passive/grep/insecure_cookies.rb +2 -2
  32. data/components/checks/passive/grep/insecure_cors_policy.rb +6 -4
  33. data/components/checks/passive/grep/x_frame_options.rb +6 -4
  34. data/components/checks/passive/htaccess_limit.rb +6 -2
  35. data/components/checks/passive/http_put.rb +8 -4
  36. data/components/checks/passive/interesting_responses.rb +3 -2
  37. data/components/checks/passive/localstart_asp.rb +6 -2
  38. data/components/checks/passive/origin_spoof_access_restriction_bypass.rb +5 -1
  39. data/components/checks/passive/xst.rb +6 -2
  40. data/components/fingerprinters/frameworks/aspx_mvc.rb +43 -0
  41. data/components/fingerprinters/frameworks/cakephp.rb +28 -0
  42. data/components/fingerprinters/frameworks/cherrypy.rb +31 -0
  43. data/components/fingerprinters/frameworks/django.rb +33 -0
  44. data/components/fingerprinters/frameworks/jsf.rb +30 -0
  45. data/components/fingerprinters/frameworks/rack.rb +5 -7
  46. data/components/fingerprinters/frameworks/rails.rb +43 -0
  47. data/components/fingerprinters/languages/aspx.rb +11 -11
  48. data/components/fingerprinters/languages/{jsp.rb → java.rb} +11 -7
  49. data/components/fingerprinters/languages/php.rb +6 -6
  50. data/components/fingerprinters/languages/python.rb +14 -6
  51. data/components/fingerprinters/languages/ruby.rb +3 -5
  52. data/components/fingerprinters/servers/apache.rb +5 -4
  53. data/components/fingerprinters/servers/gunicorn.rb +33 -0
  54. data/components/fingerprinters/servers/jetty.rb +1 -1
  55. data/components/fingerprinters/servers/tomcat.rb +11 -4
  56. data/components/path_extractors/anchors.rb +5 -12
  57. data/components/path_extractors/areas.rb +5 -13
  58. data/components/path_extractors/comments.rb +5 -3
  59. data/components/path_extractors/data_url.rb +21 -0
  60. data/components/path_extractors/forms.rb +5 -13
  61. data/components/path_extractors/frames.rb +6 -13
  62. data/components/path_extractors/generic.rb +3 -12
  63. data/components/path_extractors/links.rb +5 -13
  64. data/components/path_extractors/meta_refresh.rb +5 -13
  65. data/components/path_extractors/scripts.rb +8 -14
  66. data/components/plugins/autologin.rb +17 -5
  67. data/components/plugins/defaults/meta/remedies/discovery.rb +11 -29
  68. data/components/plugins/login_script.rb +40 -10
  69. data/components/plugins/metrics.rb +235 -0
  70. data/components/plugins/proxy.rb +21 -4
  71. data/components/plugins/proxy/panel/page_accordion.html.erb +34 -2
  72. data/components/plugins/restrict_to_dom_state.rb +70 -0
  73. data/components/plugins/vector_feed.rb +38 -9
  74. data/components/reporters/plugin_formatters/html/metrics.rb +290 -0
  75. data/components/reporters/plugin_formatters/stdout/metrics.rb +80 -0
  76. data/components/reporters/plugin_formatters/xml/metrics.rb +29 -0
  77. data/components/reporters/stdout.rb +4 -2
  78. data/components/reporters/xml.rb +4 -4
  79. data/components/reporters/xml/schema.xsd +95 -0
  80. data/lib/arachni.rb +2 -0
  81. data/lib/arachni/browser.rb +132 -77
  82. data/lib/arachni/browser/javascript.rb +173 -45
  83. data/lib/arachni/browser/javascript/scripts/dom_monitor.js +81 -6
  84. data/lib/arachni/browser/javascript/scripts/taint_tracer.js +31 -3
  85. data/lib/arachni/browser_cluster.rb +41 -15
  86. data/lib/arachni/browser_cluster/job.rb +4 -0
  87. data/lib/arachni/browser_cluster/jobs/resource_exploration.rb +0 -9
  88. data/lib/arachni/browser_cluster/worker.rb +8 -5
  89. data/lib/arachni/check/auditor.rb +20 -8
  90. data/lib/arachni/check/base.rb +38 -6
  91. data/lib/arachni/element/base.rb +18 -1
  92. data/lib/arachni/element/capabilities/analyzable/differential.rb +0 -1
  93. data/lib/arachni/element/capabilities/analyzable/taint.rb +40 -10
  94. data/lib/arachni/element/capabilities/analyzable/timeout.rb +27 -23
  95. data/lib/arachni/element/capabilities/auditable/dom.rb +22 -0
  96. data/lib/arachni/element/capabilities/inputtable.rb +6 -2
  97. data/lib/arachni/element/capabilities/submittable.rb +1 -1
  98. data/lib/arachni/element/cookie.rb +37 -23
  99. data/lib/arachni/element/cookie/capabilities/mutable.rb +6 -6
  100. data/lib/arachni/element/cookie/dom.rb +0 -8
  101. data/lib/arachni/element/form.rb +28 -14
  102. data/lib/arachni/element/form/capabilities/auditable.rb +2 -2
  103. data/lib/arachni/element/form/capabilities/mutable.rb +5 -5
  104. data/lib/arachni/element/form/dom.rb +0 -8
  105. data/lib/arachni/element/generic_dom.rb +1 -1
  106. data/lib/arachni/element/json.rb +2 -1
  107. data/lib/arachni/element/json/capabilities/inputtable.rb +6 -6
  108. data/lib/arachni/element/json/capabilities/mutable.rb +1 -1
  109. data/lib/arachni/element/link.rb +13 -16
  110. data/lib/arachni/element/link/dom.rb +1 -14
  111. data/lib/arachni/element/link_template.rb +3 -2
  112. data/lib/arachni/element/link_template/dom.rb +0 -16
  113. data/lib/arachni/element/server.rb +51 -9
  114. data/lib/arachni/element/xml.rb +1 -0
  115. data/lib/arachni/ethon/easy.rb +4 -1
  116. data/lib/arachni/framework/parts/audit.rb +26 -77
  117. data/lib/arachni/framework/parts/browser.rb +50 -55
  118. data/lib/arachni/framework/parts/check.rb +4 -3
  119. data/lib/arachni/framework/parts/data.rb +41 -6
  120. data/lib/arachni/framework/parts/state.rb +16 -7
  121. data/lib/arachni/http/client.rb +66 -38
  122. data/lib/arachni/http/client/dynamic_404_handler.rb +46 -14
  123. data/lib/arachni/http/headers.rb +22 -10
  124. data/lib/arachni/http/proxy_server.rb +67 -22
  125. data/lib/arachni/http/proxy_server/ssl-interceptor-cacert.pem +34 -0
  126. data/lib/arachni/http/proxy_server/ssl-interceptor-cakey.pem +51 -0
  127. data/lib/arachni/http/request.rb +71 -18
  128. data/lib/arachni/issue.rb +17 -3
  129. data/lib/arachni/option_groups/browser_cluster.rb +34 -1
  130. data/lib/arachni/option_groups/http.rb +1 -1
  131. data/lib/arachni/page.rb +26 -13
  132. data/lib/arachni/page/dom/transition.rb +2 -2
  133. data/lib/arachni/parser.rb +28 -11
  134. data/lib/arachni/platform/fingerprinter.rb +5 -0
  135. data/lib/arachni/platform/manager.rb +65 -32
  136. data/lib/arachni/plugin/base.rb +8 -0
  137. data/lib/arachni/processes/instances.rb +25 -11
  138. data/lib/arachni/reporter/manager.rb +2 -2
  139. data/lib/arachni/rpc/client/instance.rb +4 -0
  140. data/lib/arachni/rpc/server/framework/master.rb +3 -3
  141. data/lib/arachni/rpc/server/framework/multi_instance.rb +0 -8
  142. data/lib/arachni/rpc/server/instance.rb +2 -1
  143. data/lib/arachni/ruby/array.rb +5 -0
  144. data/lib/arachni/ruby/hash.rb +5 -0
  145. data/lib/arachni/ruby/string.rb +2 -3
  146. data/lib/arachni/session.rb +32 -6
  147. data/lib/arachni/state/framework.rb +6 -2
  148. data/lib/arachni/support/cache.rb +1 -0
  149. data/lib/arachni/support/cache/base.rb +12 -8
  150. data/lib/arachni/support/cache/least_recently_pushed.rb +29 -0
  151. data/lib/arachni/support/cache/least_recently_used.rb +5 -8
  152. data/lib/arachni/support/cache/preference.rb +1 -1
  153. data/lib/arachni/support/cache/random_replacement.rb +1 -25
  154. data/lib/arachni/support/database/queue.rb +21 -8
  155. data/lib/arachni/support/lookup/base.rb +7 -1
  156. data/lib/arachni/support/mixins/observable.rb +3 -1
  157. data/lib/arachni/support/profiler.rb +51 -10
  158. data/lib/arachni/support/signature.rb +11 -2
  159. data/lib/arachni/trainer.rb +8 -2
  160. data/lib/arachni/uri.rb +28 -25
  161. data/lib/arachni/uri/scope.rb +1 -1
  162. data/lib/arachni/utilities.rb +8 -0
  163. data/lib/arachni/watir/element.rb +1 -1
  164. data/lib/version +1 -1
  165. data/spec/arachni/browser/javascript/dom_monitor_spec.rb +388 -53
  166. data/spec/arachni/browser/javascript/taint_tracer_spec.rb +41 -0
  167. data/spec/arachni/browser/javascript_spec.rb +235 -61
  168. data/spec/arachni/browser_cluster/jobs/resource_exploration_spec.rb +0 -9
  169. data/spec/arachni/browser_cluster_spec.rb +58 -10
  170. data/spec/arachni/browser_spec.rb +170 -26
  171. data/spec/arachni/check/auditor_spec.rb +22 -3
  172. data/spec/arachni/check/base_spec.rb +84 -0
  173. data/spec/arachni/element/body_spec.rb +1 -1
  174. data/spec/arachni/element/capabilities/analyzable/taint_spec.rb +3 -3
  175. data/spec/arachni/element/capabilities/analyzable/timeout_spec.rb +1 -1
  176. data/spec/arachni/element/cookie/dom_spec.rb +0 -9
  177. data/spec/arachni/element/cookie_spec.rb +85 -0
  178. data/spec/arachni/element/form/dom_spec.rb +0 -9
  179. data/spec/arachni/element/form_spec.rb +46 -3
  180. data/spec/arachni/element/json_spec.rb +20 -0
  181. data/spec/arachni/element/link/dom_spec.rb +0 -9
  182. data/spec/arachni/element/link_spec.rb +40 -15
  183. data/spec/arachni/element/link_template/dom_spec.rb +0 -8
  184. data/spec/arachni/element/link_template_spec.rb +2 -6
  185. data/spec/arachni/element/server_spec.rb +94 -8
  186. data/spec/arachni/element/xml_spec.rb +20 -0
  187. data/spec/arachni/framework/parts/audit_spec.rb +12 -14
  188. data/spec/arachni/framework/parts/browser_spec.rb +0 -171
  189. data/spec/arachni/framework/parts/platform_spec.rb +14 -8
  190. data/spec/arachni/framework/parts/report_spec.rb +1 -1
  191. data/spec/arachni/framework/parts/state_spec.rb +0 -9
  192. data/spec/arachni/http/client/dynamic_404_handlers_spec.rb +19 -0
  193. data/spec/arachni/http/client_spec.rb +169 -42
  194. data/spec/arachni/http/headers_spec.rb +18 -0
  195. data/spec/arachni/http/request_spec.rb +23 -0
  196. data/spec/arachni/issue_spec.rb +17 -6
  197. data/spec/arachni/page_spec.rb +22 -2
  198. data/spec/arachni/parser_spec.rb +5 -0
  199. data/spec/arachni/platform/manager_spec.rb +57 -25
  200. data/spec/arachni/reporter/manager_spec.rb +26 -0
  201. data/spec/arachni/rpc/server/active_options_spec.rb +9 -4
  202. data/spec/arachni/state/framework_spec.rb +2 -8
  203. data/spec/arachni/support/cache/least_recently_pushed_spec.rb +90 -0
  204. data/spec/arachni/support/cache/least_recently_used_spec.rb +5 -13
  205. data/spec/arachni/support/database/queue_spec.rb +7 -0
  206. data/spec/arachni/support/mixins/observable_spec.rb +15 -1
  207. data/spec/arachni/trainer_spec.rb +2 -2
  208. data/spec/components/checks/active/code_injection_timing_spec.rb +1 -1
  209. data/spec/components/checks/active/file_inclusion_spec.rb +6 -6
  210. data/spec/components/checks/active/path_traversal_spec.rb +2 -2
  211. data/spec/components/checks/active/source_code_disclosure_spec.rb +2 -2
  212. data/spec/components/checks/active/unvalidated_redirect_spec.rb +6 -6
  213. data/spec/components/checks/active/xss_dom_inputs_spec.rb +3 -5
  214. data/spec/components/checks/active/xss_dom_script_context_spec.rb +1 -1
  215. data/spec/components/checks/active/xss_spec.rb +5 -5
  216. data/spec/components/checks/passive/common_admin_interfaces_spec.rb +15 -0
  217. data/spec/components/checks/passive/interesting_responses_spec.rb +14 -1
  218. data/spec/components/fingerprinters/frameworks/aspx_mvc_spec.rb +31 -0
  219. data/spec/components/fingerprinters/frameworks/cakephp_spec.rb +22 -0
  220. data/spec/components/fingerprinters/frameworks/cherrypy_spec.rb +28 -0
  221. data/spec/components/fingerprinters/frameworks/django_spec.rb +37 -0
  222. data/spec/components/fingerprinters/frameworks/jsf_spec.rb +27 -0
  223. data/spec/components/fingerprinters/frameworks/rack_spec.rb +11 -14
  224. data/spec/components/fingerprinters/frameworks/rails_spec.rb +53 -0
  225. data/spec/components/fingerprinters/languages/asp_spec.rb +7 -9
  226. data/spec/components/fingerprinters/languages/aspx_spec.rb +10 -24
  227. data/spec/components/fingerprinters/languages/java_spec.rb +88 -0
  228. data/spec/components/fingerprinters/languages/php_spec.rb +19 -12
  229. data/spec/components/fingerprinters/languages/python_spec.rb +22 -9
  230. data/spec/components/fingerprinters/languages/ruby.rb +6 -4
  231. data/spec/components/fingerprinters/os/bsd_spec.rb +6 -4
  232. data/spec/components/fingerprinters/os/linux_spec.rb +6 -4
  233. data/spec/components/fingerprinters/os/solaris_spec.rb +6 -4
  234. data/spec/components/fingerprinters/os/unix_spec.rb +6 -4
  235. data/spec/components/fingerprinters/os/windows_spec.rb +6 -4
  236. data/spec/components/fingerprinters/servers/apache_spec.rb +15 -4
  237. data/spec/components/fingerprinters/servers/gunicorn_spec.rb +28 -0
  238. data/spec/components/fingerprinters/servers/iis_spec.rb +6 -6
  239. data/spec/components/fingerprinters/servers/jetty_spec.rb +6 -6
  240. data/spec/components/fingerprinters/servers/nginx_spec.rb +6 -4
  241. data/spec/components/fingerprinters/servers/tomcat_spec.rb +15 -6
  242. data/spec/components/path_extractors/data_url_spec.rb +19 -0
  243. data/spec/components/plugins/autologin_spec.rb +23 -0
  244. data/spec/components/plugins/login_script_spec.rb +112 -24
  245. data/spec/components/plugins/restrict_to_dom_state_spec.rb +16 -0
  246. data/spec/components/plugins/vector_feed_spec.rb +39 -1
  247. data/spec/support/factories/page/dom.rb +9 -4
  248. data/spec/support/factories/page/dom/transition.rb +31 -9
  249. data/spec/support/factories/scan_report.rb +8 -6
  250. data/spec/support/fixtures/empty/placeholder +0 -0
  251. data/spec/support/fixtures/report.afr +0 -0
  252. data/spec/support/fixtures/reporters/manager_spec/error.rb +18 -0
  253. data/spec/support/servers/arachni/browser.rb +117 -11
  254. data/spec/support/servers/arachni/browser/javascript/dom_monitor.rb +148 -4
  255. data/spec/support/servers/arachni/check/auditor.rb +4 -0
  256. data/spec/support/servers/arachni/element/cookie/cookie_dom.rb +1 -1
  257. data/spec/support/servers/arachni/http/client.rb +5 -0
  258. data/spec/support/servers/arachni/http/client/dynamic_404_handler.rb +13 -0
  259. data/spec/support/servers/checks/active/code_injection_timing.rb +1 -1
  260. data/spec/support/servers/checks/active/file_inclusion.rb +2 -2
  261. data/spec/support/servers/checks/active/path_traversal.rb +2 -2
  262. data/spec/support/servers/checks/active/source_code_disclosure.rb +40 -33
  263. data/spec/support/servers/checks/active/trainer_check.rb +9 -10
  264. data/spec/support/servers/checks/active/unvalidated_redirect_dom.rb +7 -4
  265. data/spec/support/servers/checks/active/xss.rb +35 -0
  266. data/spec/support/servers/checks/active/xss_dom.rb +1 -1
  267. data/spec/support/servers/checks/active/xss_dom_inputs.rb +24 -0
  268. data/spec/support/servers/checks/active/xss_dom_script_context.rb +1 -1
  269. data/spec/support/servers/checks/passive/common_admin_interfaces.rb +6 -0
  270. data/spec/support/servers/plugins/autologin.rb +9 -0
  271. data/spec/support/servers/plugins/restrict_to_dom_state.rb +4 -0
  272. data/spec/support/shared/element/base.rb +42 -0
  273. data/spec/support/shared/element/capabilities/auditable.rb +4 -4
  274. data/spec/support/shared/element/capabilities/auditable/dom.rb +26 -0
  275. data/spec/support/shared/element/capabilities/inputtable.rb +16 -11
  276. data/spec/support/shared/element/capabilities/submitable.rb +7 -2
  277. data/spec/support/shared/fingerprinter.rb +8 -0
  278. data/spec/support/shared/path_extractor.rb +1 -1
  279. data/ui/cli/framework.rb +3 -3
  280. data/ui/cli/framework/option_parser.rb +9 -0
  281. data/ui/cli/output.rb +9 -0
  282. data/ui/cli/reporter.rb +5 -2
  283. data/ui/cli/utilities.rb +4 -2
  284. metadata +76 -17
  285. data/lib/arachni/http/proxy_server/ssl-interceptor-cert.pem +0 -34
  286. data/lib/arachni/http/proxy_server/ssl-interceptor-pkey.pem +0 -51
  287. data/spec/components/fingerprinters/languages/jsp_spec.rb +0 -56
@@ -12,18 +12,31 @@
12
12
  class Arachni::Plugins::LoginScript < Arachni::Plugin::Base
13
13
 
14
14
  STATUSES = {
15
- success: 'Login was successful.',
16
- failure: 'The script was executed successfully, but the login check failed.',
17
- error: 'A runtime error was encountered while executing the login script.',
18
- missing_check: 'No session check was provided, either via interface options or the script.'
15
+ success: 'Login was successful.',
16
+ failure: 'The script was executed successfully, but the login check failed.',
17
+ error: 'A runtime error was encountered while executing the login script.',
18
+ missing_browser: 'A browser is required for this operation but is not available.',
19
+ missing_check: 'No session check was provided, either via interface options or the script.'
19
20
  }
20
21
 
21
22
  def prepare
22
- script = IO.read( @options[:script] )
23
- @script = proc { |browser| eval script }
23
+ script = IO.read( @options[:script] )
24
+ @script = proc do |browser|
25
+ if javascript?
26
+ browser.goto @framework.options.url
27
+ browser.execute_script script
28
+ else
29
+ eval script
30
+ end
31
+ end
24
32
  end
25
33
 
26
34
  def run
35
+ if javascript? && !session.has_browser?
36
+ set_status :missing_browser, :error
37
+ return
38
+ end
39
+
27
40
  framework_pause
28
41
  print_info 'System paused.'
29
42
 
@@ -71,6 +84,10 @@ class Arachni::Plugins::LoginScript < Arachni::Plugin::Base
71
84
  framework_resume
72
85
  end
73
86
 
87
+ def javascript?
88
+ @options[:script].split( '.' ).last == 'js'
89
+ end
90
+
74
91
  def set_status( status, type = nil, extra = {} )
75
92
  type ||= status
76
93
 
@@ -96,7 +113,9 @@ The script needn't necessarily perform an actual login operation. If another
96
113
  process is used to manage sessions, the script can be used to communicate with
97
114
  that process and, for example, load and set cookies from a shared cookie-jar.
98
115
 
99
- **With browser (slow):**
116
+ # Ruby
117
+
118
+ ## With browser (slow)
100
119
 
101
120
  If a [browser](http://watirwebdriver.com/) is available, it will be exposed to
102
121
  the script via the `browser` variable. Otherwise, that variable will have a
@@ -115,7 +134,7 @@ value of `nil`.
115
134
  framework.options.session.check_url = browser.url
116
135
  framework.options.session.check_pattern = /Sign Off|MY ACCOUNT/
117
136
 
118
- **Without browser (fast):**
137
+ ## Without browser (fast)
119
138
 
120
139
  If a real browser environment is not required for the login operation, then
121
140
  using the system-wide HTTP interface is preferable, as it will be much faster
@@ -133,15 +152,26 @@ and consume much less resources.
133
152
  framework.options.session.check_url = to_absolute( response.headers.location, response.url )
134
153
  framework.options.session.check_pattern = /Sign Off|MY ACCOUNT/
135
154
 
136
- **From cookie-jar:**
155
+ ## From cookie-jar
137
156
 
138
157
  If an external process is used to manage sessions, you can keep Arachni in sync
139
158
  by loading cookies from a shared Netscape-style cookie-jar file.
140
159
 
141
160
  http.cookie_jar.load 'cookies.txt'
161
+
162
+ # Javascript
163
+
164
+ When the given script has a `.js` file extension, it will be loaded and executed
165
+ in the browser, within the page of the target URL.
166
+
167
+ document.getElementById( 'uid' ).value = 'jsmith';
168
+ document.getElementById( 'passw' ).value = 'Demo1234';
169
+
170
+ document.getElementById( 'login' ).submit();
171
+
142
172
  },
143
173
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
144
- version: '0.1',
174
+ version: '0.2',
145
175
  options: [
146
176
  Options::Path.new( :script,
147
177
  required: true,
@@ -0,0 +1,235 @@
1
+ =begin
2
+ Copyright 2010-2015 Tasos Laskos <tasos.laskos@arachni-scanner.com>
3
+
4
+ This file is part of the Arachni Framework project and is subject to
5
+ redistribution and commercial restrictions. Please see the Arachni Framework
6
+ web site for more information on licensing and terms of use.
7
+ =end
8
+
9
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
10
+ # @version 0.1
11
+ class Arachni::Plugins::Metrics < Arachni::Plugin::Base
12
+
13
+ def prepare
14
+ @metrics = {
15
+ 'general' => {
16
+ 'egress_traffic' => 0,
17
+ # Approximation, may differ from the real value depending on
18
+ # compression and other factors.
19
+ 'ingress_traffic' => 0,
20
+ 'uses_http' => false,
21
+ 'uses_https' => false
22
+ },
23
+ 'scan' => {
24
+ 'duration' => 0,
25
+ 'authenticated' => false
26
+ },
27
+ 'http' => {
28
+ 'requests' => 0,
29
+ 'response_time_min' => 0,
30
+ 'response_time_max' => 0,
31
+ 'response_time_average' => 0,
32
+ 'request_size_min' => 0,
33
+ 'request_size_max' => 0,
34
+ 'request_size_average' => 0,
35
+ 'response_size_min' => 0,
36
+ 'response_size_max' => 0,
37
+ 'response_size_average' => 0
38
+ },
39
+ 'resource' => {
40
+ 'binary' => Arachni::Support::LookUp::HashSet.new,
41
+ 'without_parameters' => Arachni::Support::LookUp::HashSet.new,
42
+ 'with_parameters' => Arachni::Support::LookUp::HashSet.new
43
+ },
44
+ 'element' => {
45
+ 'links' => 0,
46
+ 'forms' => 0,
47
+ 'cookies' => 0,
48
+ 'jsons' => 0,
49
+ 'xmls' => 0,
50
+ 'headers' => 0,
51
+ 'has_forms_with_nonces' => false,
52
+ 'has_forms_with_passwords' => false,
53
+ 'input_names_total' => 0,
54
+ 'input_names_unique' => Arachni::Support::LookUp::HashSet.new
55
+ },
56
+ 'dom' => {
57
+ 'event_listeners' => Arachni::Support::LookUp::HashSet.new,
58
+ 'swf_objects' => Arachni::Support::LookUp::HashSet.new
59
+ },
60
+ 'platforms' => Arachni::Platform::Manager::TYPES.keys.
61
+ inject({}) { |h, t| h[t.to_s] = Set.new; h }
62
+ }
63
+ end
64
+
65
+ def run
66
+ http_response_time_total = 0
67
+
68
+ http.on_complete do |response|
69
+ response.platforms.to_a.each do |platform|
70
+ @metrics['platforms'][Arachni::Platform::Manager.find_type( platform ).to_s] << platform.to_s
71
+ end
72
+
73
+ @metrics['general']['egress_traffic'] += response.request.to_s.size
74
+ @metrics['general']['ingress_traffic'] += response.to_s.size
75
+
76
+ if @metrics['http']['response_time_min'].is_a?( Integer ) ||
77
+ response.time < @metrics['http']['response_time_min']
78
+
79
+ @metrics['http']['response_time_min'] = response.time
80
+ end
81
+ if response.time > @metrics['http']['response_time_max']
82
+ @metrics['http']['response_time_max'] = response.time
83
+ end
84
+
85
+ response_size = response.to_s.size
86
+ if @metrics['http']['response_size_min'].is_a?( Integer ) ||
87
+ response_size < @metrics['http']['response_size_min']
88
+
89
+ @metrics['http']['response_size_min'] = response_size
90
+ end
91
+ if response_size > @metrics['http']['response_size_max']
92
+ @metrics['http']['response_size_max'] = response_size
93
+ end
94
+
95
+ request_size = response.request.to_s.size
96
+ if @metrics['http']['request_size_min'].is_a?( Integer ) ||
97
+ request_size < @metrics['http']['request_size_min']
98
+
99
+ @metrics['http']['request_size_min'] = request_size
100
+ end
101
+ if request_size > @metrics['http']['request_size_max']
102
+ @metrics['http']['request_size_max'] = request_size
103
+ end
104
+
105
+ # Only track OK codes, otherwise discovery checks will muck with the
106
+ # data.
107
+ if response.code == 200
108
+ if response.request.body.is_a?( Hash ) ||
109
+ response.request.parameters.any? ||
110
+ response.request.url.include?( '?' )
111
+
112
+ if response.request.body.is_a? Hash
113
+ body = response.request.body.keys.sort
114
+ else
115
+ body = nil
116
+ end
117
+
118
+ @metrics['resource']['with_parameters'] <<
119
+ "#{response.parsed_url.up_to_path}#{response.request.parameters.keys.sort}:#{body}"
120
+ else
121
+ @metrics['resource']['without_parameters'] << response.url
122
+ end
123
+ end
124
+
125
+ @metrics['general']['uses_http'] ||=
126
+ (response.parsed_url.scheme == 'http')
127
+ @metrics['general']['uses_https'] ||=
128
+ (response.parsed_url.scheme == 'https')
129
+
130
+ if !response.text?
131
+ @metrics['resource']['binary'] << response.url
132
+ end
133
+
134
+ http_response_time_total += response.time
135
+ end
136
+
137
+ framework.on_page_audit do |page|
138
+ %w(links forms cookies headers jsons xmls).each do |type|
139
+ page.send( type ).each do |e|
140
+ next if e.inputs.empty?
141
+
142
+ @metrics['element'][type] += 1
143
+ @metrics['element']['input_names_total'] += e.inputs.size
144
+
145
+ e.inputs.keys.each do |name|
146
+ @metrics['element']['input_names_unique'] << name
147
+ end
148
+
149
+ if e.is_a? Arachni::Element::Form
150
+ # Probably not a real form, just a request with inputs
151
+ # captured by the browsers and fed back to the system.
152
+ if !e.source
153
+ @metrics['element'][type] -= 1
154
+ end
155
+
156
+ @metrics['element']['has_forms_with_nonces'] ||= !!e.has_nonce?
157
+ @metrics['element']['has_forms_with_passwords'] ||= !!e.requires_password?
158
+ end
159
+ end
160
+ end
161
+
162
+ if (swf = find_swf( page ))
163
+ @metrics['dom']['swf_objects'] << swf
164
+ end
165
+
166
+ if Arachni::Options.scope.dom_depth_limit.to_i < page.dom.depth + 1 &&
167
+ browser_cluster && page.has_script?
168
+
169
+ with_browser do |browser|
170
+ browser.load( page ).each_element_with_events do |locator, event_data|
171
+ event_data.each do |data|
172
+ @metrics['dom']['event_listeners'] << "#{locator}:#{data}"
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ wait_while_framework_running
180
+
181
+ @metrics = process( @metrics )
182
+
183
+ @metrics['http']['requests'] = framework.statistics[:http][:response_count]
184
+
185
+ @metrics['http']['response_time_average'] =
186
+ http_response_time_total / @metrics['http']['requests']
187
+
188
+ @metrics['http']['response_size_average'] =
189
+ @metrics['general']['ingress_traffic'] / @metrics['http']['requests']
190
+
191
+ @metrics['http']['request_size_average'] =
192
+ @metrics['general']['egress_traffic'] / @metrics['http']['requests']
193
+
194
+ @metrics['scan']['duration'] = framework.statistics[:runtime]
195
+ @metrics['scan']['authenticated'] = !!Arachni::Options.session.check_url
196
+
197
+ register_results @metrics
198
+ end
199
+
200
+ def find_swf( page )
201
+ page.body.scan( /(?:data|src)=['"]?(.*)\.swf['"]?>/ )[0]
202
+ end
203
+
204
+ def process( hash )
205
+ h = {}
206
+ hash.each do |k, v|
207
+ case v
208
+ when Hash
209
+ v = process( v )
210
+
211
+ when Set
212
+ v = v.to_a
213
+
214
+ when Arachni::Support::LookUp::HashSet
215
+ v = v.size
216
+
217
+ end
218
+
219
+ h[k] = v
220
+ end
221
+ h
222
+ end
223
+
224
+ def self.info
225
+ {
226
+ name: 'Metrics',
227
+ description: %q{
228
+ Captures metrics about multiple aspects of the scan and the web application.
229
+ },
230
+ author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
231
+ version: '0.1'
232
+ }
233
+ end
234
+
235
+ end
@@ -60,7 +60,13 @@ class Arachni::Plugins::Proxy < Arachni::Plugin::Base
60
60
  print_info "Control panel URL: #{url_for( :panel )}"
61
61
  print_info "Shutdown URL: #{url_for( :shutdown )}"
62
62
  print_info 'The scan will resume once you visit the shutdown URL.'
63
-
63
+ print_info
64
+ print_info 'When browsing HTTPS sites, please accept the Arachni SSL certificate' +
65
+ ' or install the CA certificate manually from:'
66
+ print_info " #{Arachni::HTTP::ProxyServer::INTERCEPTOR_CA_CERTIFICATE}"
67
+ print_info
68
+ print_bad '**DO NOT** forget to revoke it after using the proxy, as it' +
69
+ ' can be used by anyone to impersonate 3rd party servers.'
64
70
  print_info
65
71
  print_info '*' * 82
66
72
  print_info '* You need to clear your browser\'s cookies for this site before using the proxy! *'
@@ -77,7 +83,12 @@ class Arachni::Plugins::Proxy < Arachni::Plugin::Base
77
83
  end
78
84
 
79
85
  def prepare_pages_for_inspection
80
- @pages.select { |p| (p.forms.any? || p.links.any? || p.cookies.any?) && p.text? }
86
+ (@pages.select do |p|
87
+ next if !p.text?
88
+
89
+ p.forms.any? || p.links.any? || p.cookies.any? || p.jsons.any? ||
90
+ p.xmls.any?
91
+ end).to_a
81
92
  end
82
93
 
83
94
  def vectors_yaml
@@ -86,12 +97,18 @@ class Arachni::Plugins::Proxy < Arachni::Plugin::Base
86
97
  page.elements.each do |element|
87
98
  next if element.inputs.empty?
88
99
 
89
- vectors << {
100
+ data = {
90
101
  type: element.type,
91
102
  method: element.method,
92
103
  action: element.action,
93
104
  inputs: element.inputs
94
105
  }
106
+
107
+ if element.respond_to? :source
108
+ data[:source] = element.source
109
+ end
110
+
111
+ vectors << data
95
112
  end
96
113
  end
97
114
  vectors.to_yaml
@@ -476,7 +493,7 @@ a way to restrict usage enough to avoid users unwittingly interfering with each
476
493
  others' sessions.
477
494
  },
478
495
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
479
- version: '0.3.2',
496
+ version: '0.3.3',
480
497
  options: [
481
498
  Options::Port.new( :port,
482
499
  description: 'Port to bind to.',
@@ -7,9 +7,13 @@
7
7
  <%= html_encode page.title %>
8
8
  -
9
9
  <%= page.forms.size %> forms,
10
- <%= page.links.size %> links and
11
- <%= page.cookies.size %> cookies
10
+ <%= page.links.size %> links,
11
+ <%= page.cookies.size %> cookies,
12
+ <%= page.jsons.size %> JSONs and
13
+ <%= page.xmls.size %> XMLs.
14
+
12
15
  <br/>
16
+
13
17
  (<%= page.url %>)
14
18
  </p>
15
19
  </div>
@@ -60,6 +64,34 @@
60
64
  <hr />
61
65
  <% end %>
62
66
  </div>
67
+ <div class="well links">
68
+ <h2>JSONs</h2>
69
+ <% page.jsons.each do |json| %>
70
+ <p>
71
+ <b>Action: <%= html_encode json.action %></b>
72
+ <ul>
73
+ <% json.inputs.each do |k, v| %>
74
+ <li><%= k.inspect %> = <%= v.inspect %></li>
75
+ <% end %>
76
+ </ul>
77
+ </p>
78
+ <hr />
79
+ <% end %>
80
+ </div>
81
+ <div class="well links">
82
+ <h2>XMLs</h2>
83
+ <% page.xmls.each do |xml| %>
84
+ <p>
85
+ <b>Action: <%= html_encode xml.action %></b>
86
+ <ul>
87
+ <% xml.inputs.each do |k, v| %>
88
+ <li><%= k.inspect %> = <%= v.inspect %></li>
89
+ <% end %>
90
+ </ul>
91
+ </p>
92
+ <hr />
93
+ <% end %>
94
+ </div>
63
95
  </div>
64
96
  </div>
65
97
  </div>
@@ -0,0 +1,70 @@
1
+ =begin
2
+ Copyright 2010-2015 Tasos Laskos <tasos.laskos@arachni-scanner.com>
3
+
4
+ This file is part of the Arachni Framework project and is subject to
5
+ redistribution and commercial restrictions. Please see the Arachni Framework
6
+ web site for more information on licensing and terms of use.
7
+ =end
8
+
9
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
10
+ # @version 0.1
11
+ class Arachni::Plugins::RestrictToDOMState < Arachni::Plugin::Base
12
+
13
+ def prepare
14
+ print_status 'Sending pause signal...'
15
+ @pause_id = framework.pause( false )
16
+ print_status '...done.'
17
+
18
+ # Disable any operations that can lead to a crawl, we only want the
19
+ # system to audit the page snapshot we give it.
20
+ framework.options.scope.do_not_crawl
21
+
22
+ @fragment = options[:fragment]
23
+ @url = "#{framework.options.url}##{@fragment}"
24
+
25
+ print_info "Full URL set to: #{@url}"
26
+ end
27
+
28
+ def run
29
+ print_status 'Initialising browser...'
30
+ browser = Arachni::Browser.new( store_pages: false )
31
+ print_status '...done.'
32
+
33
+ print_status 'Loading page...'
34
+ page = browser.load( @url ).to_page
35
+ print_info ' Transitions:'
36
+ page.dom.print_transitions( method(:print_info), ' ' )
37
+
38
+ framework.push_to_page_queue page, true
39
+ print_status 'Pushed to page queue.'
40
+ ensure
41
+ return if !browser
42
+
43
+ print_status 'Shutting down browser...'
44
+ browser.shutdown
45
+ print_status '...done.'
46
+ end
47
+
48
+ def clean_up
49
+ print_status 'Resuming scan...'
50
+ framework.resume @pause_id
51
+ print_status '...done.'
52
+ end
53
+
54
+ def self.info
55
+ {
56
+ name: 'Restrict to DOM state',
57
+ description: %q{Restricts the scan to a single page's DOM state.},
58
+ author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
59
+ version: '0.1',
60
+ options: [
61
+ Options::String.new( :fragment,
62
+ required: true,
63
+ description: 'URL fragment for the desired state.'
64
+ )
65
+ ],
66
+ priority: 0 # run before any other plugin
67
+ }
68
+ end
69
+
70
+ end