arachni 0.4.0.4 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (688) hide show
  1. data/ACKNOWLEDGMENTS.md +2 -2
  2. data/AUTHORS.md +1 -4
  3. data/CHANGELOG.md +102 -3
  4. data/CONTRIBUTORS.md +4 -1
  5. data/EXPLOITATION.md +6 -6
  6. data/Gemfile +3 -0
  7. data/HACKING.md +29 -10
  8. data/LICENSE.md +176 -339
  9. data/NOTICE +12 -0
  10. data/README.md +160 -119
  11. data/Rakefile +83 -45
  12. data/arachni.gemspec +124 -0
  13. data/bin/arachni +14 -8
  14. data/bin/arachni_console +52 -0
  15. data/bin/arachni_rpc +14 -8
  16. data/bin/arachni_rpcd +15 -9
  17. data/bin/arachni_rpcd_monitor +14 -8
  18. data/bin/arachni_script +41 -0
  19. data/bin/arachni_web +18 -19
  20. data/bin/arachni_web_autostart +17 -18
  21. data/external/metasploit/plugins/arachni.rb +7 -9
  22. data/external/metasploit/{LICENSE → plugins/arachni/LICENSE} +0 -0
  23. data/external/metasploit/{modules → plugins/arachni/modules}/exploits/unix/webapp/arachni_exec.rb +1 -1
  24. data/external/metasploit/{modules → plugins/arachni/modules}/exploits/unix/webapp/arachni_path_traversal.rb +2 -2
  25. data/external/metasploit/{modules → plugins/arachni/modules}/exploits/unix/webapp/arachni_php_eval.rb +1 -1
  26. data/external/metasploit/{modules → plugins/arachni/modules}/exploits/unix/webapp/arachni_php_include.rb +1 -1
  27. data/external/metasploit/{modules → plugins/arachni/modules}/exploits/unix/webapp/arachni_sqlmap.rb +2 -2
  28. data/external/scripts/LICENSE.tpl +174 -0
  29. data/external/scripts/README.md +95 -0
  30. data/external/scripts/README.tpl +30 -0
  31. data/external/scripts/build.sh +631 -0
  32. data/external/scripts/build_all.sh +29 -0
  33. data/external/scripts/build_and_package.sh +100 -0
  34. data/external/scripts/cross_build_and_package.sh +20 -0
  35. data/external/scripts/installer.sh.tpl +166 -0
  36. data/external/scripts/lib/readlink_f.sh +40 -0
  37. data/external/scripts/package.sh +134 -0
  38. data/external/scripts/push_nightlies.sh +125 -0
  39. data/extras/placeholder +0 -0
  40. data/gfx/README.md +18 -0
  41. data/gfx/compiled/banner.png +0 -0
  42. data/gfx/compiled/favicon.ico +0 -0
  43. data/gfx/compiled/icon.png +0 -0
  44. data/gfx/compiled/logo.png +0 -0
  45. data/gfx/compiled/spider.png +0 -0
  46. data/gfx/font/Beneath_the_Surface.ttf +0 -0
  47. data/gfx/font/bts_readme.txt +14 -0
  48. data/gfx/source/banner.svg +999 -0
  49. data/gfx/source/icon.svg +627 -0
  50. data/gfx/source/logo.svg +672 -0
  51. data/gfx/source/spider.png +0 -0
  52. data/gfx/source/spider.svg +277 -0
  53. data/lib/arachni.rb +30 -5
  54. data/lib/arachni/audit_store.rb +111 -143
  55. data/lib/arachni/banner.rb +37 -0
  56. data/lib/arachni/bloom_filter.rb +74 -0
  57. data/lib/arachni/cache.rb +21 -0
  58. data/lib/arachni/cache/base.rb +170 -0
  59. data/lib/arachni/cache/least_cost_replacement.rb +89 -0
  60. data/lib/arachni/cache/least_recently_used.rb +73 -0
  61. data/lib/arachni/cache/random_replacement.rb +52 -0
  62. data/lib/arachni/component/manager.rb +391 -0
  63. data/lib/arachni/component/options.rb +38 -0
  64. data/lib/arachni/component/options/address.rb +41 -0
  65. data/lib/arachni/component/options/base.rb +126 -0
  66. data/lib/arachni/component/options/bool.rb +55 -0
  67. data/lib/arachni/component/options/enum.rb +51 -0
  68. data/lib/arachni/component/options/float.rb +45 -0
  69. data/lib/arachni/component/options/int.rb +44 -0
  70. data/lib/arachni/component/options/path.rb +36 -0
  71. data/lib/arachni/component/options/port.rb +37 -0
  72. data/lib/arachni/component/options/string.rb +44 -0
  73. data/lib/arachni/component/options/url.rb +42 -0
  74. data/lib/arachni/crypto/rsa_aes_cbc.rb +14 -8
  75. data/lib/arachni/database.rb +4 -4
  76. data/lib/arachni/database/base.rb +14 -8
  77. data/lib/arachni/database/hash.rb +21 -12
  78. data/lib/arachni/database/queue.rb +15 -9
  79. data/lib/arachni/element/base.rb +147 -0
  80. data/lib/arachni/element/capabilities/auditable.rb +623 -0
  81. data/lib/arachni/element/capabilities/auditable/rdiff.rb +243 -0
  82. data/lib/arachni/element/capabilities/auditable/taint.rb +141 -0
  83. data/lib/arachni/element/capabilities/auditable/timeout.rb +330 -0
  84. data/lib/arachni/element/capabilities/body.rb +19 -0
  85. data/lib/arachni/element/capabilities/mutable.rb +286 -0
  86. data/lib/arachni/element/capabilities/path.rb +19 -0
  87. data/lib/arachni/element/capabilities/refreshable.rb +48 -0
  88. data/lib/arachni/element/capabilities/server.rb +19 -0
  89. data/lib/arachni/element/cookie.rb +1043 -0
  90. data/lib/arachni/element/form.rb +1364 -0
  91. data/lib/arachni/element/header.rb +87 -0
  92. data/lib/arachni/element/link.rb +227 -0
  93. data/lib/arachni/exceptions.rb +12 -34
  94. data/lib/arachni/framework.rb +345 -436
  95. data/lib/arachni/http.rb +445 -409
  96. data/lib/arachni/http/cookie_jar.rb +163 -0
  97. data/lib/arachni/issue.rb +102 -65
  98. data/lib/arachni/mixins/observable.rb +25 -28
  99. data/lib/arachni/mixins/progress_bar.rb +11 -5
  100. data/lib/arachni/mixins/terminal.rb +17 -11
  101. data/lib/arachni/module.rb +4 -4
  102. data/lib/arachni/module/auditor.rb +270 -793
  103. data/lib/arachni/module/base.rb +107 -101
  104. data/lib/arachni/module/element_db.rb +54 -59
  105. data/lib/arachni/module/key_filler.rb +35 -35
  106. data/lib/arachni/module/manager.rb +178 -68
  107. data/lib/arachni/module/output.rb +25 -30
  108. data/lib/arachni/module/trainer.rb +85 -156
  109. data/lib/arachni/module/utilities.rb +29 -138
  110. data/lib/arachni/options.rb +496 -162
  111. data/lib/arachni/page.rb +186 -0
  112. data/lib/arachni/parser.rb +392 -2
  113. data/lib/arachni/plugin.rb +4 -4
  114. data/lib/arachni/plugin/base.rb +113 -44
  115. data/lib/arachni/plugin/manager.rb +120 -54
  116. data/lib/arachni/report.rb +4 -4
  117. data/lib/arachni/report/base.rb +59 -44
  118. data/lib/arachni/report/manager.rb +33 -32
  119. data/lib/arachni/rpc/client.rb +2 -0
  120. data/lib/arachni/rpc/client/base.rb +31 -18
  121. data/lib/arachni/rpc/client/dispatcher.rb +24 -11
  122. data/lib/arachni/rpc/client/instance.rb +24 -11
  123. data/lib/arachni/rpc/server/base.rb +12 -9
  124. data/lib/arachni/rpc/server/dispatcher.rb +161 -164
  125. data/lib/arachni/rpc/server/dispatcher/handler.rb +164 -0
  126. data/lib/arachni/rpc/server/{node.rb → dispatcher/node.rb} +86 -104
  127. data/lib/arachni/rpc/server/distributor.rb +432 -0
  128. data/lib/arachni/rpc/server/framework.rb +266 -758
  129. data/lib/arachni/rpc/server/instance.rb +38 -53
  130. data/lib/arachni/rpc/server/module/manager.rb +17 -20
  131. data/lib/arachni/rpc/server/output.rb +73 -179
  132. data/lib/arachni/rpc/server/plugin/manager.rb +58 -24
  133. data/lib/arachni/ruby.rb +6 -4
  134. data/lib/arachni/ruby/array.rb +30 -9
  135. data/lib/arachni/ruby/enumerable.rb +29 -0
  136. data/lib/arachni/ruby/object.rb +47 -12
  137. data/lib/arachni/ruby/string.rb +69 -24
  138. data/lib/arachni/ruby/webrick.rb +31 -0
  139. data/lib/arachni/session.rb +279 -0
  140. data/lib/arachni/spider.rb +295 -149
  141. data/lib/arachni/typhoeus/hydra.rb +18 -4
  142. data/lib/arachni/typhoeus/request.rb +52 -65
  143. data/lib/arachni/typhoeus/response.rb +62 -22
  144. data/lib/arachni/typhoeus/utils.rb +25 -0
  145. data/lib/arachni/ui/cli/cli.rb +331 -298
  146. data/lib/arachni/ui/cli/output.rb +105 -77
  147. data/lib/arachni/ui/foo/output.rb +116 -0
  148. data/lib/arachni/ui/rpc/dispatcher_monitor.rb +5 -12
  149. data/lib/arachni/ui/rpc/rpc.rb +43 -48
  150. data/lib/arachni/ui/web/addon_manager.rb +18 -13
  151. data/lib/arachni/ui/web/addons/sample.rb +14 -8
  152. data/lib/arachni/ui/web/addons/scheduler.rb +14 -8
  153. data/lib/arachni/ui/web/addons/scheduler/views/index.erb +1 -1
  154. data/lib/arachni/ui/web/addons/scheduler/views/options.erb +0 -3
  155. data/lib/arachni/ui/web/dispatcher_manager.rb +14 -9
  156. data/lib/arachni/ui/web/instance_manager.rb +14 -8
  157. data/lib/arachni/ui/web/log.rb +14 -10
  158. data/lib/arachni/ui/web/output_stream.rb +11 -5
  159. data/lib/arachni/ui/web/report_manager.rb +14 -10
  160. data/lib/arachni/ui/web/scheduler.rb +16 -11
  161. data/lib/arachni/ui/web/server.rb +62 -56
  162. data/lib/arachni/ui/web/server/public/style.css +1 -1
  163. data/lib/arachni/ui/web/server/views/addon.erb +1 -1
  164. data/lib/arachni/ui/web/server/views/dispatchers.erb +3 -3
  165. data/lib/arachni/ui/web/server/views/dispatchers_edit.erb +2 -2
  166. data/lib/arachni/ui/web/server/views/error.erb +1 -1
  167. data/lib/arachni/ui/web/server/views/home.erb +2 -2
  168. data/lib/arachni/ui/web/server/views/instance.erb +6 -6
  169. data/lib/arachni/ui/web/server/views/layout.erb +4 -4
  170. data/lib/arachni/ui/web/server/views/settings.erb +13 -8
  171. data/lib/arachni/ui/web/server/views/welcome.erb +1 -1
  172. data/lib/arachni/ui/web/utilities.rb +24 -35
  173. data/lib/arachni/uri.rb +619 -0
  174. data/lib/arachni/utilities.rb +316 -0
  175. data/lib/arachni/version.rb +12 -6
  176. data/lib/version +1 -0
  177. data/modules/audit/code_injection.rb +64 -81
  178. data/modules/audit/code_injection_timing.rb +57 -75
  179. data/modules/audit/csrf.rb +87 -185
  180. data/modules/audit/ldapi.rb +42 -67
  181. data/modules/audit/os_cmd_injection.rb +53 -71
  182. data/modules/audit/os_cmd_injection/payloads.txt +1 -1
  183. data/modules/audit/os_cmd_injection_timing.rb +54 -75
  184. data/modules/audit/os_cmd_injection_timing/payloads.txt +1 -3
  185. data/modules/audit/path_traversal.rb +84 -110
  186. data/modules/audit/response_splitting.rb +41 -53
  187. data/modules/audit/rfi.rb +68 -76
  188. data/modules/audit/session_fixation.rb +86 -0
  189. data/modules/audit/sqli.rb +51 -77
  190. data/modules/audit/sqli/regexp_ids.txt +5 -19
  191. data/modules/audit/sqli/regexp_ignore.txt +2 -0
  192. data/modules/audit/sqli_blind_rdiff.rb +51 -62
  193. data/modules/audit/sqli_blind_timing.rb +53 -73
  194. data/modules/audit/trainer.rb +21 -58
  195. data/modules/audit/unvalidated_redirect.rb +41 -51
  196. data/modules/audit/xpath.rb +38 -69
  197. data/modules/audit/xpath/errors.txt +2 -3
  198. data/modules/audit/xss.rb +65 -69
  199. data/modules/audit/xss_event.rb +50 -69
  200. data/modules/audit/xss_path.rb +63 -89
  201. data/modules/audit/xss_script_tag.rb +53 -66
  202. data/modules/audit/xss_tag.rb +46 -65
  203. data/modules/audit/xss_uri.rb +22 -24
  204. data/modules/recon/allowed_methods.rb +46 -62
  205. data/modules/recon/backdoors.rb +39 -66
  206. data/modules/recon/backup_files.rb +49 -79
  207. data/modules/recon/common_directories.rb +39 -63
  208. data/modules/recon/common_directories/directories.txt +0 -5
  209. data/modules/recon/common_files.rb +34 -63
  210. data/modules/recon/directory_listing.rb +66 -116
  211. data/modules/recon/grep/captcha.rb +34 -41
  212. data/modules/recon/grep/credit_card.rb +57 -68
  213. data/modules/recon/grep/cvs_svn_users.rb +40 -50
  214. data/modules/recon/grep/emails.rb +34 -41
  215. data/modules/recon/grep/html_objects.rb +30 -33
  216. data/modules/recon/grep/http_only_cookies.rb +57 -0
  217. data/modules/recon/grep/insecure_cookies.rb +55 -0
  218. data/modules/recon/grep/mixed_resource.rb +93 -0
  219. data/modules/recon/grep/private_ip.rb +34 -32
  220. data/modules/recon/grep/ssn.rb +33 -31
  221. data/modules/recon/grep/unencrypted_password_forms.rb +84 -0
  222. data/modules/recon/htaccess_limit.rb +38 -54
  223. data/modules/recon/http_put.rb +48 -62
  224. data/modules/recon/interesting_responses.rb +77 -79
  225. data/modules/recon/webdav.rb +53 -79
  226. data/modules/recon/xst.rb +44 -63
  227. data/modules/test2.rb +46 -0
  228. data/path_extractors/anchors.rb +17 -15
  229. data/path_extractors/forms.rb +17 -15
  230. data/path_extractors/frames.rb +17 -18
  231. data/path_extractors/generic.rb +52 -55
  232. data/path_extractors/links.rb +16 -14
  233. data/path_extractors/meta_refresh.rb +33 -18
  234. data/path_extractors/scripts.rb +17 -15
  235. data/plugins/autologin.rb +60 -85
  236. data/plugins/beep_notify.rb +25 -27
  237. data/plugins/cookie_collector.rb +28 -45
  238. data/plugins/defaults/autothrottle.rb +43 -51
  239. data/plugins/defaults/content_types.rb +63 -52
  240. data/plugins/defaults/healthmap.rb +45 -62
  241. data/plugins/defaults/{metamodules → meta}/remedies/discovery.rb +34 -69
  242. data/plugins/defaults/meta/remedies/manual_verification.rb +61 -0
  243. data/plugins/defaults/meta/remedies/timing_attacks.rb +108 -0
  244. data/plugins/defaults/meta/uniformity.rb +81 -0
  245. data/plugins/defaults/profiler.rb +68 -115
  246. data/plugins/defaults/resolver.rb +33 -28
  247. data/plugins/email_notify.rb +60 -62
  248. data/plugins/form_dicattack.rb +67 -121
  249. data/plugins/http_dicattack.rb +51 -65
  250. data/plugins/libnotify.rb +37 -41
  251. data/plugins/proxy.rb +407 -152
  252. data/plugins/proxy/panel/403_forbidden.html.erb +11 -0
  253. data/plugins/proxy/panel/404_not_found.html.erb +6 -0
  254. data/plugins/proxy/panel/css/bootstrap.min.css +9 -0
  255. data/plugins/proxy/panel/css/panel.css +30 -0
  256. data/plugins/proxy/panel/help.html.erb +66 -0
  257. data/plugins/proxy/panel/img/glyphicons-halflings-white.png +0 -0
  258. data/plugins/proxy/panel/img/glyphicons-halflings.png +0 -0
  259. data/plugins/proxy/panel/img/record.png +0 -0
  260. data/plugins/proxy/panel/inspect.html.erb +7 -0
  261. data/plugins/proxy/panel/js/bootstrap.min.js +6 -0
  262. data/plugins/proxy/panel/js/jquery.min.js +2 -0
  263. data/plugins/proxy/panel/js/panel.js +39 -0
  264. data/plugins/proxy/panel/layout.html.erb +25 -0
  265. data/plugins/proxy/panel/page_accordion.html.erb +67 -0
  266. data/plugins/proxy/panel/page_twin_accordion.html.erb +18 -0
  267. data/plugins/proxy/panel/panel.html.erb +63 -0
  268. data/plugins/proxy/panel/shutdown_message.html.erb +7 -0
  269. data/plugins/proxy/panel/verify_login_check.html.erb +31 -0
  270. data/plugins/proxy/panel/verify_login_final.html.erb +26 -0
  271. data/plugins/proxy/panel/verify_login_sequence.html.erb +45 -0
  272. data/plugins/proxy/server.rb +175 -47
  273. data/plugins/proxy/ssl-interceptor-cert.pem +34 -0
  274. data/plugins/proxy/ssl-interceptor-pkey.pem +51 -0
  275. data/plugins/rescan.rb +27 -28
  276. data/plugins/script.rb +53 -0
  277. data/plugins/vector_feed.rb +226 -0
  278. data/plugins/waf_detector.rb +70 -73
  279. data/reports/afr.rb +23 -24
  280. data/reports/ap.rb +25 -36
  281. data/reports/html.rb +109 -163
  282. data/reports/html/default.erb +13 -12
  283. data/reports/html/default/configuration.erb +21 -21
  284. data/reports/html/default/css/main.css +350 -350
  285. data/reports/html/default/issues.erb +1 -1
  286. data/reports/html/default/js/charts.js +2 -2
  287. data/reports/html/default/js/helpers.js +0 -42
  288. data/reports/html/default/js/init.js +0 -1
  289. data/reports/html/default/sitemap.erb +2 -2
  290. data/reports/html/default/summary.erb +4 -4
  291. data/reports/html/default/summary_issue.erb +1 -1
  292. data/reports/json.rb +26 -28
  293. data/reports/marshal.rb +23 -25
  294. data/reports/metareport.rb +65 -98
  295. data/reports/plugin_formatters/html/autologin.rb +34 -41
  296. data/reports/plugin_formatters/html/content_types.rb +46 -52
  297. data/reports/plugin_formatters/html/cookie_collector.rb +41 -47
  298. data/reports/plugin_formatters/html/discovery.rb +36 -41
  299. data/reports/plugin_formatters/html/form_dicattack.rb +28 -34
  300. data/reports/plugin_formatters/html/healthmap.rb +48 -55
  301. data/reports/plugin_formatters/html/http_dicattack.rb +28 -34
  302. data/reports/plugin_formatters/html/profiler.rb +26 -30
  303. data/reports/plugin_formatters/html/profiler/template.erb +7 -7
  304. data/reports/plugin_formatters/html/resolver.rb +44 -52
  305. data/reports/plugin_formatters/html/timing_attacks.rb +42 -44
  306. data/reports/plugin_formatters/html/uniformity.rb +37 -42
  307. data/reports/plugin_formatters/html/waf_detector.rb +26 -34
  308. data/reports/plugin_formatters/stdout/autologin.rb +28 -40
  309. data/reports/plugin_formatters/stdout/content_types.rb +36 -53
  310. data/reports/plugin_formatters/stdout/cookie_collector.rb +28 -41
  311. data/reports/plugin_formatters/stdout/discovery.rb +27 -37
  312. data/reports/plugin_formatters/stdout/form_dicattack.rb +22 -35
  313. data/reports/plugin_formatters/stdout/healthmap.rb +40 -57
  314. data/reports/plugin_formatters/stdout/http_dicattack.rb +22 -36
  315. data/reports/plugin_formatters/stdout/profiler.rb +55 -74
  316. data/reports/plugin_formatters/stdout/resolver.rb +18 -34
  317. data/reports/plugin_formatters/stdout/timing_attacks.rb +27 -39
  318. data/reports/plugin_formatters/stdout/uniformity.rb +32 -44
  319. data/reports/plugin_formatters/stdout/waf_detector.rb +20 -32
  320. data/reports/plugin_formatters/xml/autologin.rb +27 -49
  321. data/reports/plugin_formatters/xml/content_types.rb +41 -66
  322. data/reports/plugin_formatters/xml/cookie_collector.rb +29 -49
  323. data/reports/plugin_formatters/xml/discovery.rb +23 -41
  324. data/reports/plugin_formatters/xml/form_dicattack.rb +22 -40
  325. data/reports/plugin_formatters/xml/healthmap.rb +44 -63
  326. data/reports/plugin_formatters/xml/http_dicattack.rb +22 -41
  327. data/reports/plugin_formatters/xml/profiler.rb +65 -89
  328. data/reports/plugin_formatters/xml/resolver.rb +21 -41
  329. data/reports/plugin_formatters/xml/timing_attacks.rb +27 -45
  330. data/reports/plugin_formatters/xml/uniformity.rb +36 -55
  331. data/reports/plugin_formatters/xml/waf_detector.rb +23 -42
  332. data/reports/stdout.rb +120 -121
  333. data/reports/txt.rb +29 -45
  334. data/reports/xml.rb +109 -148
  335. data/reports/xml/buffer.rb +66 -79
  336. data/reports/yaml.rb +26 -28
  337. data/rpcd_handlers/placeholder +0 -0
  338. data/spec/arachni/audit_store_spec.rb +223 -0
  339. data/spec/arachni/bloom_filter_spec.rb +76 -0
  340. data/spec/arachni/cache/base_spec.rb +275 -0
  341. data/spec/arachni/cache/least_cost_replacement_spec.rb +58 -0
  342. data/spec/arachni/cache/least_recently_used_spec.rb +91 -0
  343. data/spec/arachni/cache/random_replacement_spec.rb +43 -0
  344. data/spec/arachni/component/manager_spec.rb +448 -0
  345. data/spec/arachni/component/options/address_spec.rb +32 -0
  346. data/spec/arachni/component/options/base_spec.rb +105 -0
  347. data/spec/arachni/component/options/bool_spec.rb +67 -0
  348. data/spec/arachni/component/options/enum_spec.rb +51 -0
  349. data/spec/arachni/component/options/float_spec.rb +42 -0
  350. data/spec/arachni/component/options/int_spec.rb +46 -0
  351. data/spec/arachni/component/options/path_spec.rb +32 -0
  352. data/spec/arachni/component/options/port_spec.rb +38 -0
  353. data/spec/arachni/component/options/string_spec.rb +38 -0
  354. data/spec/arachni/component/options/url_spec.rb +36 -0
  355. data/spec/arachni/crypto/rsa_aes_cbc_spec.rb +31 -0
  356. data/spec/arachni/database/hash_spec.rb +217 -0
  357. data/spec/arachni/database/queue_spec.rb +52 -0
  358. data/spec/arachni/element/base_spec.rb +127 -0
  359. data/spec/arachni/element/body_spec.rb +9 -0
  360. data/spec/arachni/element/capabilities/auditable/rdiff_spec.rb +47 -0
  361. data/spec/arachni/element/capabilities/auditable/taint_spec.rb +110 -0
  362. data/spec/arachni/element/capabilities/auditable/timeout_spec.rb +107 -0
  363. data/spec/arachni/element/capabilities/mutable_spec.rb +261 -0
  364. data/spec/arachni/element/cookie_spec.rb +362 -0
  365. data/spec/arachni/element/form_spec.rb +668 -0
  366. data/spec/arachni/element/header_spec.rb +49 -0
  367. data/spec/arachni/element/link_spec.rb +220 -0
  368. data/spec/arachni/element/path_spec.rb +9 -0
  369. data/spec/arachni/element/server_spec.rb +9 -0
  370. data/spec/arachni/framework_spec.rb +860 -0
  371. data/spec/arachni/http/cookie_jar_spec.rb +267 -0
  372. data/spec/arachni/http_spec.rb +991 -0
  373. data/spec/arachni/issue_spec.rb +307 -0
  374. data/spec/arachni/mixins/observable_spec.rb +59 -0
  375. data/spec/arachni/mixins/progress_bar_spec.rb +41 -0
  376. data/spec/arachni/module/auditor_spec.rb +506 -0
  377. data/spec/arachni/module/element_db_spec.rb +131 -0
  378. data/spec/arachni/module/key_filler.rb +15 -0
  379. data/spec/arachni/module/manager_spec.rb +154 -0
  380. data/spec/arachni/module/trainer_spec.rb +102 -0
  381. data/spec/arachni/module/utilities_spec.rb +30 -0
  382. data/spec/arachni/module/utilities_spec/read_file.txt +3 -0
  383. data/spec/arachni/options_spec.rb +555 -0
  384. data/spec/arachni/page_spec.rb +290 -0
  385. data/spec/arachni/parser_spec.rb +508 -0
  386. data/spec/arachni/plugin/manager_spec.rb +174 -0
  387. data/spec/arachni/report/base_spec.rb +53 -0
  388. data/spec/arachni/report/manager_spec.rb +82 -0
  389. data/spec/arachni/rpc/client/base_spec.rb +157 -0
  390. data/spec/arachni/rpc/client/dispatcher_spec.rb +40 -0
  391. data/spec/arachni/rpc/client/instance_spec.rb +92 -0
  392. data/spec/arachni/rpc/server/base_spec.rb +40 -0
  393. data/spec/arachni/rpc/server/dispatcher/handler.rb +120 -0
  394. data/spec/arachni/rpc/server/dispatcher/node_spec.rb +220 -0
  395. data/spec/arachni/rpc/server/dispatcher_spec.rb +136 -0
  396. data/spec/arachni/rpc/server/distributor_spec.rb +628 -0
  397. data/spec/arachni/rpc/server/framework_hpg_spec.rb +321 -0
  398. data/spec/arachni/rpc/server/framework_simple_spec.rb +453 -0
  399. data/spec/arachni/rpc/server/instance_spec.rb +81 -0
  400. data/spec/arachni/rpc/server/modules/manager_spec.rb +79 -0
  401. data/spec/arachni/rpc/server/options_spec.rb +124 -0
  402. data/spec/arachni/rpc/server/output_spec.rb +238 -0
  403. data/spec/arachni/rpc/server/plugin/manager_spec.rb +86 -0
  404. data/spec/arachni/ruby/array_spec.rb +103 -0
  405. data/spec/arachni/ruby/enumerable_spec.rb +37 -0
  406. data/spec/arachni/ruby/object_spec.rb +38 -0
  407. data/spec/arachni/ruby/string_spec.rb +77 -0
  408. data/spec/arachni/ruby/webrick_spec.rb +15 -0
  409. data/spec/arachni/session_spec.rb +308 -0
  410. data/spec/arachni/spider_spec.rb +383 -0
  411. data/spec/arachni/typhoeus/hydra_spec.rb +14 -0
  412. data/spec/arachni/typhoeus/requrest_spec.rb +58 -0
  413. data/spec/arachni/typhoeus/response_spec.rb +78 -0
  414. data/spec/arachni/uri_spec.rb +462 -0
  415. data/spec/arachni/utilities_spec.rb +297 -0
  416. data/spec/fixtures/auditstore.afr +2959 -0
  417. data/spec/fixtures/cookies.txt +9 -0
  418. data/spec/fixtures/modules/test.rb +58 -0
  419. data/spec/fixtures/modules/test2.rb +46 -0
  420. data/spec/fixtures/modules/test3.rb +46 -0
  421. data/spec/fixtures/passwords.txt +17 -0
  422. data/spec/fixtures/plugins/bad.rb +46 -0
  423. data/spec/fixtures/plugins/defaults/default.rb +45 -0
  424. data/spec/fixtures/plugins/distributable.rb +42 -0
  425. data/spec/fixtures/plugins/loop.rb +32 -0
  426. data/spec/fixtures/plugins/wait.rb +34 -0
  427. data/spec/fixtures/plugins/with_options.rb +31 -0
  428. data/spec/fixtures/reports/base_spec/plugin_formatters/with_formatters/foobar.rb +21 -0
  429. data/spec/fixtures/reports/base_spec/with_formatters.rb +23 -0
  430. data/spec/fixtures/reports/base_spec/with_outfile.rb +24 -0
  431. data/spec/fixtures/reports/base_spec/without_outfile.rb +20 -0
  432. data/spec/fixtures/reports/manager_spec/afr.rb +21 -0
  433. data/spec/fixtures/reports/manager_spec/foo.rb +26 -0
  434. data/spec/fixtures/rescan.afr.tpl +145 -0
  435. data/spec/fixtures/rpcd_handlers/echo.rb +68 -0
  436. data/spec/fixtures/run_mod/body.rb +58 -0
  437. data/spec/fixtures/run_mod/cookies.rb +58 -0
  438. data/spec/fixtures/run_mod/empty.rb +58 -0
  439. data/spec/fixtures/run_mod/flch.rb +63 -0
  440. data/spec/fixtures/run_mod/forms.rb +58 -0
  441. data/spec/fixtures/run_mod/headers.rb +58 -0
  442. data/spec/fixtures/run_mod/links.rb +58 -0
  443. data/spec/fixtures/run_mod/nil.rb +57 -0
  444. data/spec/fixtures/run_mod/path.rb +58 -0
  445. data/spec/fixtures/run_mod/server.rb +58 -0
  446. data/spec/fixtures/script_plugin.rb +1 -0
  447. data/spec/fixtures/taint_module/taint.rb +48 -0
  448. data/spec/fixtures/usernames.txt +13 -0
  449. data/spec/fixtures/wait_module/wait.rb +48 -0
  450. data/spec/helpers/auditor.rb +9 -0
  451. data/spec/helpers/misc.rb +41 -0
  452. data/spec/helpers/processes.rb +112 -0
  453. data/spec/helpers/requires.rb +8 -0
  454. data/spec/helpers/server.rb +54 -0
  455. data/spec/logs/Dispatcher - 2752-13830.log +49 -0
  456. data/spec/logs/Dispatcher - 2766-8238.log +35 -0
  457. data/spec/logs/Dispatcher - 2808-9029.log +31 -0
  458. data/spec/logs/Dispatcher - 2854-8571.log +26 -0
  459. data/spec/logs/Dispatcher - 2888-10411.log +20 -0
  460. data/spec/logs/Dispatcher - 2922-14464.log +13 -0
  461. data/spec/logs/Dispatcher - 2957-15255.log +19 -0
  462. data/spec/logs/Dispatcher - 3216-14203.log +35 -0
  463. data/spec/logs/Dispatcher - 3305-8622.log +43 -0
  464. data/spec/logs/Dispatcher - 3340-15426.log +35 -0
  465. data/spec/logs/Dispatcher - 3399-12586.log +40 -0
  466. data/spec/logs/Dispatcher - 3433-14149.log +26 -0
  467. data/spec/logs/Dispatcher - 3582-6198.log +27 -0
  468. data/spec/logs/Dispatcher - 3616-11169.log +13 -0
  469. data/spec/logs/Dispatcher - 3849-9016.log +7 -0
  470. data/spec/logs/output_spec.log +4 -0
  471. data/spec/logs/placeholder +0 -0
  472. data/spec/modules/audit/code_injection_spec.rb +25 -0
  473. data/spec/modules/audit/code_injection_timing_spec.rb +24 -0
  474. data/spec/modules/audit/csrf_spec.rb +38 -0
  475. data/spec/modules/audit/ldapi_spec.rb +19 -0
  476. data/spec/modules/audit/os_cmd_injection_spec.rb +24 -0
  477. data/spec/modules/audit/os_cmd_injection_timing_spec.rb +24 -0
  478. data/spec/modules/audit/path_traversal_spec.rb +23 -0
  479. data/spec/modules/audit/response_splitting_spec.rb +19 -0
  480. data/spec/modules/audit/rfi_spec.rb +19 -0
  481. data/spec/modules/audit/session_fixation_spec.rb +23 -0
  482. data/spec/modules/audit/sqli_blind_rdiff_spec.rb +19 -0
  483. data/spec/modules/audit/sqli_blind_timing_spec.rb +23 -0
  484. data/spec/modules/audit/sqli_spec.rb +24 -0
  485. data/spec/modules/audit/trainer_spec.rb +25 -0
  486. data/spec/modules/audit/unvalidated_redirect_spec.rb +24 -0
  487. data/spec/modules/audit/xpath_spec.rb +25 -0
  488. data/spec/modules/audit/xss_event_spec.rb +19 -0
  489. data/spec/modules/audit/xss_path_spec.rb +19 -0
  490. data/spec/modules/audit/xss_script_tag_spec.rb +19 -0
  491. data/spec/modules/audit/xss_spec.rb +24 -0
  492. data/spec/modules/audit/xss_tag_spec.rb +19 -0
  493. data/spec/modules/recon/allowed_methods_spec.rb +19 -0
  494. data/spec/modules/recon/backdoors_spec.rb +19 -0
  495. data/spec/modules/recon/backup_files_spec.rb +19 -0
  496. data/spec/modules/recon/common_directories_spec.rb +19 -0
  497. data/spec/modules/recon/common_files_spec.rb +19 -0
  498. data/spec/modules/recon/directory_listing_spec.rb +19 -0
  499. data/spec/modules/recon/grep/captcha_spec.rb +19 -0
  500. data/spec/modules/recon/grep/credit_card_spec.rb +19 -0
  501. data/spec/modules/recon/grep/cvs_svn_users_spec.rb +19 -0
  502. data/spec/modules/recon/grep/emails_spec.rb +19 -0
  503. data/spec/modules/recon/grep/html_objects_spec.rb +19 -0
  504. data/spec/modules/recon/grep/http_only_cookies_spec.rb +19 -0
  505. data/spec/modules/recon/grep/insecure_cookies_spec.rb +19 -0
  506. data/spec/modules/recon/grep/mixed_resource_spec.rb +20 -0
  507. data/spec/modules/recon/grep/private_ip_spec.rb +26 -0
  508. data/spec/modules/recon/grep/ssn_spec.rb +19 -0
  509. data/spec/modules/recon/grep/unencrypted_password_forms_spec.rb +19 -0
  510. data/spec/modules/recon/htaccess_limit_spec.rb +19 -0
  511. data/spec/modules/recon/http_put_spec.rb +19 -0
  512. data/spec/modules/recon/interesting_responses_spec.rb +27 -0
  513. data/spec/modules/recon/webdav_spec.rb +19 -0
  514. data/spec/modules/recon/xst_spec.rb +19 -0
  515. data/spec/path_extractors/anchors_spec.rb +19 -0
  516. data/spec/path_extractors/forms_spec.rb +19 -0
  517. data/spec/path_extractors/frames_spec.rb +20 -0
  518. data/spec/path_extractors/generic_spec.rb +28 -0
  519. data/spec/path_extractors/links_spec.rb +19 -0
  520. data/spec/path_extractors/meta_refresh_spec.rb +24 -0
  521. data/spec/path_extractors/scripts_spec.rb +19 -0
  522. data/spec/pems/cacert.pem +39 -0
  523. data/spec/pems/client/cert.pem +39 -0
  524. data/spec/pems/client/foo-cert.pem +39 -0
  525. data/spec/pems/client/foo-key.pem +51 -0
  526. data/spec/pems/client/key.pem +51 -0
  527. data/spec/pems/server/cert.pem +39 -0
  528. data/spec/pems/server/key.pem +51 -0
  529. data/spec/plugins/autologin_spec.rb +76 -0
  530. data/spec/plugins/autothrottle_spec.rb +45 -0
  531. data/spec/plugins/content_types_spec.rb +93 -0
  532. data/spec/plugins/cookie_collector_spec.rb +32 -0
  533. data/spec/plugins/form_dicattack_spec.rb +60 -0
  534. data/spec/plugins/healthmap_spec.rb +40 -0
  535. data/spec/plugins/http_dicattack_spec.rb +40 -0
  536. data/spec/plugins/meta/remedies/discovery_spec.rb +15 -0
  537. data/spec/plugins/meta/remedies/manual_verification_spec.rb +28 -0
  538. data/spec/plugins/meta/remedies/timing_attacks_spec.rb +30 -0
  539. data/spec/plugins/meta/uniformity_spec.rb +83 -0
  540. data/spec/plugins/profiler_spec.rb +82 -0
  541. data/spec/plugins/rescan_spec.rb +26 -0
  542. data/spec/plugins/resolver_spec.rb +16 -0
  543. data/spec/plugins/script_spec.rb +12 -0
  544. data/spec/plugins/vector_feed_spec.rb +155 -0
  545. data/spec/plugins/waf_detector_spec.rb +41 -0
  546. data/spec/reports/afr_spec.rb +13 -0
  547. data/spec/reports/ap_spec.rb +9 -0
  548. data/spec/reports/html_spec.rb +13 -0
  549. data/spec/reports/json_spec.rb +17 -0
  550. data/spec/reports/marshal_spec.rb +13 -0
  551. data/spec/reports/stdout_spec.rb +9 -0
  552. data/spec/reports/txt_spec.rb +8 -0
  553. data/spec/reports/xml_spec.rb +13 -0
  554. data/spec/reports/yaml_spec.rb +13 -0
  555. data/spec/servers/arachni/element/capabilities/auditable/rdiff.rb +36 -0
  556. data/spec/servers/arachni/element/capabilities/auditable/taint.rb +10 -0
  557. data/spec/servers/arachni/element/capabilities/auditable/timeout.rb +30 -0
  558. data/spec/servers/arachni/element/cookie.rb +37 -0
  559. data/spec/servers/arachni/element/form.rb +93 -0
  560. data/spec/servers/arachni/element/header.rb +22 -0
  561. data/spec/servers/arachni/element/link.rb +26 -0
  562. data/spec/servers/arachni/framework.rb +54 -0
  563. data/spec/servers/arachni/http.rb +140 -0
  564. data/spec/servers/arachni/http_auth.rb +9 -0
  565. data/spec/servers/arachni/module/auditor.rb +135 -0
  566. data/spec/servers/arachni/module/trainer.rb +40 -0
  567. data/spec/servers/arachni/parser.rb +70 -0
  568. data/spec/servers/arachni/rpc/server/framework_hpg.rb +21 -0
  569. data/spec/servers/arachni/rpc/server/framework_simple.rb +30 -0
  570. data/spec/servers/arachni/session.rb +110 -0
  571. data/spec/servers/arachni/spider.rb +148 -0
  572. data/spec/servers/modules/audit/code_injection.rb +140 -0
  573. data/spec/servers/modules/audit/code_injection_timing.rb +110 -0
  574. data/spec/servers/modules/audit/csrf.rb +80 -0
  575. data/spec/servers/modules/audit/ldapi.rb +73 -0
  576. data/spec/servers/modules/audit/os_cmd_injection.rb +140 -0
  577. data/spec/servers/modules/audit/os_cmd_injection_timing.rb +111 -0
  578. data/spec/servers/modules/audit/path_traversal.rb +176 -0
  579. data/spec/servers/modules/audit/response_splitting.rb +114 -0
  580. data/spec/servers/modules/audit/rfi.rb +113 -0
  581. data/spec/servers/modules/audit/session_fixation.rb +87 -0
  582. data/spec/servers/modules/audit/sqli.rb +118 -0
  583. data/spec/servers/modules/audit/sqli/coldfusion +1 -0
  584. data/spec/servers/modules/audit/sqli/db2 +4 -0
  585. data/spec/servers/modules/audit/sqli/emc +2 -0
  586. data/spec/servers/modules/audit/sqli/informix +3 -0
  587. data/spec/servers/modules/audit/sqli/interbase +2 -0
  588. data/spec/servers/modules/audit/sqli/jdbc +0 -0
  589. data/spec/servers/modules/audit/sqli/mssql +26 -0
  590. data/spec/servers/modules/audit/sqli/mysql +13 -0
  591. data/spec/servers/modules/audit/sqli/oracle +6 -0
  592. data/spec/servers/modules/audit/sqli/postgresql +7 -0
  593. data/spec/servers/modules/audit/sqli/sqlite +4 -0
  594. data/spec/servers/modules/audit/sqli/sybase +0 -0
  595. data/spec/servers/modules/audit/sqli_blind_rdiff.rb +74 -0
  596. data/spec/servers/modules/audit/sqli_blind_timing.rb +121 -0
  597. data/spec/servers/modules/audit/trainer_module.rb +160 -0
  598. data/spec/servers/modules/audit/unvalidated_redirect.rb +115 -0
  599. data/spec/servers/modules/audit/xpath.rb +111 -0
  600. data/spec/servers/modules/audit/xpath/dotnet +5 -0
  601. data/spec/servers/modules/audit/xpath/general +13 -0
  602. data/spec/servers/modules/audit/xpath/java +3 -0
  603. data/spec/servers/modules/audit/xpath/libxml2 +2 -0
  604. data/spec/servers/modules/audit/xpath/php +2 -0
  605. data/spec/servers/modules/audit/xss.rb +152 -0
  606. data/spec/servers/modules/audit/xss_event.rb +80 -0
  607. data/spec/servers/modules/audit/xss_path.rb +44 -0
  608. data/spec/servers/modules/audit/xss_script_tag.rb +73 -0
  609. data/spec/servers/modules/audit/xss_tag.rb +139 -0
  610. data/spec/servers/modules/module_server.rb +14 -0
  611. data/spec/servers/modules/recon/allowed_methods.rb +5 -0
  612. data/spec/servers/modules/recon/backdoors.rb +4 -0
  613. data/spec/servers/modules/recon/backup_files.rb +28 -0
  614. data/spec/servers/modules/recon/common_directories.rb +6 -0
  615. data/spec/servers/modules/recon/common_files.rb +6 -0
  616. data/spec/servers/modules/recon/directory_listing.rb +30 -0
  617. data/spec/servers/modules/recon/grep/captcha.rb +27 -0
  618. data/spec/servers/modules/recon/grep/credit_card.rb +28 -0
  619. data/spec/servers/modules/recon/grep/cvs_svn_users.rb +23 -0
  620. data/spec/servers/modules/recon/grep/emails.rb +21 -0
  621. data/spec/servers/modules/recon/grep/html_objects.rb +7 -0
  622. data/spec/servers/modules/recon/grep/http_only_cookies.rb +21 -0
  623. data/spec/servers/modules/recon/grep/insecure_cookies.rb +21 -0
  624. data/spec/servers/modules/recon/grep/mixed_resource.rb +83 -0
  625. data/spec/servers/modules/recon/grep/private_ip.rb +18 -0
  626. data/spec/servers/modules/recon/grep/ssn.rb +5 -0
  627. data/spec/servers/modules/recon/grep/unencrypted_password_forms.rb +33 -0
  628. data/spec/servers/modules/recon/htaccess_limit.rb +8 -0
  629. data/spec/servers/modules/recon/http_put.rb +7 -0
  630. data/spec/servers/modules/recon/interesting_responses.rb +5 -0
  631. data/spec/servers/modules/recon/webdav.rb +25 -0
  632. data/spec/servers/modules/recon/xst.rb +6 -0
  633. data/spec/servers/plugins/autologin.rb +38 -0
  634. data/spec/servers/plugins/autothrottle.rb +8 -0
  635. data/spec/servers/plugins/content_types.rb +17 -0
  636. data/spec/servers/plugins/cookie_collector.rb +20 -0
  637. data/spec/servers/plugins/form_dicattack.rb +28 -0
  638. data/spec/servers/plugins/healthmap.rb +16 -0
  639. data/spec/servers/plugins/http_dicattack.rb +9 -0
  640. data/spec/servers/plugins/http_dicattack_secure.rb +9 -0
  641. data/spec/servers/plugins/http_dicattack_unprotected.rb +5 -0
  642. data/spec/servers/plugins/meta/remedies/discovery.rb +7 -0
  643. data/spec/servers/plugins/meta/remedies/timing_attacks.rb +29 -0
  644. data/spec/servers/plugins/profiler.rb +82 -0
  645. data/spec/servers/plugins/rescan.rb +31 -0
  646. data/spec/servers/plugins/waf_detector.rb +33 -0
  647. data/spec/shared/component.rb +43 -0
  648. data/spec/shared/element/capabilities/auditable.rb +729 -0
  649. data/spec/shared/element/capabilities/refreshable.rb +56 -0
  650. data/spec/shared/module.rb +162 -0
  651. data/spec/shared/path_extractor.rb +47 -0
  652. data/spec/shared/plugin.rb +50 -0
  653. data/spec/shared/reports.rb +47 -0
  654. data/spec/spec_helper.rb +53 -0
  655. metadata +870 -323
  656. data/extras/modules/recon/raft_dirs.rb +0 -108
  657. data/extras/modules/recon/raft_dirs/raft-large-directories.txt +0 -62290
  658. data/extras/modules/recon/raft_files.rb +0 -110
  659. data/extras/modules/recon/raft_files/raft-large-files.txt +0 -37037
  660. data/extras/modules/recon/svn_digger_dirs.rb +0 -108
  661. data/extras/modules/recon/svn_digger_dirs/Licence.txt +0 -674
  662. data/extras/modules/recon/svn_digger_dirs/ReadMe-Arachni.txt +0 -4
  663. data/extras/modules/recon/svn_digger_dirs/ReadMe.txt +0 -6
  664. data/extras/modules/recon/svn_digger_dirs/all-dirs.txt +0 -5960
  665. data/extras/modules/recon/svn_digger_files.rb +0 -114
  666. data/extras/modules/recon/svn_digger_files/Licence.txt +0 -674
  667. data/extras/modules/recon/svn_digger_files/ReadMe-Arachni.txt +0 -4
  668. data/extras/modules/recon/svn_digger_files/ReadMe.txt +0 -6
  669. data/extras/modules/recon/svn_digger_files/all-extensionless.txt +0 -25419
  670. data/extras/modules/recon/svn_digger_files/all.txt +0 -43135
  671. data/lib/arachni/component_manager.rb +0 -293
  672. data/lib/arachni/component_options.rb +0 -425
  673. data/lib/arachni/parser/auditable.rb +0 -606
  674. data/lib/arachni/parser/elements.rb +0 -315
  675. data/lib/arachni/parser/page.rb +0 -168
  676. data/lib/arachni/parser/parser.rb +0 -866
  677. data/lib/arachni/rpc/server/options.rb +0 -95
  678. data/lib/arachni/ui/web/addons/autodeploy.rb +0 -207
  679. data/lib/arachni/ui/web/addons/autodeploy/lib/manager.rb +0 -398
  680. data/lib/arachni/ui/web/addons/autodeploy/views/index.erb +0 -291
  681. data/modules/recon/mixed_resource.rb +0 -100
  682. data/modules/recon/unencrypted_password_forms.rb +0 -107
  683. data/path_extractors/sitemap.rb +0 -31
  684. data/plugins/defaults/metamodules/remedies/manual_verification.rb +0 -65
  685. data/plugins/defaults/metamodules/remedies/timing_attacks.rb +0 -134
  686. data/plugins/defaults/metamodules/uniformity.rb +0 -99
  687. data/reports/metareport/arachni_metareport.rb +0 -174
  688. data/reports/plugin_formatters/stdout/metamodules.rb +0 -82
