arachni 1.1 → 1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
@@ -185,6 +185,14 @@ class Base < Component::Base
185
185
  framework.http
186
186
  end
187
187
 
188
+ def browser_cluster
189
+ framework.browser_cluster
190
+ end
191
+
192
+ def with_browser( &block )
193
+ browser_cluster.with_browser( &block )
194
+ end
195
+
188
196
  # Registers the plugin's results to {Data::Plugins}.
189
197
  #
190
198
  # @param [Object] results
@@ -68,7 +68,7 @@ class Instances
68
68
  # `rpc_server_address` and `port` instead of `rpc_port`.
69
69
  #
70
70
  # @return [RPC::Client::Instance]
71
- def spawn( options = {} )
71
+ def spawn( options = {}, &block )
72
72
  token = options.delete(:token) || generate_token
73
73
  fork = options.delete(:fork)
74
74
 
@@ -93,17 +93,24 @@ class Instances
93
93
 
94
94
  Manager.spawn( :instance, options: options, token: token, fork: fork )
95
95
 
96
- while sleep( 0.1 )
97
- begin
98
- connect( url, token ).service.alive?
99
- break
100
- rescue => e
101
- # ap e
96
+ client = connect( url, token )
97
+
98
+ if block_given?
99
+ client.when_ready do
100
+ block.call client
101
+ end
102
+ else
103
+ while sleep( 0.1 )
104
+ begin
105
+ client.service.alive?
106
+ break
107
+ rescue => e
108
+ # ap "#{e.class}: #{e}"
109
+ # ap e.backtrace
110
+ end
102
111
  end
112
+ client
103
113
  end
104
-
105
- @list[url] = token
106
- connect( url )
107
114
  end
108
115
 
109
116
  # Starts {RPC::Server::Dispatcher} grid and returns a high-performance Instance.
@@ -168,7 +175,14 @@ class Instances
168
175
  end
169
176
 
170
177
  def kill( url )
171
- Manager.kill_many connect( url ).service.consumed_pids
178
+ service = connect( url ).service
179
+ service.consumed_pids do |pids|
180
+ service.shutdown do
181
+ # Make sure....
182
+ Manager.kill_many pids
183
+ end
184
+ end
185
+
172
186
  @list.delete url
173
187
  end
174
188
 
@@ -29,8 +29,8 @@ class Manager < Arachni::Component::Manager
29
29
  # @param [Hash] options
30
30
  #
31
31
  # @see Report
32
- def run( name, report, options = {} )
33
- exception_jail false do
32
+ def run( name, report, options = {}, raise = false )
33
+ exception_jail raise do
34
34
  self[name].new( report, prepare_options( name, self[name], options ) ).tap(&:run)
35
35
  end
36
36
  end
@@ -63,6 +63,10 @@ class Instance
63
63
  @plugins = Proxy.new( @client, 'plugins' )
64
64
  end
65
65
 
66
+ def when_ready( &block )
67
+ self.class.when_ready( url, token, &block )
68
+ end
69
+
66
70
  def token
67
71
  @token
68
72
  end
@@ -228,7 +228,7 @@ module Master
228
228
 
229
229
  # If for some reason we've got pages in the page queue this early,
230
230
  # consume them and get it over with.
231
- audit_page_queue
231
+ master_audit_page_queue
232
232
 
233
233
  @first_run = true if @first_run.nil?
234
234
  next_page = nil
@@ -266,10 +266,10 @@ module Master
266
266
  audit_page( page ) or http.run
267
267
  end
268
268
 
269
- audit_page_queue
269
+ master_audit_page_queue
270
270
  end
271
271
 
272
- audit_page_queue
272
+ master_audit_page_queue
273
273
 
274
274
  @audit_queues_done = true
275
275
  true
@@ -222,14 +222,6 @@ module MultiInstance
222
222
  end
223
223
  end
224
224
 
225
- def audit_page_queue
226
- if master?
227
- master_audit_page_queue
228
- else
229
- super
230
- end
231
- end
232
-
233
225
  # @return [Boolean]
234
226
  # `true` if `token` matches the local privilege token, `false` otherwise.
235
227
  def valid_token?( token )
@@ -276,12 +276,13 @@ class Instance
276
276
  @framework.resume( @rpc_pause_request )
277
277
 
278
278
  if !@framework.has_slaves?
279
+ @rpc_pause_request = nil
279
280
  block.call true
280
281
  return
281
282
  end
282
283
 
283
284
  each = proc { |instance, iter| instance.service.resume { iter.next } }
284
- each_slave( each, proc { block.call true } )
285
+ each_slave( each, proc { @rpc_pause_request = nil; block.call true } )
285
286
  end
