arachni 0.3 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (348) hide show
  1. data/ACKNOWLEDGMENTS.md +1 -1
  2. data/CHANGELOG.md +146 -0
  3. data/CONTRIBUTORS.md +1 -0
  4. data/HACKING.md +3 -3
  5. data/README.md +81 -49
  6. data/Rakefile +11 -14
  7. data/bin/arachni +4 -8
  8. data/bin/arachni_rpc +17 -0
  9. data/bin/arachni_rpcd +18 -0
  10. data/bin/arachni_rpcd_monitor +18 -0
  11. data/bin/arachni_web +25 -48
  12. data/bin/arachni_web_autostart +3 -3
  13. data/conf/README.webui.yaml.txt +7 -21
  14. data/external/metasploit/plugins/arachni.rb +0 -7
  15. data/extras/modules/recon/raft_dirs.rb +108 -0
  16. data/extras/modules/recon/raft_dirs/raft-large-directories.txt +62290 -0
  17. data/extras/modules/recon/raft_files.rb +110 -0
  18. data/extras/modules/recon/raft_files/raft-large-files.txt +37037 -0
  19. data/extras/modules/recon/svn_digger_dirs.rb +108 -0
  20. data/extras/modules/recon/svn_digger_dirs/Licence.txt +674 -0
  21. data/extras/modules/recon/svn_digger_dirs/ReadMe-Arachni.txt +4 -0
  22. data/extras/modules/recon/svn_digger_dirs/ReadMe.txt +6 -0
  23. data/extras/modules/recon/svn_digger_dirs/all-dirs.txt +5960 -0
  24. data/extras/modules/recon/svn_digger_files.rb +114 -0
  25. data/extras/modules/recon/svn_digger_files/Licence.txt +674 -0
  26. data/extras/modules/recon/svn_digger_files/ReadMe-Arachni.txt +4 -0
  27. data/extras/modules/recon/svn_digger_files/ReadMe.txt +6 -0
  28. data/extras/modules/recon/svn_digger_files/all-extensionless.txt +25419 -0
  29. data/extras/modules/recon/svn_digger_files/all.txt +43135 -0
  30. data/lib/arachni.rb +2 -7
  31. data/lib/{audit_store.rb → arachni/audit_store.rb} +68 -60
  32. data/lib/{component_manager.rb → arachni/component_manager.rb} +8 -8
  33. data/lib/{component_options.rb → arachni/component_options.rb} +34 -4
  34. data/lib/{crypto → arachni/crypto}/rsa_aes_cbc.rb +1 -2
  35. data/lib/arachni/database.rb +4 -0
  36. data/lib/arachni/database/base.rb +125 -0
  37. data/lib/arachni/database/hash.rb +384 -0
  38. data/lib/arachni/database/queue.rb +93 -0
  39. data/lib/{exceptions.rb → arachni/exceptions.rb} +1 -1
  40. data/lib/arachni/framework.rb +899 -0
  41. data/lib/{http.rb → arachni/http.rb} +63 -166
  42. data/lib/{issue.rb → arachni/issue.rb} +46 -17
  43. data/lib/{mixins → arachni/mixins}/observable.rb +1 -1
  44. data/lib/arachni/mixins/progress_bar.rb +81 -0
  45. data/lib/arachni/mixins/terminal.rb +106 -0
  46. data/lib/{module.rb → arachni/module.rb} +0 -0
  47. data/lib/{module → arachni/module}/auditor.rb +250 -86
  48. data/lib/{module → arachni/module}/base.rb +8 -18
  49. data/lib/{module → arachni/module}/element_db.rb +10 -2
  50. data/lib/{module → arachni/module}/key_filler.rb +1 -1
  51. data/lib/arachni/module/manager.rb +145 -0
  52. data/lib/{module → arachni/module}/output.rb +6 -1
  53. data/lib/{module → arachni/module}/trainer.rb +48 -52
  54. data/lib/{module → arachni/module}/utilities.rb +66 -15
  55. data/lib/{nokogiri → arachni/nokogiri}/xml/node.rb +0 -0
  56. data/lib/arachni/options.rb +986 -0
  57. data/lib/{parser.rb → arachni/parser.rb} +0 -0
  58. data/lib/{parser → arachni/parser}/auditable.rb +111 -32
  59. data/lib/{parser → arachni/parser}/elements.rb +28 -20
  60. data/lib/{parser → arachni/parser}/page.rb +20 -3
  61. data/lib/{parser → arachni/parser}/parser.rb +100 -63
  62. data/lib/{plugin.rb → arachni/plugin.rb} +0 -0
  63. data/lib/{plugin → arachni/plugin}/base.rb +43 -6
  64. data/lib/{plugin → arachni/plugin}/manager.rb +40 -13
  65. data/lib/{report.rb → arachni/report.rb} +0 -0
  66. data/lib/{report → arachni/report}/base.rb +43 -2
  67. data/lib/{report → arachni/report}/manager.rb +7 -18
  68. data/lib/arachni/rpc/client/base.rb +42 -0
  69. data/lib/{rpc/xml → arachni/rpc}/client/dispatcher.rb +12 -13
  70. data/lib/arachni/rpc/client/instance.rb +62 -0
  71. data/lib/arachni/rpc/server/base.rb +51 -0
  72. data/lib/arachni/rpc/server/dispatcher.rb +438 -0
  73. data/lib/arachni/rpc/server/framework.rb +1163 -0
  74. data/lib/arachni/rpc/server/instance.rb +184 -0
  75. data/lib/{rpc/xml → arachni/rpc}/server/module/manager.rb +8 -5
  76. data/lib/arachni/rpc/server/node.rb +267 -0
  77. data/lib/{rpc/xml → arachni/rpc}/server/options.rb +6 -35
  78. data/lib/{rpc/xml → arachni/rpc}/server/output.rb +29 -3
  79. data/lib/{rpc/xml → arachni/rpc}/server/plugin/manager.rb +5 -6
  80. data/lib/{ruby.rb → arachni/ruby.rb} +1 -2
  81. data/lib/arachni/ruby/array.rb +31 -0
  82. data/lib/{ruby → arachni/ruby}/object.rb +1 -1
  83. data/lib/{ruby → arachni/ruby}/string.rb +1 -1
  84. data/lib/{spider.rb → arachni/spider.rb} +83 -110
  85. data/lib/arachni/typhoeus/hydra.rb +7 -0
  86. data/lib/{typhoeus → arachni/typhoeus}/request.rb +11 -9
  87. data/lib/{typhoeus → arachni/typhoeus}/response.rb +4 -0
  88. data/lib/{ui → arachni/ui}/cli/cli.rb +154 -84
  89. data/lib/{ui → arachni/ui}/cli/output.rb +57 -19
  90. data/lib/{ui/xmlrpc → arachni/ui/rpc}/dispatcher_monitor.rb +11 -10
  91. data/lib/{ui/xmlrpc/xmlrpc.rb → arachni/ui/rpc/rpc.rb} +102 -158
  92. data/lib/{ui → arachni/ui}/web/addon_manager.rb +23 -3
  93. data/lib/arachni/ui/web/addons/autodeploy.rb +207 -0
  94. data/lib/{ui → arachni/ui}/web/addons/autodeploy/lib/manager.rb +142 -35
  95. data/lib/arachni/ui/web/addons/autodeploy/views/index.erb +291 -0
  96. data/lib/{ui → arachni/ui}/web/addons/sample.rb +1 -1
  97. data/lib/{ui → arachni/ui}/web/addons/sample/views/index.erb +0 -0
  98. data/lib/{ui → arachni/ui}/web/addons/scheduler.rb +30 -22
  99. data/lib/{ui → arachni/ui}/web/addons/scheduler/views/index.erb +56 -22
  100. data/lib/{ui → arachni/ui}/web/addons/scheduler/views/options.erb +0 -0
  101. data/lib/arachni/ui/web/dispatcher_manager.rb +274 -0
  102. data/lib/arachni/ui/web/instance_manager.rb +69 -0
  103. data/lib/{ui → arachni/ui}/web/log.rb +1 -1
  104. data/lib/arachni/ui/web/output_stream.rb +54 -0
  105. data/lib/{ui → arachni/ui}/web/report_manager.rb +48 -54
  106. data/lib/{ui → arachni/ui}/web/scheduler.rb +42 -47
  107. data/lib/arachni/ui/web/server.rb +1197 -0
  108. data/lib/{ui → arachni/ui}/web/server/db/placeholder +0 -0
  109. data/lib/{ui → arachni/ui}/web/server/public/banner.png +0 -0
  110. data/lib/{ui → arachni/ui}/web/server/public/bodybg-small.png +0 -0
  111. data/lib/{ui → arachni/ui}/web/server/public/bodybg.png +0 -0
  112. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/pbar-ani.gif +0 -0
  113. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  114. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  115. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  116. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  117. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  118. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  119. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  120. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  121. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  122. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  123. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  124. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  125. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  126. data/lib/{ui → arachni/ui}/web/server/public/css/smoothness/jquery-ui-1.8.9.custom.css +0 -0
  127. data/lib/{ui → arachni/ui}/web/server/public/favicon.ico +0 -0
  128. data/lib/{ui → arachni/ui}/web/server/public/footer.jpg +0 -0
  129. data/lib/{ui/web/server/public/icons/error.png → arachni/ui/web/server/public/icons/bad.png} +0 -0
  130. data/lib/arachni/ui/web/server/public/icons/error.png +0 -0
  131. data/lib/{ui → arachni/ui}/web/server/public/icons/info.png +0 -0
  132. data/lib/{ui → arachni/ui}/web/server/public/icons/ok.png +0 -0
  133. data/lib/{ui → arachni/ui}/web/server/public/icons/status.png +0 -0
  134. data/lib/{ui → arachni/ui}/web/server/public/js/jquery-1.4.4.min.js +0 -0
  135. data/lib/{ui → arachni/ui}/web/server/public/js/jquery-ui-1.8.9.custom.min.js +0 -0
  136. data/lib/{ui → arachni/ui}/web/server/public/js/jquery-ui-timepicker.js +0 -0
  137. data/lib/{ui → arachni/ui}/web/server/public/logo.png +0 -0
  138. data/lib/{ui → arachni/ui}/web/server/public/nav-left.jpg +0 -0
  139. data/lib/{ui → arachni/ui}/web/server/public/nav-right.jpg +0 -0
  140. data/lib/{ui → arachni/ui}/web/server/public/nav-selected-left.jpg +0 -0
  141. data/lib/{ui → arachni/ui}/web/server/public/nav-selected-right.jpg +0 -0
  142. data/lib/{ui → arachni/ui}/web/server/public/plugins/sample/style.css +0 -0
  143. data/lib/{ui/web/server/tmp → arachni/ui/web/server/public/reports}/placeholder +0 -0
  144. data/lib/{ui → arachni/ui}/web/server/public/sidebar-bottom.jpg +0 -0
  145. data/lib/{ui → arachni/ui}/web/server/public/sidebar-h4.jpg +0 -0
  146. data/lib/{ui → arachni/ui}/web/server/public/sidebar-top.jpg +0 -0
  147. data/lib/{ui → arachni/ui}/web/server/public/spider.png +0 -0
  148. data/lib/{ui → arachni/ui}/web/server/public/style.css +3 -2
  149. data/lib/arachni/ui/web/server/tmp/placeholder +0 -0
  150. data/lib/{ui → arachni/ui}/web/server/views/addon.erb +0 -0
  151. data/lib/{ui → arachni/ui}/web/server/views/addons.erb +0 -0
  152. data/lib/{ui → arachni/ui}/web/server/views/dispatcher_error.erb +0 -0
  153. data/lib/arachni/ui/web/server/views/dispatchers.erb +175 -0
  154. data/lib/arachni/ui/web/server/views/dispatchers_edit.erb +71 -0
  155. data/lib/arachni/ui/web/server/views/error.erb +22 -0
  156. data/lib/{ui → arachni/ui}/web/server/views/flash.erb +2 -2
  157. data/lib/arachni/ui/web/server/views/home.erb +60 -0
  158. data/lib/{ui → arachni/ui}/web/server/views/instance.erb +55 -75
  159. data/lib/arachni/ui/web/server/views/js/home.erb +32 -0
  160. data/lib/{ui → arachni/ui}/web/server/views/layout.erb +2 -2
  161. data/lib/{ui → arachni/ui}/web/server/views/log.erb +0 -0
  162. data/lib/arachni/ui/web/server/views/module.erb +30 -0
  163. data/lib/{ui → arachni/ui}/web/server/views/modules.erb +2 -22
  164. data/lib/{ui → arachni/ui}/web/server/views/options.erb +0 -0
  165. data/lib/{ui → arachni/ui}/web/server/views/output_results.erb +4 -4
  166. data/lib/{ui → arachni/ui}/web/server/views/plugins.erb +23 -12
  167. data/lib/{ui → arachni/ui}/web/server/views/report_formats.erb +1 -1
  168. data/lib/{ui → arachni/ui}/web/server/views/reports.erb +1 -1
  169. data/lib/{ui → arachni/ui}/web/server/views/settings.erb +59 -16
  170. data/lib/{ui → arachni/ui}/web/server/views/welcome.erb +3 -1
  171. data/lib/{ui → arachni/ui}/web/utilities.rb +8 -3
  172. data/lib/arachni/version.rb +16 -0
  173. data/modules/audit/code_injection.rb +11 -20
  174. data/modules/audit/code_injection_timing.rb +2 -6
  175. data/modules/audit/csrf.rb +8 -16
  176. data/modules/audit/ldapi.rb +5 -11
  177. data/modules/audit/os_cmd_injection.rb +5 -9
  178. data/modules/audit/os_cmd_injection_timing.rb +4 -8
  179. data/modules/audit/path_traversal.rb +7 -13
  180. data/modules/audit/response_splitting.rb +8 -21
  181. data/modules/audit/rfi.rb +6 -46
  182. data/modules/audit/sqli.rb +5 -11
  183. data/modules/audit/sqli/regexp_ids.txt +0 -6
  184. data/modules/audit/sqli_blind_rdiff.rb +5 -10
  185. data/modules/audit/sqli_blind_timing.rb +4 -9
  186. data/modules/audit/trainer.rb +6 -12
  187. data/modules/audit/unvalidated_redirect.rb +6 -17
  188. data/modules/audit/xpath.rb +5 -12
  189. data/modules/audit/xss.rb +37 -23
  190. data/modules/audit/xss_event.rb +5 -10
  191. data/modules/audit/xss_path.rb +47 -41
  192. data/modules/audit/xss_script_tag.rb +5 -10
  193. data/modules/audit/xss_tag.rb +5 -10
  194. data/modules/audit/xss_uri.rb +17 -89
  195. data/modules/recon/allowed_methods.rb +6 -15
  196. data/modules/recon/backdoors.rb +12 -52
  197. data/modules/recon/backup_files.rb +25 -88
  198. data/modules/recon/common_directories.rb +8 -54
  199. data/modules/recon/common_files.rb +7 -58
  200. data/modules/recon/directory_listing.rb +6 -15
  201. data/modules/recon/grep/captcha.rb +1 -1
  202. data/modules/recon/grep/credit_card.rb +62 -27
  203. data/modules/recon/grep/cvs_svn_users.rb +1 -1
  204. data/modules/recon/grep/emails.rb +1 -1
  205. data/modules/recon/grep/html_objects.rb +1 -1
  206. data/modules/recon/grep/private_ip.rb +1 -1
  207. data/modules/recon/grep/ssn.rb +9 -9
  208. data/modules/recon/htaccess_limit.rb +6 -14
  209. data/modules/recon/http_put.rb +7 -15
  210. data/modules/recon/interesting_responses.rb +7 -13
  211. data/modules/recon/mixed_resource.rb +100 -0
  212. data/modules/recon/unencrypted_password_forms.rb +8 -20
  213. data/modules/recon/webdav.rb +6 -16
  214. data/modules/recon/xst.rb +7 -13
  215. data/path_extractors/anchors.rb +1 -1
  216. data/path_extractors/forms.rb +1 -1
  217. data/path_extractors/frames.rb +1 -1
  218. data/path_extractors/generic.rb +47 -3
  219. data/path_extractors/links.rb +1 -1
  220. data/path_extractors/meta_refresh.rb +1 -1
  221. data/path_extractors/scripts.rb +3 -4
  222. data/path_extractors/sitemap.rb +1 -1
  223. data/plugins/autologin.rb +9 -18
  224. data/plugins/beep_notify.rb +51 -0
  225. data/plugins/cookie_collector.rb +12 -12
  226. data/plugins/defaults/autothrottle.rb +86 -0
  227. data/plugins/{content_types.rb → defaults/content_types.rb} +25 -19
  228. data/plugins/{healthmap.rb → defaults/healthmap.rb} +30 -18
  229. data/plugins/defaults/metamodules/remedies/discovery.rb +164 -0
  230. data/plugins/defaults/metamodules/remedies/manual_verification.rb +65 -0
  231. data/{metamodules/timeout_notice.rb → plugins/defaults/metamodules/remedies/timing_attacks.rb} +26 -22
  232. data/{metamodules → plugins/defaults/metamodules}/uniformity.rb +15 -14
  233. data/plugins/{profiler.rb → defaults/profiler.rb} +19 -30
  234. data/plugins/defaults/resolver.rb +55 -0
  235. data/plugins/email_notify.rb +108 -0
  236. data/plugins/form_dicattack.rb +8 -16
  237. data/plugins/http_dicattack.rb +4 -12
  238. data/plugins/libnotify.rb +86 -0
  239. data/plugins/proxy.rb +8 -17
  240. data/plugins/proxy/server.rb +3 -3
  241. data/plugins/rescan.rb +60 -0
  242. data/plugins/waf_detector.rb +5 -16
  243. data/profiles/full.afp +3 -30
  244. data/reports/afr.rb +2 -5
  245. data/reports/ap.rb +3 -1
  246. data/reports/html.rb +210 -68
  247. data/reports/html/default.erb +72 -1014
  248. data/reports/html/default/configuration.erb +126 -0
  249. data/reports/html/default/css/jquery-ui.css +570 -0
  250. data/reports/html/default/css/jquery.jqplot.min.css +1 -0
  251. data/reports/html/default/css/main.css +391 -0
  252. data/reports/html/default/issue.erb +189 -0
  253. data/reports/html/default/issues.erb +65 -0
  254. data/reports/html/default/js/charts.js +146 -0
  255. data/reports/html/default/js/helpers.js +95 -0
  256. data/reports/html/default/js/init.js +73 -0
  257. data/reports/html/default/js/lib/jqplot.barRenderer.min.js +57 -0
  258. data/reports/html/default/js/lib/jqplot.categoryAxisRenderer.min.js +57 -0
  259. data/reports/html/default/js/lib/jqplot.cursor.min.js +57 -0
  260. data/reports/html/default/js/lib/jqplot.pieRenderer.min.js +57 -0
  261. data/reports/html/default/js/lib/jqplot.pointLabels.min.js +57 -0
  262. data/reports/html/default/js/lib/jquery-ui.min.js +404 -0
  263. data/reports/html/default/js/lib/jquery.jqplot.min.js +57 -0
  264. data/reports/html/default/js/lib/jquery.min.js +167 -0
  265. data/reports/html/default/plugins.erb +22 -0
  266. data/reports/html/default/search.erb +8 -0
  267. data/reports/html/default/sitemap.erb +15 -0
  268. data/reports/html/default/summary.erb +68 -0
  269. data/reports/html/default/summary_issue.erb +19 -0
  270. data/reports/json.rb +51 -0
  271. data/reports/marshal.rb +49 -0
  272. data/reports/metareport.rb +4 -6
  273. data/reports/metareport/arachni_metareport.rb +1 -1
  274. data/reports/plugin_formatters/html/autologin.rb +30 -41
  275. data/reports/plugin_formatters/html/content_types.rb +1 -10
  276. data/reports/plugin_formatters/html/cookie_collector.rb +36 -44
  277. data/reports/plugin_formatters/html/discovery.rb +50 -0
  278. data/reports/plugin_formatters/html/form_dicattack.rb +24 -32
  279. data/reports/plugin_formatters/html/healthmap.rb +45 -54
  280. data/reports/plugin_formatters/html/http_dicattack.rb +24 -32
  281. data/reports/plugin_formatters/html/profiler.rb +17 -48
  282. data/reports/plugin_formatters/html/profiler/template.erb +6 -99
  283. data/reports/plugin_formatters/html/resolver.rb +63 -0
  284. data/reports/plugin_formatters/html/{metaformatters/timeout_notice.rb → timing_attacks.rb} +7 -19
  285. data/reports/plugin_formatters/html/{metaformatters/uniformity.rb → uniformity.rb} +5 -17
  286. data/reports/plugin_formatters/html/waf_detector.rb +24 -32
  287. data/reports/plugin_formatters/stdout/autologin.rb +30 -35
  288. data/reports/plugin_formatters/stdout/content_types.rb +41 -46
  289. data/reports/plugin_formatters/stdout/cookie_collector.rb +33 -38
  290. data/reports/plugin_formatters/stdout/discovery.rb +47 -0
  291. data/reports/plugin_formatters/stdout/form_dicattack.rb +27 -32
  292. data/reports/plugin_formatters/stdout/healthmap.rb +47 -51
  293. data/reports/plugin_formatters/stdout/http_dicattack.rb +27 -32
  294. data/reports/plugin_formatters/stdout/metamodules.rb +48 -55
  295. data/reports/plugin_formatters/stdout/profiler.rb +60 -65
  296. data/reports/plugin_formatters/stdout/resolver.rb +45 -0
  297. data/reports/plugin_formatters/stdout/{metaformatters/timeout_notice.rb → timing_attacks.rb} +6 -14
  298. data/reports/plugin_formatters/stdout/{metaformatters/uniformity.rb → uniformity.rb} +6 -14
  299. data/reports/plugin_formatters/stdout/waf_detector.rb +23 -28
  300. data/reports/plugin_formatters/xml/autologin.rb +36 -41
  301. data/reports/plugin_formatters/xml/content_types.rb +47 -52
  302. data/reports/plugin_formatters/xml/cookie_collector.rb +39 -44
  303. data/reports/plugin_formatters/xml/discovery.rb +54 -0
  304. data/reports/plugin_formatters/xml/form_dicattack.rb +22 -27
  305. data/reports/plugin_formatters/xml/healthmap.rb +53 -58
  306. data/reports/plugin_formatters/xml/http_dicattack.rb +22 -27
  307. data/reports/plugin_formatters/xml/profiler.rb +61 -77
  308. data/reports/plugin_formatters/xml/resolver.rb +53 -0
  309. data/reports/plugin_formatters/xml/{metaformatters/timeout_notice.rb → timing_attacks.rb} +3 -15
  310. data/reports/plugin_formatters/xml/{metaformatters/uniformity.rb → uniformity.rb} +4 -14
  311. data/reports/plugin_formatters/xml/waf_detector.rb +23 -28
  312. data/reports/stdout.rb +1 -1
  313. data/reports/txt.rb +2 -5
  314. data/reports/xml.rb +2 -5
  315. data/reports/xml/buffer.rb +6 -2
  316. data/reports/yaml.rb +49 -0
  317. metadata +419 -278
  318. data/bin/arachni_xmlrpc +0 -21
  319. data/bin/arachni_xmlrpcd +0 -82
  320. data/bin/arachni_xmlrpcd_monitor +0 -74
  321. data/getoptslong.rb +0 -242
  322. data/lib/anemone.rb +0 -2
  323. data/lib/framework.rb +0 -673
  324. data/lib/module/manager.rb +0 -111
  325. data/lib/options.rb +0 -547
  326. data/lib/rpc/xml/client/base.rb +0 -76
  327. data/lib/rpc/xml/client/instance.rb +0 -88
  328. data/lib/rpc/xml/server/base.rb +0 -112
  329. data/lib/rpc/xml/server/dispatcher.rb +0 -386
  330. data/lib/rpc/xml/server/framework.rb +0 -206
  331. data/lib/rpc/xml/server/instance.rb +0 -191
  332. data/lib/ruby/xmlrpc/server.rb +0 -27
  333. data/lib/ui/web/addons/autodeploy.rb +0 -172
  334. data/lib/ui/web/addons/autodeploy/views/index.erb +0 -124
  335. data/lib/ui/web/dispatcher_manager.rb +0 -165
  336. data/lib/ui/web/instance_manager.rb +0 -87
  337. data/lib/ui/web/output_stream.rb +0 -94
  338. data/lib/ui/web/server.rb +0 -925
  339. data/lib/ui/web/server/public/reports/placeholder +0 -1
  340. data/lib/ui/web/server/views/dispatchers.erb +0 -100
  341. data/lib/ui/web/server/views/dispatchers_edit.erb +0 -42
  342. data/lib/ui/web/server/views/error.erb +0 -1
  343. data/lib/ui/web/server/views/home.erb +0 -25
  344. data/metamodules/autothrottle.rb +0 -74
  345. data/plugins/metamodules.rb +0 -118
  346. data/profiles/comprehensive.afp +0 -74
  347. data/reports/plugin_formatters/html/metamodules.rb +0 -93
  348. data/reports/plugin_formatters/xml/metamodules.rb +0 -91