@@ -1,11 +1,17 @@
1
1
  =begin
2
- Arachni
3
- Copyright (c) 2010-2012 Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
2
+ Copyright 2010-2012 Tasos Laskos <tasos.laskos@gmail.com>
4
3
 
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)
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
8
7
 
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
9
15
  =end
10
16
 
11
17
  module Arachni
@@ -1,11 +1,17 @@
1
1
  =begin
2
- Arachni
3
- Copyright (c) 2010-2012 Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
2
+ Copyright 2010-2012 Tasos Laskos <tasos.laskos@gmail.com>
4
3
 
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)
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
8
7
 
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
9
15
  =end
10
16
 
11
17
  module Arachni
@@ -27,7 +33,7 @@ module Mixins
27
33
  # include ProgressBar
28
34
  #
29
35
  # # clear the screen
30
- # clear_screen!
36
+ # clear_screen
31
37
  #
32
38
  # start_time = Time.now
33
39
  #
@@ -36,7 +42,7 @@ module Mixins
36
42
  # |i|
37
43
  #
38
44
  # # move the cursor to its home, top-left of the screen.
39
- # move_to_home!
45
+ # move_to_home
40
46
  #
41
47
  # prog = i / Float( MAX ) * 100
42
48
  #
@@ -50,7 +56,7 @@ module Mixins
50
56
  #