286
287
 
287
288
  # @note Don't forget to {#shutdown} the instance once you get the report.
@@ -30,6 +30,11 @@ class Array
30
30
  map { |v| v.respond_to?( :recode ) ? v.recode : v }
31
31
  end
32
32
 
33
+ def recode!
34
+ each { |v| v.recode! if v.respond_to?( :recode! ) }
35
+ self
36
+ end
37
+
33
38
  def chunk( pieces = 2 )
34
39
  return self if pieces <= 0
35
40
 
@@ -100,6 +100,11 @@ class Hash
100
100
  recoded
101
101
  end
102
102
 
103
+ def recode!
104
+ each { |_, v| v.recode! if v.respond_to?( :recode! ) }
105
+ self
106
+ end
107
+
103
108
  # @return [Array<Symbol>]
104
109
  # Returns all symbol keys from +self+ and children hashes.
105
110
  def find_symbol_keys_recursively
@@ -146,9 +146,8 @@ class String
146
146
  end
147
147
 
148
148
  def recode!
149
- force_encoding( 'utf-8' )
150
- encode!( 'utf-16be', invalid: :replace, undef: :replace )
151
- encode!( 'utf-8' )
149
+ encode!( 'utf-8', invalid: :replace, undef: :replace )
150
+ self
152
151
  end
153
152
 
154
153
  def recode
@@ -43,6 +43,10 @@ class Session
43
43
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
44
44
  class FormNotFound < Error
45
45
  end
46
+
47
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
48
+ class FormNotVisible < Error
49
+ end
46
50
  end
47
51
 
48
52
  LOGIN_TRIES = 5
@@ -153,7 +157,8 @@ class Session
153
157
  elsif (url = opts[:url])
154
158
  http_opts = {
155
159
  update_cookies: true,
156
- follow_location: true
160
+ follow_location: true,
161
+ performer: self
157
162
  }
158
163
 
159
164
  if async
@@ -263,14 +268,20 @@ class Session
263
268
 
264
269
  http_options = http_options.merge(
265
270
  mode: block_given? ? :async : :sync,
266
- follow_location: true
271
+ follow_location: true,
272
+ performer: self
267
273
  )
268
274
 
275
+ print_debug 'Performing login check.'
276
+
269
277
  bool = nil
270
278
  http.get( Options.session.check_url, http_options ) do |response|
271
279
  bool = !!response.body.match( Options.session.check_pattern )
280
+
281
+ print_debug "Login check done: #{bool}"
272
282
  block.call( bool ) if block
273
283
  end
284
+
274
285
  bool
275
286
  end
276
287
 
@@ -335,8 +346,15 @@ class Session
335
346
 
336
347
  form.page = page
337
348
 
338
- # Use the form DOM to submit if a browser is available.
339
- form = form.dom if has_browser?
349
+ if has_browser?
350
+ # Use the form DOM to submit if a browser is available.
351
+ form = form.dom
352
+ form.browser = browser
353
+
354
+ if !form.element.visible?
355
+ fail Error::FormNotVisible, 'Login form is not visible in the DOM.'
356
+ end
357
+ end
340
358
 
341
359
  form.update configuration[:inputs]
342
360
  form.auditor = self
@@ -352,14 +370,22 @@ class Session
352
370
  page = form.submit(
353
371
  mode: :sync,
354
372
  follow_location: false,
355
- update_cookies: true
373
+ update_cookies: true,
374
+ performer: self
356
375
  ).to_page
357
376
 
358
377
  if page.response.redirection?
359
378
  url = to_absolute( page.response.headers.location, page.url )
360
379
  print_debug "Redirected to: #{url}"
361
380
 
362
- page = Page.from_url( url, precision: 1, http: { update_cookies: true } )
381
+ page = Page.from_url(
382
+ url,
383
+ precision: 1,
384
+ http: {
385
+ performer: self,
386
+ update_cookies: true
387
+ }
388
+ )
363
389
  end
364
390
  end
365
391
 
@@ -99,7 +99,6 @@ class Framework
99
99
  # All possible {#status_messages} by type.
100
100
  def available_status_messages