@@ -1,925 +0,0 @@
1
- =begin
2
- Arachni
3
- Copyright (c) 2010-2011 Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
4
-
5
- This is free software; you can copy and distribute and modify
6
- this program under the term of the GPL v2.0 License
7
- (See LICENSE file for details)
8
-
9
- =end
10
-
11
- require 'webrick'
12
- require 'webrick/https'
13
- require 'openssl'
14
-
15
- require 'sinatra/base'
16
- require "rack/csrf"
17
- require 'rack-flash'
18
- require 'json'
19
- require 'erb'
20
- require 'yaml'
21
- require 'cgi'
22
- require 'fileutils'
23
- require 'ap'
24
-
25
-
26
- module Arachni
27
- module UI
28
-
29
- require Arachni::Options.instance.dir['lib'] + 'ui/cli/output'
30
- require Arachni::Options.instance.dir['lib'] + 'framework'
31
- require Arachni::Options.instance.dir['lib'] + 'ui/web/utilities'
32
- require Arachni::Options.instance.dir['lib'] + 'ui/web/report_manager'
33
- require Arachni::Options.instance.dir['lib'] + 'ui/web/dispatcher_manager'
34
- require Arachni::Options.instance.dir['lib'] + 'ui/web/instance_manager'
35
- require Arachni::Options.instance.dir['lib'] + 'ui/web/scheduler'
36
- require Arachni::Options.instance.dir['lib'] + 'ui/web/log'
37
- require Arachni::Options.instance.dir['lib'] + 'ui/web/output_stream'
38
-
39
- require Arachni::Options.instance.dir['lib'] + 'ui/web/addon_manager'
40
-
41
- #
42
- #
43
- # Provides a web user interface for the Arachni Framework using Sinatra.
44
- #
45
- # It's basically an XMLRPC client for Dispatchers and Instances wearing a pretty frock.
46
- #
47
- # @author: Tasos "Zapotek" Laskos
48
- # <tasos.laskos@gmail.com>
49
- # <zapotek@segfault.gr>
50
- # @version: 0.2
51
- #
52
- # @see Arachni::RPC::XML::Client::Instance
53
- # @see Arachni::RPC::XML::Client::Dispatcher
54
- #
55
- module Web
56
-
57
- VERSION = '0.2'
58
-
59
- class Server < Sinatra::Base
60
-
61
- include Utilities
62
-
63
- configure do
64
- use Rack::Flash
65
- use Rack::Session::Cookie
66
- use Rack::Csrf, :raise => true
67
-
68
- @@conf = YAML::load_file( Arachni::Options.instance.dir['root'] + 'conf/webui.yaml' )
69
- Arachni::Options.instance.ssl = @@conf['ssl']['client']['enable']
70
- Arachni::Options.instance.ssl_pkey = @@conf['ssl']['client']['key']
71
- Arachni::Options.instance.ssl_cert = @@conf['ssl']['client']['cert']
72
- Arachni::Options.instance.ssl_ca = @@conf['ssl']['client']['ca']
73
-
74
- end
75
-
76
- helpers do
77
-
78
- def title
79
- main = 'Arachni - Web Application Security Scanner Framework'
80
-
81
- sub = env['PATH_INFO'].split( '/' ).map {
82
- |part|
83
- normalize_section_name( part )
84
- }.reject { |part| part.empty? }.join( ' &rarr; ' )
85
-
86
- return sub.empty? ? main : sub + ' :: ' + main
87
- end
88
-
89
- def normalize_section_name( name )
90
- name.gsub( '_', ' ' ).capitalize
91
- end
92
-
93
- def report_count
94
- reports.all.size
95
- end
96
-
97
- def plugin_has_required_file_option?( options )
98
- options.each {
99
- |opt|
100
- return true if opt['type'] == 'path' && opt['required']
101
- }
102
-
103
- return false
104
- end
105
-
106
- def format_redundants( rules )
107
- return if !rules || !rules.is_a?( Array ) || rules.empty?
108
-
109
- str = ''
110
- rules.each {
111
- |rule|
112
- next if !rule['regexp'] || !rule['count']
113
- str += rule['regexp'] + ':' + rule['count'] + "\r\n"
114
- }
115
- return str
116
- end
117
-
118
- def prep_description( str )
119
- placeholder = '--' + rand( 1000 ).to_s + '--'
120
- cstr = str.gsub( /^\s*$/xm, placeholder )
121
- cstr.gsub!( /^\s*/xm, '' )
122
- cstr.gsub!( placeholder, "\n" )
123
- cstr.chomp
124
- end
125
-
126
- def selected_tab?( tab )
127
- splits = env['PATH_INFO'].split( '/' )
128
- ( splits.empty? && tab == '/' ) || splits[1] == tab
129
- end
130
-
131
- def csrf_token
132
- Rack::Csrf.csrf_token( env )
133
- end
134
-
135
- def csrf_tag
136
- Rack::Csrf.csrf_tag( env )
137
- end
138
-
139
- def modules
140
- @@modules
141
- end
142
-
143
- def plugins
144
- @@plugins
145
- end
146
-
147
- def proc_mem( rss )
148
- # we assume a page size of 4096
149
- rss.to_i * 4096 / 1024 / 1024
150
- end
151
-
152
- def secs_to_hms( secs )
153
- secs = secs.to_i
154
- return [secs/3600, secs/60 % 60, secs % 60].map {
155
- |t|
156
- t.to_s.rjust( 2, '0' )
157
- }.join(':')
158
- end
159
-
160
- end
161
-
162
-
163
- dir = File.dirname( File.expand_path( __FILE__ ) )
164
-
165
- set :views, "#{dir}/server/views"
166
- set :public, "#{dir}/server/public"
167
- set :tmp, "#{dir}/server/tmp"
168
- set :db, "#{dir}/server/db"
169
- set :static, true
170
- set :environment, :development
171
-
172
- #
173
- # This will be used for the "owner" field of the helper instance
174
- #
175
- HELPER_OWNER = "WebUI helper"
176
-
177
- enable :sessions
178
-
179
- set :log, Log.new( Arachni::Options.instance, settings )
180
- set :reports, ReportManager.new( Arachni::Options.instance, settings )
181
- set :dispatchers, DispatcherManager.new( Arachni::Options.instance, settings )
182
- set :instances, InstanceManager.new( Arachni::Options.instance, settings )
183
- set :scheduler, Scheduler.new( Arachni::Options.instance, settings )
184
- set :addons, AddonManager.new( Arachni::Options.instance, settings )
185
-
186
- configure do
187
- # shit's on!
188
- log.webui_started
189
- end
190
-
191
- def addons
192
- settings.addons
193
- end
194
-
195
- def log
196
- settings.log
197
- end
198
-
199
- def reports
200
- settings.reports
201
- end
202
-
203
- def dispatchers
204
- settings.dispatchers
205
- end
206
-
207
- #
208
- # Provides statistics about running jobs etc using the dispatcher
209
- #
210
- def dispatcher_stats
211
- dispatchers.stats
212
- end
213
-
214
- def scheduler
215
- settings.scheduler
216
- end
217
-
218
- def instances
219
- settings.instances
220
- end
221
-
222
- def exception_jail( &block )
223
- # begin
224
- block.call
225
- # rescue Errno::ECONNREFUSED => e
226
- # erb :error, { :layout => true }, :error => 'Remote server has been shut down.'
227
- # end
228
- end
229
-
230
- def show( page, layout = true )
231
- if page == :dispatchers
232
- ensure_dispatcher
233
- erb :dispatchers, { :layout => true }, :stats => dispatcher_stats
234
- else
235
- erb page.to_sym, { :layout => layout }
236
- end
237
- end
238
-
239
- def welcomed?
240
- File.exist?( settings.db + '/welcomed' )
241
- end
242
-
243
- def welcomed!
244
- File.new( settings.db + '/welcomed', 'w' ).close
245
- end
246
-
247
- def ensure_welcomed
248
- return if welcomed?
249
-
250
- welcomed!
251
- redirect '/welcome'
252
- end
253
-
254
- def options
255
- Arachni::Options.instance
256
- end
257
-
258
- #
259
- # Similar to String.to_i but it returns the original object if String is not a number
260
- #
261
- def to_i( str )
262
- return str if !str.is_a?( String )
263
-
264
- if str.match( /\d+/ ).to_s.size == str.size
265
- return str.to_i
266
- else
267
- return str
268
- end
269
- end
270
-
271
- #
272
- # Prepares form params to be used as options for XMLRPC transmission
273
- #
274
- # @param [Hash] params
275
- #
276
- # @return [Hash] normalized hash
277
- #
278
- def prep_opts( params )
279
-
280
- need_to_split = [
281
- 'exclude_cookies',
282
- 'exclude',
283
- 'include'
284
- ]
285
-
286
- cparams = {}
287
- params.each_pair {
288
- |name, value|
289
-
290
- next if [ '_csrf', 'modules', 'plugins' ].include?( name ) || ( value.is_a?( String ) && value.empty?)
291
-
292
- value = true if value == 'on'
293
-
294
- if name == 'cookiejar'
295
- cparams['cookies'] = Arachni::HTTP.parse_cookiejar( value[:tempfile] )
296
- elsif need_to_split.include?( name ) && value.is_a?( String )
297
- cparams[name] = value.split( "\r\n" )
298
-
299
- elsif name == 'redundant'
300
- cparams[name] = []
301
- value.split( "\r\n" ).each {
302
- |rule|
303
- regexp, counter = rule.split( ':', 2 )
304
- cparams[name] << {
305
- 'regexp' => regexp,
306
- 'count' => counter
307
- }
308
- }
309
- else
310
- cparams[name] = to_i( value )
311
- end
312
- }
313
-
314
- if !cparams['audit_links'] && !cparams['audit_forms'] &&
315
- !cparams['audit_cookies'] && !cparams['audit_headers']
316
-
317
- cparams['audit_links'] = true
318
- cparams['audit_forms'] = true
319
- cparams['audit_cookies'] = true
320
- end
321
-
322
- return cparams
323
- end
324
-
325
- def prep_modules( params )
326
- return ['-'] if !params['modules']
327
- mods = params['modules'].keys
328
- return ['*'] if mods.empty?
329
- return mods
330
- end
331
-
332
- def prep_plugins( params )
333
- plugins = {}
334
-
335
- return plugins if !params['plugins']
336
- params['plugins'].keys.each {
337
- |name|
338
- plugins[name] = params['options'][name] || {}
339
- }
340
-
341
- return plugins
342
- end
343
-
344
- def helper_instance
345
- begin
346
- @@arachni ||= nil
347
- if !@@arachni
348
-
349
- d_url = dispatchers.first_alive.url
350
-
351
- instance = dispatchers.connect( d_url ).dispatch( HELPER_OWNER )
352
- instance_url = instances.port_to_url( instance['port'], d_url )
353
-
354
- @@arachni = instances.connect( instance_url, session, instance['token'] )
355
- end
356
-
357
- return @@arachni
358
- rescue Exception => e
359
- # ap e
360
- # ap e.backtrace
361
- redirect '/dispatchers/edit'
362
- end
363
- end
364
-
365
- def component_cache_filled?
366
- begin
367
- return @@modules.size + @@plugins.size
368
- rescue
369
- return false
370
- end
371
- end
372
-
373
- def fill_component_cache
374
-
375
- if !component_cache_filled?
376
- do_shutdown = true
377
- else
378
- do_shutdown = false
379
- end
380
-
381
- @@modules ||= helper_instance.framework.lsmod.dup
382
- @@plugins ||= helper_instance.framework.lsplug.dup
383
-
384
- # shutdown the helper instance, we got what we wanted
385
- helper_instance.service.shutdown! if do_shutdown
386
- end
387
-
388
- #
389
- # Makes sure that all systems are go and populates the session with default values
390
- #
391
- def prep_session
392
- ensure_dispatcher
393
-
394
- session['opts'] ||= {}
395
- session['opts']['settings'] ||= {
396
- 'audit_links' => true,
397
- 'audit_forms' => true,
398
- 'audit_cookies' => true,
399
- 'http_req_limit' => 20,
400
- 'user_agent' => 'Arachni/' + Arachni::VERSION
401
- }
402
- session['opts']['modules'] ||= [ '*' ]
403
- session['opts']['plugins'] ||= YAML::dump( {
404
- 'content_types' => {},
405
- 'healthmap' => {},
406
- 'metamodules' => {}
407
- } )
408
-
409
-
410
- #
411
- # Garbage collector, zombie killer. Reaps idle processes every 5 seconds.
412
- #
413
- @@reaper ||= Thread.new {
414
- while( true )
415
- shutdown_zombies
416
- ::IO::select( nil, nil, nil, 5 )
417
- end
418
- }
419
-
420
- end
421
-
422
- #
423
- # Makes sure that we have a dispatcher, if not it redirects the user to
424
- # an appropriate error page.
425
- #
426
- # @return [Bool] true if alive, redirect if not
427
- #
428
- def ensure_dispatcher
429
- redirect '/dispatchers/edit' if !dispatchers.first_alive
430
- end
431
-
432
- #
433
- # Saves the report, shuts down the instance and returns the content as HTML
434
- # to be sent back to the user's browser.
435
- #
436
- # @param [Arachni::RPC::XML::Client::Instance] arachni
437
- #
438
- def save_shutdown_and_show( arachni )
439
- report = save_and_shutdown( arachni )
440
- reports.get( 'html', reports.all.last.id )
441
- end
442
-
443
- #
444
- # Saves the report and shuts down the instance
445
- #
446
- # @param [Arachni::RPC::XML::Client::Instance] arachni
447
- #
448
- def save_and_shutdown( arachni )
449
- arachni.framework.clean_up!( true )
450
- report_path = reports.save( arachni.framework.auditstore )
451
- arachni.service.shutdown!
452
- return report_path
453
- end
454
-
455
- #
456
- # Kills all running instances
457
- #
458
- def shutdown_all( url )
459
- log.dispatcher_global_shutdown( env, url )
460
-
461
- dispatcher_stats.each_pair {
462
- |d_url, stats|
463
-
464
- next if remove_proto( d_url.dup ) != url
465
-
466
- stats['running_jobs'].each {
467
- |job|
468
-
469
- instance_url = instances.port_to_url( job['port'], d_url )
470
- begin
471
- save_and_shutdown( instances.connect( instance_url, session ) )
472
- rescue
473
- begin
474
- instances.connect( instance_url, session ).service.shutdown!
475
- rescue
476
- log.instance_fucker_wont_die( env, instance_url )
477
- next
478
- end
479
- end
480
-
481
- log.instance_shutdown( env, instance_url )
482
- }
483
- }
484
-
485
- end
486
-
487
- #
488
- # Kills all idle instances
489
- #
490
- # @return [Integer] the number of reaped instances
491
- #
492
- def shutdown_zombies
493
- i = 0
494
-
495
- dispatcher_stats.each_pair {
496
- |url, stats|
497
-
498
- stats['running_jobs'].each {
499
- |job|
500
-
501
- begin
502
- instance_url = instances.port_to_url( job['port'], url )
503
- arachni = instances.connect( instance_url, session )
504
-
505
- begin
506
- if !arachni.framework.busy? && !job['owner'] != HELPER_OWNER
507
- save_and_shutdown( arachni )
508
- log.webui_zombie_cleanup( env, instance_url )
509
- i+=1
510
- end
511
- rescue
512
- end
513
-
514
- rescue
515
- end
516
- }
517
- }
518
-
519
- return i
520
- end
521
-
522
- get "/" do
523
- prep_session
524
- ensure_welcomed
525
- show :home
526
- end
527
-
528
- get "/welcome" do
529
- erb :welcome, { :layout => true }
530
- end
531
-
532
- get "/dispatchers" do
533
- show :dispatchers
534
- end
535
-
536
- #
537
- # sets the dispatcher URL
538
- #
539
- post "/dispatchers" do
540
-
541
- if !params['url'] || params['url'].empty?
542
- flash[:err] = "URL cannot be empty."
543
- show :dispatchers_edit
544
- else
545
- log.dispatcher_selected( env, params['url'] )
546
- begin
547
- dispatchers.connect( url ).jobs
548
- log.dispatcher_verified( env, params['url'] )
549
- redirect '/'
550
- rescue
551
- log.dispatcher_error( env, params['url'] )
552
- flash[:err] = "Couldn't find a dispatcher at \"#{escape( params['url'] )}\"."
553
- show :dispatchers_edit
554
- end
555
- end
556
- end
557
-
558
- get '/dispatchers/edit' do
559
- show :dispatchers_edit
560
- end
561
-
562
- post '/dispatchers/add' do
563
-
564
- if dispatchers.alive?( params[:url] )
565
- dispatchers.new( params[:url] )
566
- else
567
- flash[:err] = "Couldn't find a dispatcher at \"#{escape( params['url'] )}\"."
568
- end
569
-
570
- show :dispatchers_edit
571
- end
572
-
573
- post '/dispatchers/:url/delete' do
574
- dispatchers.delete( params[:url] )
575
- show :dispatchers_edit
576
- end
577
-
578
-
579
- #
580
- # shuts down all instances
581
- #
582
- post "/dispatchers/:url/shutdown_all" do
583
- shutdown_all( params[:url] )
584
- redirect '/dispatchers'
585
- end
586
-
587
-
588
- get '/dispatchers/error' do
589
- show :dispatchers_edit
590
- end
591
-
592
- #
593
- # starts a scan
594
- #
595
- post "/scan" do
596
-
597
- valid = true
598
- begin
599
- URI.parse( params['url'] )
600
- rescue
601
- valid = false
602
- end
603
-
604
- if !params['url'] || params['url'].empty?
605
- flash[:err] = "URL cannot be empty."
606
- show :home
607
- elsif !valid
608
- flash[:err] = "Invalid URL."
609
- show :home
610
- elsif !params['dispatcher'] || params['dispatcher'].empty?
611
- flash[:err] = "Please select a Dispatcher."
612
- show :home
613
- else
614
-
615
- session['opts']['settings']['url'] = params[:url]
616
-
617
- unescape_hash( session['opts'] )
618
- session['opts']['settings']['audit_links'] = true if session['opts']['settings']['audit_links']
619
- session['opts']['settings']['audit_forms'] = true if session['opts']['settings']['audit_forms']
620
- session['opts']['settings']['audit_cookies'] = true if session['opts']['settings']['audit_cookies']
621
- session['opts']['settings']['audit_headers'] = true if session['opts']['settings']['audit_headers']
622
-
623
- opts = {}
624
- opts['settings'] = prep_opts( session['opts']['settings'] )
625
- opts['plugins'] = YAML::load( session['opts']['plugins'] )
626
- opts['modules'] = session['opts']['modules']
627
-
628
- job = Scheduler::Job.new(
629
- :dispatcher => params[:dispatcher],
630
- :url => params[:url],
631
- :opts => opts.to_yaml,
632
- :owner_addr => env['REMOTE_ADDR'],
633
- :owner_host => env['REMOTE_HOST'],
634
- :created_at => Time.now
635
- )
636
-
637
- instance_url = scheduler.run( job, env, session )
638
- redirect '/instance/' + instance_url.to_s.gsub( 'https://', '' )
639
- end
640
- end
641
-
642
- get "/modules" do
643
- fill_component_cache
644
- prep_session
645
- show :modules, true
646
- end
647
-
648
- #
649
- # sets modules
650
- #
651
- post "/modules" do
652
- session['opts']['modules'] = prep_modules( escape_hash( params ) )
653
- flash.now[:ok] = "Modules updated."
654
- show :modules, true
655
- end
656
-
657
- get "/plugins" do
658
- fill_component_cache
659
- prep_session
660
- erb :plugins, { :layout => true }, :session_options => YAML::load( session['opts']['plugins'] )
661
- end
662
-
663
- #
664
- # sets plugins
665
- #
666
- post "/plugins" do
667
- session['opts']['plugins'] = YAML::dump( prep_plugins( escape_hash( params ) ) )
668
- flash.now[:ok] = "Plugins updated."
669
- erb :plugins, { :layout => true }, :session_options => YAML::load( session['opts']['plugins'] )
670
- end
671
-
672
- get "/settings" do
673
- prep_session
674
- erb :settings, { :layout => true }
675
- end
676
-
677
- #
678
- # sets general framework settings
679
- #
680
- post "/settings" do
681
-
682
- if session['opts']['settings']['url']
683
- url = session['opts']['settings']['url'].dup
684
- end
685
-
686
- session['opts']['settings'] = prep_opts( escape_hash( params ) )
687
-
688
- if session['opts']['settings']['url']
689
- session['opts']['settings']['url'] = url
690
- end
691
-
692
- flash.now[:ok] = "Settings updated."
693
- show :settings, true
694
- end
695
-
696
- get "/instance/:url" do
697
- begin
698
- arachni = instances.connect( params[:url], session )
699
- erb :instance, { :layout => true }, :paused => arachni.framework.paused?, :shutdown => false
700
- rescue Exception => e
701
- flash.now[:notice] = "Instance at #{params[:url]} has been shutdown."
702
- erb :instance, { :layout => true }, :shutdown => true
703
- end
704
-
705
- end
706
-
707
- get "/instance/:url/output.json" do
708
- content_type :json
709
-
710
- begin
711
- arachni = instances.connect( params[:url], session )
712
- if arachni.framework.busy?
713
- @@output_streams ||= {}
714
- @@output_streams[params[:url]] ||= OutputStream.new( arachni, 38 )
715
- { 'data' => @@output_streams[params[:url]].data }.to_json
716
- else
717
- log.instance_shutdown( env, params[:url] )
718
- save_and_shutdown( arachni )
719
- { 'status' => 'finished', 'data' => "The server has been shut down." }.to_json
720
- end
721
- rescue IOError, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
722
- Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
723
- { 'data' => "<strong>Connection error, retrying...</strong>" }.to_json
724
- rescue Exception => e
725
- { 'status' => 'finished', 'data' => "The server has been shut down." }.to_json
726
- end
727
- end
728
-
729
- get "/instance/:url/output_results.json" do
730
- content_type :json
731
- begin
732
- arachni = instances.connect( params[:url], session )
733
- if !arachni.framework.paused? && arachni.framework.busy?
734
- out = erb( :output_results, { :layout => false }, :issues => YAML.load( arachni.framework.auditstore ).issues )
735
- { 'data' => out }.to_json
736
- end
737
- rescue IOError, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
738
- Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
739
- { 'data' => "<strong>Connection error, retrying...</strong>" }.to_json
740
- rescue Exception => e
741
- { 'data' => "The server has been shut down." }.to_json
742
- end
743
- end
744
-
745
- get "/instance/:url/stats.json" do
746
- content_type :json
747
- begin
748
- arachni = instances.connect( params[:url], session )
749
- stats = arachni.framework.stats( true )
750
- stats['current_page'] = escape( stats['current_page'] )
751
- { 'refresh' => true, 'stats' => stats }.to_json
752
- rescue
753
- { 'refresh' => false }.to_json
754
- end
755
- end
756
-
757
-
758
- post "/*/:url/pause" do
759
- arachni = instances.connect( params[:url], session )
760
-
761
- begin
762
- arachni.framework.pause!
763
- log.instance_paused( env, params[:url] )
764
-
765
- flash.now[:notice] = "Instance at #{params[:url]} will pause as soon as the current page is audited."
766
- erb params[:splat][0].to_sym, { :layout => true }, :paused => arachni.framework.paused?, :shutdown => false, :stats => dispatcher_stats
767
- rescue
768
- flash.now[:notice] = "Instance at #{params[:url]} has been shutdown."
769
- erb params[:splat][0].to_sym, { :layout => true }, :shutdown => true, :stats => dispatcher_stats
770
- end
771
-
772
- end
773
-
774
- post "/*/:url/resume" do
775
- arachni = instances.connect( params[:url], session )
776
-
777
- begin
778
- arachni.framework.resume!
779
- log.instance_resumed( env, params[:url] )
780
-
781
- flash.now[:notice] = "Instance at #{params[:url]} resumes."
782
- erb params[:splat][0].to_sym, { :layout => true }, :paused => arachni.framework.paused?, :shutdown => false, :stats => dispatcher_stats
783
- rescue
784
- flash.now[:notice] = "Instance at #{params[:url]} has been shutdown."
785
- erb params[:splat][0].to_sym, { :layout => true }, :shutdown => true, :stats => dispatcher_stats
786
- end
787
- end
788
-
789
- post "/*/:url/shutdown" do
790
- arachni = instances.connect( params[:url], session )
791
-
792
- begin
793
- arachni.framework.busy?
794
- log.instance_shutdown( env, params[:url] )
795
-
796
- begin
797
- save_shutdown_and_show( arachni )
798
- rescue
799
- flash.now[:notice] = "Instance at #{params[:url]} has been shutdown."
800
- show params[:splat][0].to_sym
801
- ensure
802
- arachni.service.shutdown!
803
- end
804
- rescue
805
- flash.now[:notice] = "Instance at #{params[:url]} has been shutdown."
806
- erb params[:splat][0].to_sym, { :layout => true }, :shutdown => true, :stats => dispatcher_stats
807
- end
808
- end
809
-
810
- get "/reports" do
811
- erb :reports, { :layout => true }, :reports => reports.all( :order => :datestamp.desc ),
812
- :available => reports.available
813
- end
814
-
815
- get '/reports/formats' do
816
- erb :report_formats, { :layout => true }, :reports => reports.available
817
- end
818
-
819
- post '/reports/delete' do
820
- reports.delete_all
821
- log.reports_deleted( env )
822
-
823
- redirect '/reports'
824
- end
825
-
826
- post '/report/:id/delete' do
827
- reports.delete( params[:id] )
828
- log.report_deleted( env, params[:id] )
829
-
830
- redirect '/reports'
831
- end
832
-
833
- get '/report/:id.:type' do
834
- log.report_converted( env, params[:id] + '.' + params[:type] )
835
- content_type( params[:type], :default => 'application/octet-stream' )
836
- reports.get( params[:type], params[:id] )
837
- end
838
-
839
- get '/log' do
840
- erb :log, { :layout => true }, :entries => log.entry.all.reverse
841
- end
842
-
843
- get '/addons' do
844
- erb :addons
845
- end
846
-
847
- post '/addons' do
848
- params['addons'] ||= {}
849
- addon_names = params['addons'].keys
850
-
851
- addons.enable!( addon_names )
852
- erb :addons
853
- end
854
-
855
-
856
- # override run! using this patch: https://github.com/sinatra/sinatra/pull/132
857
- def self.run!( options = {} )
858
- set options
859
-
860
- handler = detect_rack_handler
861
- handler_name = handler.name.gsub( /.*::/, '' )
862
-
863
- # handler specific options use the lower case handler name as hash key, if present
864
- handler_opts = options[handler_name.downcase.to_sym] || {}
865
-
866
- puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " +
867
- "on #{port} for #{environment} with backup from #{handler_name}" unless handler_name =~/cgi/i
868
-
869
- handler.run self, handler_opts.merge( :Host => bind, :Port => port ) do |server|
870
- [ :INT, :TERM ].each { |sig| trap( sig ) { quit!( server, handler_name ) } }
871
-
872
- set :running, true
873
- end
874
- rescue Errno::EADDRINUSE => e
875
- puts "== Someone is already performing on port #{port}!"
876
- end
877
-
878
- def self.prep_webrick
879
- if @@conf['ssl']['server']['key']
880
- pkey = ::OpenSSL::PKey::RSA.new( File.read( @@conf['ssl']['server']['key'] ) )
881
- end
882
-
883
- if @@conf['ssl']['server']['cert']
884
- cert = ::OpenSSL::X509::Certificate.new( File.read( @@conf['ssl']['server']['cert'] ) )
885
- end
886
-
887
- if @@conf['ssl']['key'] || @@conf['ssl']['cert'] || @@conf['ssl']['ca']
888
- verification = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
889
- else
890
- verification = ::OpenSSL::SSL::VERIFY_NONE
891
- end
892
-
893
- return {
894
- :SSLEnable => @@conf['ssl']['server']['enable'] || false,
895
- :SSLVerifyClient => verification,
896
- :SSLCertName => [ [ "CN", Arachni::Options.instance.server || ::WEBrick::Utils::getservername ] ],
897
- :SSLCertificate => cert,
898
- :SSLPrivateKey => pkey,
899
- :SSLCACertificateFile => @@conf['ssl']['server']['ca']
900
- }
901
- end
902
-
903
- run! :host => Arachni::Options.instance.server || ::WEBrick::Utils::getservername,
904
- :port => Arachni::Options.instance.rpc_port || 4567,
905
- :server => %w[ webrick ],
906
- :webrick => prep_webrick
907
-
908
- at_exit do
909
-
910
- log.webui_shutdown
911
-
912
- begin
913
- # shutdown our helper instance
914
- @@arachni ||= nil
915
- @@arachni.service.shutdown! if @@arachni
916
- rescue
917
- end
918
-
919
- end
920
-
921
- end
922
-
923
- end
924
- end
925
- end