51
57
  #
52
58
  # # make sure that everything is sent out on time
53
- # flush!
59
+ # flush
54
60
  # sleep 0.003
55
61
  # }
56
62
  #
@@ -81,21 +87,21 @@ module Terminal
81
87
  #
82
88
  # Clear the bottom of the screen
83
89
  #
84
- def clear_screen!
90
+ def clear_screen
85
91
  print "\e[2J"
86
92
  end
87
93
 
88
94
  #
89
95
  # Moves cursor top left to its home
90
96
  #
91
- def move_to_home!
97
+ def move_to_home
92
98
  print "\e[H"
93
99
  end
94
100
 
95
101
  #
96
102
  # Flushes the STDOUT buffer
97
103
  #
98
- def flush!
104
+ def flush
99
105
  $stdout.flush
100
106
  end
101
107
 
@@ -1,4 +1,4 @@
1
- opts = Arachni::Options.instance
2
- require opts.dir['lib'] + 'component_manager'
3
- require opts.dir['lib'] + 'module/base'
4
- require opts.dir['lib'] + 'module/manager'
1
+ lib = Arachni::Options.dir['lib']
2
+ require lib + 'component/manager'
3
+ require lib + 'module/base'
4
+ require lib + 'module/manager'
@@ -1,11 +1,17 @@
1
1
  =begin