101
101
  {
102
- pausing: 'Will pause as soon as the current page is audited.',
103
102
  suspending: 'Will suspend as soon as the current page is audited.',
104
103
  waiting_for_browser_cluster_jobs: 'Waiting for %i browser cluster jobs to finish.',
105
104
  suspending_plugins: 'Suspending plugins.',
@@ -345,7 +344,6 @@ class Framework
345
344
 
346
345
  if !paused?
347
346
  @status = :pausing
348
- set_status_message :pausing
349
347
  end
350
348
 
351
349
  @pause_signals << caller
@@ -402,6 +400,12 @@ class Framework
402
400
  false
403
401
  end
404
402
 
403
+ def force_resume
404
+ @pause_signals.to_a.each do |ref|
405
+ resume ref
406
+ end
407
+ end
408
+
405
409
  def dump( directory )
406
410
  FileUtils.mkdir_p( directory )
407
411
 
@@ -8,6 +8,7 @@
8
8
 
9
9
  lib = Arachni::Options.paths.support + 'cache/'
10
10
  require lib + 'base'
11
+ require lib + 'least_recently_pushed'
11
12
  require lib + 'least_recently_used'
12
13
  require lib + 'random_replacement'
13
14
  require lib + 'least_cost_replacement'
@@ -60,7 +60,7 @@ class Base
60
60
  # @return [Integer]
61
61
  # Number of entries in the cache.
62
62
  def size
63
- cache.size
63
+ @cache.size
64
64
  end
65
65
 
66
66
  # Storage method.
@@ -74,7 +74,7 @@ class Base
74
74
  def store( k, v )
75
75
  prune while capped? && (size > max_size - 1)
76
76
 
77
- cache[k.hash] = v
77
+ @cache[make_key( k )] = v
78
78
  end
79
79
 
80
80
  # @see {#store}
@@ -90,7 +90,7 @@ class Base
90
90
  # @return [Object, nil]
91
91
  # Value for key `k`, `nil` if there is no key `k`.
92
92
  def []( k )
93
- cache[k.hash]
93
+ @cache[make_key( k )]
94
94
  end
95
95
 
96
96
  # @note If key `k` exists, its corresponding value will be returned.
@@ -109,13 +109,13 @@ class Base
109
109
  # @return [Bool]
110
110
  # `true` if cache includes an entry for key `k`, false otherwise.
111
111
  def include?( k )
112
- cache.include?( k.hash )
112
+ @cache.include?( make_key( k ) )
113
113
  end
114
114
 
115
115
  # @return [Bool]
116
116
  # `true` if cache is empty, false otherwise.
117
117
  def empty?
118
- cache.empty?
118
+ @cache.empty?
119
119
  end
120
120
 
121
121
  # @return [Bool]
@@ -132,12 +132,12 @@ class Base
132
132
  # @return [Object, nil]
133
133
  # Value for key `k`, `nil` if there is no key `k`.
134
134
  def delete( k )
135
- cache.delete( k.hash )
135
+ @cache.delete( make_key( k ) )
136
136
  end
137
137
 
138
138
  # Clears/empties the cache.
139
139
  def clear
140
- cache.clear
140
+ @cache.clear
141
141
  end
142
142
 
143
143
  def ==( other )
@@ -145,7 +145,7 @@ class Base
145
145
  end
146
146
 
147
147
  def hash
148
- cache.hash
148
+ @cache.hash
149
149
  end
150
150
 
151
151
  def dup
@@ -154,6 +154,10 @@ class Base
154
154
 
155
155
  private
156
156
 
157
+ def make_key( k )
158
+ k.hash
159
+ end
160
+
157
161
  def cache
158
162
  @cache
159
163
  end
@@ -0,0 +1,29 @@
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
+ module Arachni
10
+ module Support::Cache
11
+
12
+ # Least Recently Pushed cache implementation.
13
+ #
14
+ # Discards the least recently pushed entries, in order to make room for newer ones.
15
+ #
16
+ # This is the cache with best performance across the board.
17
+ #
18
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
19
+ class LeastRecentlyPushed < Base
20
+
21
+ private
22
+
23
+ def prune
24
+ @cache.delete( @cache.first.first )
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -15,23 +15,20 @@ module Support::Cache
15
15
  # Discards the least recently used entries in order to make room for newer ones.
16
16
  #
17
17
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
18
- class LeastRecentlyUsed < Base
18
+ class LeastRecentlyUsed < LeastRecentlyPushed
19
19
 
20
20
  # @see Arachni::Cache::Base#[]
21
21
  def []( k )
22
- super( k )
23
- ensure
22
+ return if !include? k
23
+
24
24
  renew( k )
25
+ super( k )
25
26
  end
26
27
 
27
28
  private
28
29
 
29
30
  def renew( k )
30
- @cache[k] = @cache.delete( k )
31
- end
32
-
33
- def prune
34
- @cache.delete( @cache.first.first )
31
+ @cache[make_key( k )] = @cache.delete( make_key( k ) )
35
32
  end
36
33
 
37
34
  end