2
- Arachni
3
- Copyright (c) 2010-2012 Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
2
+ Copyright 2010-2012 Tasos Laskos <tasos.laskos@gmail.com>
4
3
 
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)
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
8
7
 
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
9
15
  =end
10
16
 
11
17
  module Arachni
@@ -14,244 +20,156 @@ module Module
14
20
  #
15
21
  # Auditor module
16
22
  #
17
- # Included by {Module::Base} and provides abstract audit methods.
23
+ # Included by {Module::Base} and provides helper audit methods to all modules.
24
+ #
25
+ # There are 3 main types of audit and analysis techniques available:
26
+ # * Taint analysis -- {#audit}
27
+ # * Timeout analysis -- {#audit_timeout}
28
+ # * Differential analysis -- {#audit_rdiff}
18
29
  #
19
- # There are 3 main types of audit techniques available:
20
- # * Pattern matching -- {#audit}
21
- # * Timing attacks -- {#audit_timeout}
22
- # * Differential analysis attacks -- {#audit_rdiff}
30
+ # It should be noted that actual analysis takes place at the element level,
31
+ # and to be more specific, the {Arachni::Element::Capabilities::Auditable} element level.
23
32
  #
33
+ # The module also provides:
34
+ # * discovery helpers for checking and logging the existence of remote files
35
+ # * pattern matching helpers for checking and logging the existence of strings
36
+ # in responses or in the body of the page that's being audited
37
+ # * general {Arachni::Issue} logging helpers
24
38
  #
25
- # @author: Tasos "Zapotek" Laskos
26
- # <tasos.laskos@gmail.com>
27
- # <zapotek@segfault.gr>
28
- # @version: 0.3.1
39
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
29
40
  #
30
41
  module Auditor
42
+ include Output
31
43
 
32
- def self.included( mod )
33
- # @@__timeout_audited ||= Set.new
34
-
35
- # holds timing-attack performing Procs to be run after all
36
- # non-timing-attack modules have finished.
37
- @@__timeout_audit_blocks ||= Queue.new
38
-
39
- @@__timeout_audit_operations_cnt ||= 0
40
-
41
- # populated by timing attack phase 1 with
42
- # candidate elements to be verified by phase 2
43
- @@__timeout_candidates ||= Queue.new
44
-
45
- # modules which have called the timing attack audit method (audit_timeout)
46
- # we're interested in the amount, not the names, and is used to
47
- # determine scan progress
48
- @@__timeout_loaded_modules ||= Set.new
49
-
50
- @@__on_timing_attacks ||= []
51
-
52
- @@__running_timeout_attacks ||= false
53
-
54
- # the rdiff attack performs it own redundancy checks so we need this to
55
- # keep track audited elements
56
- @@__rdiff_audited ||= Set.new
57
- end
58
-
59
- #
60
- # Returns the names of all loaded modules that use timing attacks.
61
- #
62
- # @return [Set]
63
- #
64
- def self.timeout_loaded_modules
65
- @@__timeout_loaded_modules
44
+ def self.reset
45
+ audited.clear
66
46
  end
67
47
 
68
- #
69
- # Holds timing-attack performing Procs to be run after all
70
- # non-timing-attack modules have finished.
71
- #
72
- # @return [Queue]
73
- #
74
48
  def self.timeout_audit_blocks
75
- @@__timeout_audit_blocks
76
- end
77
-
78
- def self.current_timeout_audit_operations_cnt
79
- @@__timeout_audit_blocks.size + @@__timeout_candidates.size
49
+ Element::Capabilities::Auditable.timeout_audit_blocks
80
50
  end
81
-
82
- def self.add_timeout_audit_block( &block )
83
- @@__timeout_audit_operations_cnt += 1
84
- @@__timeout_audit_blocks << block
51
+ def self.timeout_loaded_modules
52
+ Element::Capabilities::Auditable.timeout_loaded_modules
85
53
  end
86
-
87
- def Auditor.add_timeout_candidate( elem )
88
- @@__timeout_audit_operations_cnt += 1
89
- @@__timeout_candidates << elem
54
+ def self.on_timing_attacks( &block )
55
+ Element::Capabilities::Auditable.on_timing_attacks( &block )
90
56
  end
91
-
92
-
93
57
  def self.running_timeout_attacks?
94
- @@__running_timeout_attacks
58
+ Element::Capabilities::Auditable.running_timeout_attacks?
95
59
  end
96
-
97
- def self.on_timing_attacks( &block )
98
- @@__on_timing_attacks << block
60
+ def self.timeout_audit_run
61
+ Element::Capabilities::Auditable.timeout_audit_run
99
62
  end
100
-
101
63
  def self.timeout_audit_operations_cnt
102
- @@__timeout_audit_operations_cnt
64
+ Element::Capabilities::Auditable.timeout_audit_operations_cnt
65
+ end
66
+ def self.current_timeout_audit_operations_cnt
67
+ Element::Capabilities::Auditable.current_timeout_audit_operations_cnt
103
68
  end
104
69
 
105
- def Auditor.call_on_timing_blocks( res, elem )
106
- @@__on_timing_attacks.each {
107
- |block|
108
- block.call( res, elem )
109
- }
70
+ #
71
+ # @param [#to_s] id identifier of the object to be marked as audited
72
+ #
73
+ # @see #audited?
74
+ #
75
+ def audited( id )
76
+ Auditor.audited << "#{self.class}-#{id}"
110
77
  end
111
78
 
112
- def call_on_timing_blocks( res, elem )
113
- Auditor.call_on_timing_blocks( res, elem )
79
+ #
80
+ # @param [#to_s] id identifier of the object to be checked
81
+ #
82
+ # @return [Bool] +true+ if audited, +false+ otherwise
83
+ #
84
+ # @see #audited
85
+ #
86
+ def audited?( id )
87
+ Auditor.audited.include?( "#{self.class}-#{id}" )
114
88
  end
115
89
 
116
90
  #
117
91
  # Holds constant bitfields that describe the preferred formatting
118
92
  # of injection strings.
119
93
  #
120
- module Format
121
-
122
- #
123
- # Leaves the injection string as is.
124
- #
125
- STRAIGHT = 1 << 0
126
-
127
- #
128
- # Appends the injection string to the default value of the input vector.<br/>
129
- # (If no default value exists Arachni will choose one.)
130
- #
131
- APPEND = 1 << 1
132
-
133
- #
134
- # Terminates the injection string with a null character.
135
- #
136
- NULL = 1 << 2
137
-
138
- #
139
- # Prefix the string with a ';', useful for command injection modules
140
- #
141
- SEMICOLON = 1 << 3
142
- end
94
+ Format = Element::Capabilities::Mutable::Format
143
95
 
144
96
  #
145
97
  # Holds constants that describe the HTML elements to be audited.
146
98
  #
147
- module Element
148
- LINK = Issue::Element::LINK
149
- FORM = Issue::Element::FORM
150
- COOKIE = Issue::Element::COOKIE
151
- HEADER = Issue::Element::HEADER
152
- BODY = Issue::Element::BODY
153
- PATH = Issue::Element::PATH
154
- SERVER = Issue::Element::SERVER
155
- end
156
-
157
- RDIFF_OPTIONS = {
158
- # append our seeds to the default values
159
- :format => [ Format::APPEND ],
160
-
161
- # allow duplicate requests
162
- :redundant => true,
163
-
164
- # amount of rdiff iterations
165
- :precision => 2
166
- }
99
+ #module Element
100
+ # include Issue::Element
101
+ #end
167
102
 
168
103
  #
169
- # Default audit options.
104
+ # Holds constants that describe Issue severities.
170
105
  #
171
- OPTIONS = {
106
+ #Severity = Issue::Severity
172
107
 
108
+ OPTIONS = {
173
109
  #
174
110
  # Elements to audit.
175
111
  #
176
- # Only required when calling {#audit}.<br/>
177
- # If no elements have been passed to audit it will
178
- # use the elements in {#self.info}.
112
+ # If no elements have been passed to audit candidates will be
113
+ # determined by {#candidate_elements}.
179
114
  #
180
- :elements => [ Element::LINK, Element::FORM,
181
- Element::COOKIE, Element::HEADER,
182
- Issue::Element::BODY ],
115
+ elements: [Element::LINK, Element::FORM,
116
+ Element::COOKIE, Element::HEADER,
117
+ Element::BODY],
183
118
 
184
119
  #
185
- # The regular expression to match against the response body.
186
- #
187
- :regexp => nil,
188
-
189
- #
190
- # Verify the matched string with this value.
191
- #
192
- :match => nil,
193
-
194
- #
195
- # Formatting of the injection strings.
196
- #
197
- # A new set of audit inputs will be generated
198
- # for each value in the array.
199
- #
200
- # Values can be OR'ed bitfields of all available constants
201
- # of {Auditor::Format}.
202
- #
203
- # @see Auditor::Format
204
- #
205
- :format => [ Format::STRAIGHT, Format::APPEND,
206
- Format::NULL, Format::APPEND | Format::NULL ],
207
-
208
- #
209
- # If 'train' is set to true the HTTP response will be
210
- # analyzed for new elements. <br/>
120
+ # If set to +true+ the HTTP response will be
121
+ # analyzed for new elements.
211
122
  # Be careful when enabling it, there'll be a performance penalty.
212
123
  #
213
- # When the Auditor submits a form with original or sample values
214
- # this option will be overridden to true.
215
- #
216
- :train => false,
217
-
218
- #
219
- # Enable skipping of already audited inputs
220
- #
221
- :redundant => false,
222
-
124
+ # If set to +false+, no training is going to occur.
223
125
  #
224
- # Make requests asynchronously
126
+ # If set to +nil+, when the Auditor submits a form with original or sample values
127
+ # this option will be overridden to +true+.
225
128
  #
226
- :async => true
129
+ train: nil
227
130
  }
228
131
 
229
132
  #
230
- # ABSTRACT - OPTIONAL
133
+ # REQUIRED
231
134
  #
232
- # Prevents auditing elements that have been previously
233
- # logged by any of the modules returned by this method.
135
+ # Must return the Page object you wish to be audited.
234
136
  #
235
- # @return [Array] module names
137
+ # @return [Arachni::Page]
138
+ # @abstract
236
139
  #
237
- def redundant
238
- # [ 'sqli', 'sqli_blind_rdiff' ]
239
- []
240
- end
140
+ attr_reader :page
141
+
142
+ #
143
+ # REQUIRED
144
+ #
145
+ # Must return the Framework
146
+ #
147
+ # @return [Arachni::Framework]
148
+ #
149
+ # @abstract
150
+ #
151
+ attr_reader :framework
241
152
 
242
153
  #
243
- # ABSTRACT - OPTIONAL
154
+ # OPTIONAL
244
155
  #
245
156
  # Allows modules to ignore HPG scope restrictions
246
157
  #
247
- # This way they can audit elements that are not on the Grid sanctioned whitlist.
158
+ # This way they can audit elements that are not on the Grid sanctioned whitelist.
248
159
  #
249
160
  # @return [Bool]
250
161
  #
162
+ # @abstract
163
+ #
251
164
  def override_instance_scope?
252
165
  false
253
166
  end
254
167
 
168
+ # @return [Arachni::HTTP]
169
+ def http
170
+ HTTP
171
+ end
172
+
255
173
  #
256
174
  # Just a delegator logs an array of issues.
257
175
  #
@@ -260,7 +178,7 @@ module Auditor
260
178
  # @see Arachni::Module::Manager.register_results
261
179
  #
262
180
  def register_results( issues )
263
- Arachni::Module::Manager.register_results( issues )
181
+ Module::Manager.register_results( issues )
264
182
  end
265
183
 
266
184
  #
@@ -269,7 +187,7 @@ module Auditor
269
187
  # @param [String] url
270
188
  # @param [Bool] silent if false, a message will be sent to stdout
271
189
  # containing the status of the operation.
272
- # @param [Proc] &block called if the file exists, just before logging
190
+ # @param [Proc] block called if the file exists, just before logging
273
191
  #
274
192
  # @return [Object] - nil if no URL was provided
275
193
  # - false if the request couldn't be fired
@@ -280,24 +198,20 @@ module Auditor
280
198
  def log_remote_file_if_exists( url, silent = false, &block )
281
199
  return nil if !url
282
200
 
283
- req = @http.get( url )
284
- return false if !req
285
- req.on_complete {
286
- |res|
287
-
201
+ print_status( "Checking for #{url}" ) if !silent
202
+ remote_file_exist?( url ) do |bool, res|
288
203
  print_status( 'Analyzing response for: ' + url ) if !silent
289
204
 
290
- if remote_file_exist?( res )
205
+ if bool
291
206
  block.call( res ) if block_given?
292
207
  log_remote_file( res )
293
208
 
294
209
  # if the file exists let the trainer parse it since it may
295
210
  # contain brand new data to audit
296
- @http.trainer.add_response( res )
211
+ http.trainer.push( res )
297
212
  end
298
- }
299
-
300
- return true
213
+ end
214
+ true
301
215
  end
302
216
  alias :log_remote_directory_if_exists :log_remote_file_if_exists
303
217
 
@@ -305,10 +219,20 @@ module Auditor
305
219
  # Checks that the response points to an existing file/page and not
306
220
  # an error or custom 404 response.
307
221
  #
308
- # @param [Typhoeus::Response] res
222
+ # @param [String] url
309
223
  #
310
- def remote_file_exist?( res )
311
- res.code == 200 && !@http.custom_404?( res )
224
+ def remote_file_exist?( url, &block )
225
+ req = http.get( url )
226
+ return false if !req
227
+
228
+ req.on_complete do |res|
229
+ if res.code != 200
230
+ block.call( false, res )
231
+ else
232
+ http.custom_404?( res ) { |bool| block.call( !bool, res ) }
233
+ end
234
+ end
235
+ true
312
236
  end
313
237
 
314
238
  #
@@ -318,22 +242,23 @@ module Auditor
318
242
  #
319
243
  # @see #log_issue
320
244
  #
321
- def log_remote_file( res )
245
+ def log_remote_file( res, silent = false )
322
246
  url = res.effective_url
323
247
  filename = File.basename( URI( res.effective_url ).path )
324
248
 
325
249
  log_issue(
326
- :url => url,
327
- :injected => filename,
328
- :id => filename,
329
- :elem => Issue::Element::PATH,
330
- :response => res.body,
331
- :headers => {
332
- :request => res.request.headers,
333
- :response => res.headers,
250
+ url: url,
251
+ injected: filename,
252
+ id: filename,
253
+ elem: Element::PATH,
254
+ response: res.body,
255
+ headers: {
256
+ request: res.request.headers,
257
+ response: res.headers,
334
258
  }
335
259
  )
336
260
 
261
+ print_ok( "Found #{filename} at #{url}" ) if !silent
337
262
  end
338
263
  alias :log_remote_directory :log_remote_file
339
264
 
@@ -341,7 +266,6 @@ module Auditor
341
266
  # Helper method for issue logging.
342
267
  #
343
268
  # @param [Hash] opts issue options ({Issue})
344
- # @param [Bool] include_class_info merge opts with module.info?
345
269
  #
346
270
  # @see Arachni::Module::Base#register_results
347
271
  #
@@ -351,714 +275,267 @@ module Auditor
351
275
  end
352
276
 
353
277
  #
354
- # Matches the "string" (default string is the HTML code in @page.html) to
278
+ # Matches the "string" (default string is the HTML code in page.body) to
355
279
  # an array of regular expressions and logs the results.
356
280
  #
357
- # For good measure, regexps will also be run against the page headers (@page.response_headers).
281
+ # For good measure, regexps will also be run against the page headers (page.response_headers).
358
282
  #
359
283
  # @param [Array<Regexp>] regexps array of regular expressions to be tested
360
284
  # @param [String] string string to
361
285
  # @param [Block] block block to verify matches before logging,
362
286
  # must return true/false
363
287
  #
364
- def match_and_log( regexps, string = @page.html, &block )
365
-
288
+ def match_and_log( regexps, string = page.body, &block )
366
289
  # make sure that we're working with an array
367
290
  regexps = [regexps].flatten
368
291
 
369
292
  elems = self.class.info[:elements]
370
293
  elems = OPTIONS[:elements] if !elems || elems.empty?
371
294
 
372
- regexps.each {
373
- |regexp|
374
-
375
- string.scan( regexp ).flatten.uniq.each {
376
- |match|
295
+ regexps.each do |regexp|
296
+ string.scan( regexp ).flatten.uniq.each do |match|
377
297
 
378
298
  next if !match
379
299
  next if block && !block.call( match )
380
300
 
381
301
  log(
382
- :regexp => regexp,
383
- :match => match,
384
- :element => Issue::Element::BODY
302
+ regexp: regexp,
303
+ match: match,
304
+ element: Element::BODY
385
305
  )
386
- } if elems.include? Issue::Element::BODY
306
+ end if elems.include? Element::BODY
387
307
 
388
- next if string == @page.html
308
+ next if string != page.body
389
309
 
390
- @page.response_headers.each {
391
- |k,v|
310
+ page.response_headers.each do |k,v|
392
311
  next if !v
393
312
 
394
- v.to_s.scan( regexp ).flatten.uniq.each {
395
- |match|
396
-
313
+ v.to_s.scan( regexp ).flatten.uniq.each do |match|
397
314
  next if !match
398
315
  next if block && !block.call( match )
399
316
 
400
317
  log(
401
- :var => k,
402
- :regexp => regexp,
403
- :match => match,
404
- :element => Issue::Element::HEADER
318
+ var: k,
319
+ regexp: regexp,
320
+ match: match,
321
+ element: Element::HEADER
405
322
  )
406
- }
407
- } if elems.include? Issue::Element::HEADER
323
+ end
324
+ end if elems.include? Element::HEADER
408
325
 
409
- }
326
+ end
410
327
  end
411
328
 
412
329
  #
413
330
  # Populates and logs an {Arachni::Issue} based on data from "opts" and "res".
414
331
  #
415
332
  # @param [Hash] opts as passed to blocks by audit methods
416
- # @param [Typhoeus::Response] res defaults to @page data
333
+ # @param [Typhoeus::Response] res defaults to page data
417
334
  #
418
335
  def log( opts, res = nil )
336
+ response_headers = {}
337
+ request_headers = {}
338
+ response = nil
339
+ method = nil
340
+
341
+ if page
342
+ request_headers = nil
343
+ response_headers = page.response_headers
344
+ response = page.body
345
+ url = page.url
346
+ method = page.method.to_s.upcase if page.method
347
+ end
419
348
 
420
- method = nil
421
-
422
- request_headers = nil
423
- response_headers = @page.response_headers
424
- response = @page.html
425
- url = @page.url
426
- method = @page.method.to_s.upcase if @page.method
427
-
428
- if( res )
349
+ if res
429
350
  request_headers = res.request.headers
430
351
  response_headers = res.headers
431
352
  response = res.body
432
- url = opts[:action]
353
+ url = opts[:action] || res.effective_url
433
354
  method = res.request.method.to_s.upcase
434
355
  end
435
356
 
436
- if response_headers['content-type'] &&
437
- !response_headers['content-type'].substring?( 'text' )
357
+ if !response_headers['content-type'].to_s.include?( 'text' )
438
358
  response = nil
439
359
  end
440
360
 
441
- begin
442
- print_ok( "In #{opts[:element]} var '#{opts[:altered]}' ( #{url} )" )
443
- rescue
444
- end
361
+ var = opts[:altered] || opts[:var]
362
+
363
+ msg = "In #{opts[:element]}"
364
+ msg << " var '#{var}'" if var
365
+ print_ok "#{msg} ( #{url} )"
445
366
 
446
367
  print_verbose( "Injected string:\t" + opts[:injected] ) if opts[:injected]
447
368
  print_verbose( "Verified string:\t" + opts[:match].to_s ) if opts[:match]
448
- print_verbose( "Matched regular expression: " + opts[:regexp].to_s )
369
+ print_verbose( "Matched regular expression: " + opts[:regexp].to_s ) if opts[:regexp]
449
370
  print_debug( 'Request ID: ' + res.request.id.to_s ) if res
450
371
  print_verbose( '---------' ) if only_positives?
451
372
 
452
- # Instantiate a new Issue class and append it to the results array
453
373
  log_issue(
454
- :var => opts[:altered],
455
- :url => url,
456
- :injected => opts[:injected],
457
- :id => opts[:id],
458
- :regexp => opts[:regexp],
459
- :regexp_match => opts[:match],
460
- :elem => opts[:element],
461
- :verification => opts[:verification] || false,
462
- :method => method,
463
- :response => response,
464
- :opts => opts,
465
- :headers => {
466
- :request => request_headers,
467
- :response => response_headers,
374
+ var: var,
375
+ url: url,
376
+ injected: opts[:injected],
377
+ id: opts[:id],
378
+ regexp: opts[:regexp],
379
+ regexp_match: opts[:match],
380
+ elem: opts[:element],
381
+ verification: !!opts[:verification],
382
+ method: method,
383
+ response: response,
384
+ opts: opts,
385
+ headers: {
386
+ request: request_headers,
387
+ response: response_headers,
468
388
  }
469
389
  )
470
390
  end
471
391
 
472
- #
473
- # Provides easy access to element auditing using simple injection and pattern
474
- # matching.
475
- #
476
- # If a block has been provided analysis and logging will be delegated to it,
477
- # otherwise, if a match is found it will be automatically logged.
478
- #
479
- # If no elements have been specified in 'opts' it will
480
- # use the elements from the module's "self.info()" hash. <br/>
481
- # If no elements have been specified in 'opts' or "self.info()" it will
482
- # use the elements in {OPTIONS}. <br/>
483
- #
484
- #
485
- # @param [String] injection_str the string to be injected
486
- # @param [Hash] opts options as described in {OPTIONS}
487
- # @param [Block] &block block to be used for custom analysis of responses; will be passed the following:
488
- # * HTTP response
489
- # * options
490
- # * element
491
- # The block will be called as soon as the
492
- # HTTP response is received.
493
- #
494
- def audit( injection_str, opts = { }, &block )
495
-
496
- if( !opts.include?( :elements) || !opts[:elements] || opts[:elements].empty? )
497
- opts[:elements] = self.class.info[:elements]
498
- end
499
-
500
- if( !opts.include?( :elements) || !opts[:elements] || opts[:elements].empty? )
501
- opts[:elements] = OPTIONS[:elements]
502
- end
503
-
504
- opts = OPTIONS.merge( opts )
505
-
506
- opts[:elements].each {
507
- |elem|
508
-
509
- case elem
510
-
511
- when Element::LINK
512
- audit_links( injection_str, opts, &block )
513
-
514
- when Element::FORM
515
- audit_forms( injection_str, opts, &block )
516
-
517
- when Element::COOKIE
518
- audit_cookies( injection_str, opts, &block )
519
-
520
- when Element::HEADER
521
- audit_headers( injection_str, opts, &block )
522
- when Element::BODY
523
- else
524
- raise( 'Unknown element to audit: ' + elem.to_s )
525
- end
526
-
527
- }
392
+ # @see Arachni::Module::Base.preferred
393
+ def preferred
394
+ []
528
395
  end
529
396
 
530
397
  #
531
- # This is called right before an [Arachni::Parser::Element]
532
- # is submitted/audited and is used to determine whether to skip it or not.
398
+ # This is called right before an [Arachni::Element]
399
+ # is audited and is used to determine whether to skip it or not.
533
400
  #
534
401
  # Running modules can override this as they wish *but* at their own peril.
535
402
  #
536
- # @param [Arachni::Parser::Element] elem
403
+ # @param [Arachni::Element] elem
537
404
  #
538
405
  def skip?( elem )
539
- redundant.map {
540
- |mod|
541
-
542
- mod_name = @framework.modules[mod].info[:name]
543
-
544
- set_id = @framework.modules.class.issue_set_id_from_elem( mod_name, elem )
545
- return true if @framework.modules.issue_set.include?( set_id )
546
- } if @framework
406
+ if framework
407
+ @modname ||= framework.modules.map { |k, v| k if v == self.class }.compact.first
408
+ (preferred | [@modname]).each do |mod|
409
+ next if !framework.modules.include?( mod )
410
+ issue_id = elem.provisioned_issue_id( framework.modules[mod].info[:name] )
411
+ return true if framework.modules.issue_set.include?( issue_id )
412
+ end
413
+ end
547
414
 
548
- return false
415
+ false
549
416
  end
550
417
 
551
418
  #
552
- # Audits elements using timing attacks and automatically logs results.
553
- #
554
- # Here's how it works:
555
- # * Loop 1 -- Populates the candidate queue. We're picking the low hanging
556
- # fruit here so we can run this in larger concurrent bursts which cause *lots* of noise.
557
- # - Initial probing for candidates -- Any element that times out is added to a queue.
558
- # - Stabilization -- The candidate is submitted with its default values in
559
- # order to wait until the effects of the timing attack have worn off.
560
- # * Loop 2 -- Verifies the candidates. This is much more delicate so the
561
- # concurrent requests are lowered to pairs.
562
- # - Liveness test -- Ensures that stabilization was successful before moving on.
563
- # - Verification using an increased timeout -- Any elements that time out again are logged.
564
- # - Stabilization
565
- #
566
- # Ideally, all requests involved with timing attacks would be run in sync mode
567
- # but the performance penalties are too high, thus we compromise and make the best of it
568
- # by running as little an amount of concurrent requests as possible for any given phase.
419
+ # Returns a list of prepared elements to be audited.
569
420
  #
570
- # opts = {
571
- # :format => [ Format::STRAIGHT ],
572
- # :timeout => 4000,
573
- # :timeout_divider => 1000
574
- # }
421
+ # If no element types have been specified in 'opts' it will
422
+ # use the elements from the module's "self.info()" hash.
575
423
  #
576
- # audit_timeout( [ 'sleep( __TIME__ );' ], opts )
424
+ # If no elements have been specified in 'opts' or "self.info()" it will
425
+ # use the elements in {OPTIONS}.
577
426
  #
427
+ # @param [Hash] opts options as described in {OPTIONS} -- only interested in opts[:elements]
578
428
  #
579
- # @param [Array] strings injection strings
580
- # __TIME__ will be substituted with (timeout / timeout_divider)
581
- # @param [Hash] opts options as described in {OPTIONS} with the following extra:
582
- # * :timeout -- milliseconds to wait for the request to complete
583
- # * :timeout_divider -- __TIME__ = timeout / timeout_divider
429
+ # @return [Array<Arachni::Element::Capabilities::Auditable] array of auditable elements
584
430
  #
585
- def audit_timeout( strings, opts )
586
- @@__timeout_loaded_modules << self.class.info[:name]
587
-
588
- Auditor.add_timeout_audit_block {
589
- delay = opts[:timeout]
590
-
591
- audit_timeout_debug_msg( 1, delay )
592
- timing_attack( strings, opts ) {
593
- |res, c_opts, elem|
594
-
595
- elem.auditor( self )
596
-
597
- print_info( "Found a candidate -- #{elem.type.capitalize} input '#{elem.altered}' at #{elem.action}" )
598
-
599
- Arachni::Module::Auditor.audit_timeout_stabilize( elem )
600
-
601
- Auditor.add_timeout_candidate( elem )
602
- }
603
- }
604
- end
605
-
606
- #
607
- # Runs all blocks in {timeout_audit_blocks} and verifies
608
- # and logs the candidate elements.
609
- #
610
- def self.timeout_audit_run
611
- @@__running_timeout_attacks = true
612
-
613
- while( !@@__timeout_audit_blocks.empty? )
614
- @@__timeout_audit_blocks.pop.call
431
+ def candidate_elements( opts = {} )
432
+ if !opts.include?( :elements) || !opts[:elements] || opts[:elements].empty?
433
+ opts[:elements] = self.class.info[:elements]
615
434
  end
616
435
 
617
- while( !@@__timeout_candidates.empty? )
618
- self.audit_timeout_phase_2( @@__timeout_candidates.pop )
436
+ if !opts.include?( :elements) || !opts[:elements] || opts[:elements].empty?
437
+ opts[:elements] = OPTIONS[:elements]
619
438
  end
620
- end
621
-
622
- #
623
- # Runs phase 2 of the timing attack auditing an individual element
624
- # (which passed phase 1) with a higher delay and timeout
625
- #
626
- def self.audit_timeout_phase_2( elem )
627
-
628
- # reset the audited list since we're going to re-audit the elements
629
- # @@__timeout_audited = Set.new
630
439
 
631
- opts = elem.opts
632
- opts[:timeout] *= 2
633
- # opts[:async] = false
634
- # self.audit_timeout_debug_msg( 2, opts[:timeout] )
440
+ elements = []
441
+ opts[:elements].each do |elem|
442
+ next if !Options.audit?( elem )
635
443
 
636
- str = opts[:timing_string].gsub( '__TIME__',
637
- ( opts[:timeout] / opts[:timeout_divider] ).to_s )
444
+ elements |= case elem
445
+ when Element::LINK
446
+ page.links
638
447
 
639
- opts[:timeout] *= 0.7
448
+ when Element::FORM
449
+ page.forms
640
450
 
641
- elem.auditable = elem.orig
451
+ when Element::COOKIE
452
+ page.cookies
642
453
 
643
- # this is the control; request the URL of the element to make sure
644
- # that the web page is alive i.e won't time-out by default
645
- elem.get_auditor.http.get( elem.action ).on_complete {
646
- |res|
454
+ when Element::HEADER
455
+ page.headers
647
456
 
648
- self.call_on_timing_blocks( res, elem )
649
-
650
- if !res.timed_out?
651
-
652
- elem.get_auditor.print_info( 'Liveness check was successful, progressing to verification...' )
653
-
654
- elem.audit( str, opts ) {
655
- |c_res, c_opts|
656
-
657
- if c_res.timed_out?
658
-
659
- # all issues logged by timing attacks need manual verification.
660
- # end of story.
661
- # c_opts[:verification] = true
662
- elem.get_auditor.log( c_opts, c_res )
663
-
664
- self.audit_timeout_stabilize( elem )
665
-
666
- else
667
- elem.get_auditor.print_info( 'Verification failed.' )
668
- end
669
- }
670
- else
671
- elem.get_auditor.print_info( 'Liveness check failed, bailing out...' )
457
+ when Element::BODY
458
+ else
459
+ failt "Unknown element to audit: #{elem}"
672
460
  end
673
- }
461
+ end
674
462
 
675
- elem.get_auditor.http.run
463
+ elements.map { |e| d = e.dup; d.auditor = self; d }
676
464
  end
677
465
 
678
466
  #
679
- # Submits an element which has just been audited using a timing attack
680
- # with a high timeout in order to determine when the effects of a timing
681
- # attack has worn off in order to safely continue the audit.
467
+ # If a block has been provided it calls {Arachni::Element::Capabilities::Auditable#audit}
468
+ # for every element, otherwise, it defaults to {#audit_taint}.
682
469
  #
683
- # @param [Arachni::Element::Auditable] elem
470
+ # Uses {#candidate_elements} to decide which elements to audit.
684
471
  #
685
- def self.audit_timeout_stabilize( elem )
686
-
687
- d_opts = {
688
- :skip_orig => true,
689
- :redundant => true,
690
- :timeout => 120000,
691
- :silent => true,
692
- :async => false
693
- }
694
-
695
- orig_opts = elem.opts
696
-
697
- elem.get_auditor.print_info( 'Waiting for the effects of the timing attack to wear off.' )
698
- elem.get_auditor.print_info( 'Max waiting time: ' + ( d_opts[:timeout] /1000 ).to_s + ' seconds.' )
699
-
700
- elem.auditable = elem.orig
701
- res = elem.submit( d_opts ).response
702
-
703
- if !res.timed_out?
704
- elem.get_auditor.print_info( 'Server seems responsive again.' )
472
+ # @see OPTIONS
473
+ # @see Arachni::Element::Capabilities::Auditable#audit
474
+ # @see #audit_taint
475
+ #
476
+ def audit( injection_str, opts = {}, &block )
477
+ opts = OPTIONS.merge( opts )
478
+ if !block_given?
479
+ audit_taint( injection_str, opts )
705
480
  else
706
- elem.get_auditor.print_error( 'Max waiting time exceeded, the server may be dead.' )
481
+ candidate_elements( opts ).each { |e| e.audit( injection_str, opts, &block ) }
707
482
  end
708
-
709
- elem.opts.merge!( orig_opts )
710
- end
711
-
712
- def audit_timeout_debug_msg( phase, delay )
713
- print_debug( '---------------------------------------------' )
714
- print_debug( "Running phase #{phase.to_s} of timing attack." )
715
- print_debug( "Delay set to: #{delay.to_s} milliseconds" )
716
- print_debug( '---------------------------------------------' )
717
483
  end
718
484
 
719
485
  #
720
- # Audits elements using a timing attack.
486
+ # Provides easy access to element auditing using simple taint analysis.
721
487
  #
722
- # 'opts' needs to contain a :timeout value in milliseconds.</br>
723
- # Optionally, you can add a :timeout_divider.
488
+ # Uses {#candidate_elements} to decide which elements to audit.
724
489
  #
725
- # @param [Array] strings injection strings
726
- # '__TIME__' will be substituted with (timeout / timeout_divider)
727
- # @param [Hash] opts options as described in {OPTIONS}
728
- # @param [Block] &block block to call if a timeout occurs,
729
- # it will be passed the response and opts
490
+ # @see OPTIONS
491
+ # @see Arachni::Element::Analysis::Taint
730
492
  #
731
- def timing_attack( strings, opts, &block )
732
-
733
- opts[:timeout_divider] ||= 1
734
-
735
- [strings].flatten.each {
736
- |str|
737
-
738
- opts[:timing_string] = str
739
- str = str.gsub( '__TIME__', ( (opts[:timeout] + 3 * opts[:timeout_divider]) / opts[:timeout_divider] ).to_s )
740
- opts[:skip_orig] = true
741
-
742
- audit( str, opts ) {
743
- |res, c_opts, elem|
744
-
745
- call_on_timing_blocks( res, elem )
746
- block.call( res, c_opts, elem ) if block && res.timed_out?
747
- }
748
- }
749
-
750
- @http.run
493
+ def audit_taint( taint, opts = {} )
494
+ opts = OPTIONS.merge( opts )
495
+ candidate_elements( opts ).each { |e| e.taint_analysis( taint, opts ) }
751
496
  end
752
497
 
753
498
  #
754
- # Audits all elements types in opts[:elements] (or self.class.info[:elements]
755
- # if there are none in opts) using differential analysis attacks.
756
- #
757
- # opts = {
758
- # :precision => 3,
759
- # :faults => [ 'fault injections' ],
760
- # :bools => [ 'boolean injections' ]
761
- # }
762
- #
763
- # audit_rdiff( opts )
764
- #
765
- # Here's how it goes:
766
- # let default be the default/original response
767
- # let fault be the response of the fault injection
768
- # let bool be the response of the boolean injection
499
+ # Audits elements using differential analysis attacks.
769
500
  #
770
- # a vulnerability is logged if default == bool AND bool.code == 200 AND fault != bool
501
+ # Uses {#candidate_elements} to decide which elements to audit.
771
502
  #
772
- # The "bool" response is also checked in order to determine if it's a custom 404, if it is it'll be skipped.
773
- #
774
- # If a block has been provided analysis and logging will be delegated to it.
775
- #
776
- # @param [Hash] opts available options:
777
- # * :format -- as seen in {OPTIONS}
778
- # * :elements -- as seen in {OPTIONS}
779
- # * :train -- as seen in {OPTIONS}
780
- # * :precision -- amount of rdiff iterations
781
- # * :faults -- array of fault injection strings (these are supposed to force erroneous conditions when interpreted)
782
- # * :bools -- array of boolean injection strings (these are supposed to not alter the webapp behavior when interpreted)
783
- # @param [Block] &block block to be used for custom analysis of responses; will be passed the following:
784
- # * injected string
785
- # * audited element
786
- # * default response body
787
- # * boolean response
788
- # * fault injection response body
503
+ # @see OPTIONS
504
+ # @see Arachni::Element::Analysis::RDiff
789
505
  #
790
506
  def audit_rdiff( opts = {}, &block )
791
-
792
- if( !opts.include?( :elements) || !opts[:elements] || opts[:elements].empty? )
793
- opts[:elements] = self.class.info[:elements]
794
- end
795
-
796
- if( !opts.include?( :elements) || !opts[:elements] || opts[:elements].empty? )
797
- opts[:elements] = OPTIONS[:elements]
798
- end
799
-
800
- opts[:elements].each {
801
- |elem|
802
-
803
- case elem
804
-
805
- when Element::LINK
806
- next if !Options.instance.audit_links
807
- @page.links.each {
808
- |c_elem|
809
- audit_rdiff_elem( c_elem, opts, &block )
810
- }
811
-
812
- when Element::FORM
813
- next if !Options.instance.audit_forms
814
- @page.forms.each {
815
- |c_elem|
816
- audit_rdiff_elem( c_elem, opts, &block )
817
- }
818
-
819
- when Element::COOKIE
820
- next if !Options.instance.audit_cookies
821
- @page.cookies.each {
822
- |c_elem|
823
- audit_rdiff_elem( c_elem, opts, &block )
824
- }
825
-
826
- when Element::HEADER
827
- next if !Options.instance.audit_headers
828
- @page.headers.each {
829
- |c_elem|
830
- audit_rdiff_elem( c_elem, opts, &block )
831
- }
832
- when Element::BODY
833
- else
834
- raise( 'Unknown element to audit: ' + elem.to_s )
835
-
836
- end
837
-
838
- }
507
+ opts = OPTIONS.merge( opts )
508
+ candidate_elements( opts ).each { |e| e.rdiff_analysis( opts, &block ) }
839
509
  end
840
510
 
841
511
  #
842
- # Audits a single element using an rdiff attack.
512
+ # Audits elements using timing attacks and automatically logs results.
843
513
  #
844
- # @param [Arachni::Element::Auditable] elem the element to audit
845
- # @param [Hash] opts same as for {#audit_rdiff}
846
- # @param [Block] &block same as for {#audit_rdiff}
514
+ # Uses {#candidate_elements} to decide which elements to audit.
847
515
  #
848
- def audit_rdiff_elem( elem, opts = {}, &block )
849
-
850
- opts = RDIFF_OPTIONS.merge( opts )
851
-
852
- # don't continue if there's a missing value
853
- elem.auditable.values.each {
854
- |val|
855
- return if !val || val.empty?
856
- }
857
-
858
- return if __rdiff_audited?( elem )
859
- __rdiff_audited!( elem )
860
-
861
- responses = {
862
- :orig => nil,
863
- :good => {},
864
- :bad => {},
865
- :bad_total => 0,
866
- :good_total => 0
867
- }
868
-
869
- elem.auditor( self )
870
- opts[:precision].times {
871
- # get the default responses
872
- elem.audit( '', opts ) {
873
- |res|
874
- responses[:orig] ||= res.body
875
- # remove context-irrelevant dynamic content like banners and such
876
- # from the error page
877
- responses[:orig] = responses[:orig].rdiff( res.body )
878
- }
879
- }
880
-
881
- opts[:precision].times {
882
- opts[:faults].each {
883
- |str|
884
-
885
- # get injection variations that will hopefully cause an internal/silent
886
- # SQL error
887
- variations = elem.injection_sets( str, opts )
888
-
889
- responses[:bad_total] = variations.size
890
-
891
- variations.each {
892
- |c_elem|
893
-
894
- print_status( c_elem.get_status_str( c_elem.altered ) )
895
-
896
- # register us as the auditor
897
- c_elem.auditor( self )
898
- # submit the link and get the response
899
- c_elem.submit( opts ).on_complete {
900
- |res|
901
-
902
- responses[:bad][c_elem.altered] ||= res.body.clone
903
-
904
- # remove context-irrelevant dynamic content like banners and such
905
- # from the error page
906
- responses[:bad][c_elem.altered] =
907
- responses[:bad][c_elem.altered].rdiff( res.body.clone )
908
- }
909
- }
910
- }
911
- }
912
-
913
- opts[:bools].each {
914
- |str|
915
-
916
- # get injection variations that will not affect the outcome of the query
917
- variations = elem.injection_sets( str, opts )
918
-
919
- responses[:good_total] = variations.size
920
-
921
- variations.each {
922
- |c_elem|
923
-
924
- print_status( c_elem.get_status_str( c_elem.altered ) )
925
-
926
- # register us as the auditor
927
- c_elem.auditor( self )
928
- # submit the link and get the response
929
- c_elem.submit( opts ).on_complete {
930
- |res|
931
-
932
- responses[:good][c_elem.altered] ||= []
933
-
934
- # save the response for later analysis
935
- responses[:good][c_elem.altered] << {
936
- 'str' => str,
937
- 'res' => res,
938
- 'elem' => c_elem
939
- }
940
- }
941
- }
942
- }
943
-
944
- # when this runs the 'responses' hash will have been populated
945
- @http.after_run {
946
-
947
- responses[:good].keys.each {
948
- |key|
949
-
950
- responses[:good][key].each {
951
- |res|
952
-
953
- if block
954
- block.call( res['str'], res['elem'], responses[:orig], res['res'], responses[:bad][key] )
955
- elsif( responses[:orig] == res['res'].body &&
956
- responses[:bad][key] != res['res'].body &&
957
- !@http.custom_404?( res['res'] ) && res['res'].code == 200 )
958
-
959
- url = res['res'].effective_url
960
-
961
- # since we bypassed the auditor completely we need to create
962
- # our own opts hash and pass it to the Vulnerability class.
963
- #
964
- # this is only required for Metasploitable vulnerabilities
965
- opts = {
966
- :injected_orig => res['str'],
967
- :combo => res['elem'].auditable
968
- }
969
-
970
- issue = Issue.new( {
971
- :var => key,
972
- :url => url,
973
- :method => res['res'].request.method.to_s,
974
- :opts => opts,
975
- :injected => res['str'],
976
- :id => res['str'],
977
- :regexp => 'n/a',
978
- :regexp_match => 'n/a',
979
- :elem => res['elem'].type,
980
- :response => res['res'].body,
981
- # :verification => true,
982
- :headers => {
983
- :request => res['res'].request.headers,
984
- :response => res['res'].headers,
985
- }
986
- }.merge( self.class.info )
987
- )
988
-
989
- print_ok( "In #{res['elem'].type} var '#{key}' ( #{url} )" )
990
-
991
- # register our results with the system
992
- register_results( [ issue ] )
993
- end
994
-
995
- }
996
- }
997
- }
998
- end
999
-
1000
- def __rdiff_audited!( elem )
1001
- @@__rdiff_audited << __rdiff_audit_id( elem )
516
+ # @see OPTIONS
517
+ # @see Arachni::Element::Analysis::Timeout
518
+ #
519
+ def audit_timeout( strings, opts = {} )
520
+ opts = OPTIONS.merge( opts )
521
+ candidate_elements( opts ).each { |e| e.timeout_analysis( strings, opts ) }
1002
522
  end
1003
523
 
1004
- def __rdiff_audited?( elem )
1005
- @@__rdiff_audited.include?( __rdiff_audit_id( elem ) )
1006
- end
1007
524
 
1008
- def __rdiff_audit_id( elem )
1009
- elem.action + elem.auditable.keys.to_s
1010
- end
525
+ private
1011
526
 
1012
527
  #
1013
- # Provides the following methods:
1014
- # * audit_links()
1015
- # * audit_forms()
1016
- # * audit_cookies()
1017
- # * audit_headers()
528
+ # Helper +Set+ for modules which want to keep track of what they've audited
529
+ # by themselves.
1018
530
  #
1019
- # Metaprogrammed to avoid redundant code while maintaining compatibility
1020
- # and method shortcuts.
1021
- #
1022
- # @see #audit_elems
1023
- #
1024
- def method_missing( sym, *args, &block )
1025
-
1026
- elem = sym.to_s.gsub!( 'audit_', '@' )
1027
- raise NoMethodError.new( "Undefined method '#{sym.to_s}'.", sym, args ) if !elem
1028
-
1029
- elems = @page.instance_variable_get( elem )
1030
-
1031
- if( elems && elem )
1032
- raise ArgumentError.new( "Missing required argument 'injection_str'" +
1033
- " for audit_#{elem.gsub( '@', '' )}()." ) if( !args[0] )
1034
- audit_elems( elems, args[0], args[1] ? args[1]: {}, &block )
1035
- else
1036
- raise NoMethodError.new( "Undefined method '#{sym.to_s}'.", sym, args )
1037
- end
1038
- end
1039
-
1040
- #
1041
- # Audits Auditable HTML/HTTP elements
531
+ # @return [Set]
1042
532
  #
1043
- # @param [Array<Arachni::Element::Auditable>] elements elements to audit
1044
- # @param [String] injection_str same as for {#audit}
1045
- # @param [Hash] opts same as for {#audit}
1046
- # @param [Block] &block same as for {#audit}
533
+ # @see #audited?
534
+ # @see #audited
1047
535
  #
1048
- # @see #method_missing
1049
536
  #
1050
- def audit_elems( elements, injection_str, opts = { }, &block )
1051
-
1052
- opts = OPTIONS.merge( opts )
1053
- url = @page.url
1054
-
1055
- opts[:injected_orig] = injection_str
1056
-
1057
- elements.deep_clone.each {
1058
- |elem|
1059
- elem.auditor( self )
1060
- elem.audit( injection_str, opts, &block )
1061
- }
537
+ def self.audited
538
+ @audited ||= BloomFilter.new
1062
539
  end
1063
540
 
1064
541
  end