arachni 0.2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. data/ACKNOWLEDGMENTS.md +14 -0
  2. data/AUTHORS.md +6 -0
  3. data/CHANGELOG.md +162 -0
  4. data/CONTRIBUTORS.md +10 -0
  5. data/EXPLOITATION.md +429 -0
  6. data/HACKING.md +101 -0
  7. data/LICENSE.md +341 -0
  8. data/README.md +350 -0
  9. data/Rakefile +86 -0
  10. data/bin/arachni +22 -0
  11. data/bin/arachni_web +77 -0
  12. data/bin/arachni_xmlrpc +21 -0
  13. data/bin/arachni_xmlrpcd +82 -0
  14. data/bin/arachni_xmlrpcd_monitor +74 -0
  15. data/conf/README.webui.yaml.txt +44 -0
  16. data/conf/webui.yaml +11 -0
  17. data/external/metasploit/LICENSE +24 -0
  18. data/external/metasploit/modules/exploits/unix/webapp/arachni_exec.rb +142 -0
  19. data/external/metasploit/modules/exploits/unix/webapp/arachni_path_traversal.rb +113 -0
  20. data/external/metasploit/modules/exploits/unix/webapp/arachni_php_eval.rb +150 -0
  21. data/external/metasploit/modules/exploits/unix/webapp/arachni_php_include.rb +141 -0
  22. data/external/metasploit/modules/exploits/unix/webapp/arachni_sqlmap.rb +92 -0
  23. data/external/metasploit/plugins/arachni.rb +536 -0
  24. data/getoptslong.rb +241 -0
  25. data/lib/anemone.rb +2 -0
  26. data/lib/anemone/cookie_store.rb +35 -0
  27. data/lib/anemone/core.rb +371 -0
  28. data/lib/anemone/exceptions.rb +5 -0
  29. data/lib/anemone/http.rb +144 -0
  30. data/lib/anemone/page.rb +337 -0
  31. data/lib/anemone/page_store.rb +160 -0
  32. data/lib/anemone/storage.rb +34 -0
  33. data/lib/anemone/storage/base.rb +75 -0
  34. data/lib/anemone/storage/exceptions.rb +15 -0
  35. data/lib/anemone/storage/mongodb.rb +89 -0
  36. data/lib/anemone/storage/pstore.rb +50 -0
  37. data/lib/anemone/storage/redis.rb +90 -0
  38. data/lib/anemone/storage/tokyo_cabinet.rb +57 -0
  39. data/lib/anemone/tentacle.rb +40 -0
  40. data/lib/arachni.rb +16 -0
  41. data/lib/audit_store.rb +346 -0
  42. data/lib/component_manager.rb +293 -0
  43. data/lib/component_options.rb +395 -0
  44. data/lib/exceptions.rb +76 -0
  45. data/lib/framework.rb +637 -0
  46. data/lib/http.rb +809 -0
  47. data/lib/issue.rb +302 -0
  48. data/lib/module.rb +4 -0
  49. data/lib/module/auditor.rb +455 -0
  50. data/lib/module/base.rb +188 -0
  51. data/lib/module/element_db.rb +158 -0
  52. data/lib/module/key_filler.rb +87 -0
  53. data/lib/module/manager.rb +87 -0
  54. data/lib/module/output.rb +68 -0
  55. data/lib/module/trainer.rb +240 -0
  56. data/lib/module/utilities.rb +110 -0
  57. data/lib/options.rb +547 -0
  58. data/lib/parser.rb +2 -0
  59. data/lib/parser/auditable.rb +522 -0
  60. data/lib/parser/elements.rb +296 -0
  61. data/lib/parser/page.rb +149 -0
  62. data/lib/parser/parser.rb +717 -0
  63. data/lib/plugin.rb +4 -0
  64. data/lib/plugin/base.rb +110 -0
  65. data/lib/plugin/manager.rb +162 -0
  66. data/lib/report.rb +4 -0
  67. data/lib/report/base.rb +119 -0
  68. data/lib/report/manager.rb +92 -0
  69. data/lib/rpc/xml/client/base.rb +71 -0
  70. data/lib/rpc/xml/client/dispatcher.rb +49 -0
  71. data/lib/rpc/xml/client/instance.rb +88 -0
  72. data/lib/rpc/xml/server/base.rb +90 -0
  73. data/lib/rpc/xml/server/dispatcher.rb +357 -0
  74. data/lib/rpc/xml/server/framework.rb +206 -0
  75. data/lib/rpc/xml/server/instance.rb +191 -0
  76. data/lib/rpc/xml/server/module/manager.rb +46 -0
  77. data/lib/rpc/xml/server/options.rb +124 -0
  78. data/lib/rpc/xml/server/output.rb +299 -0
  79. data/lib/rpc/xml/server/plugin/manager.rb +58 -0
  80. data/lib/ruby.rb +5 -0
  81. data/lib/ruby/object.rb +32 -0
  82. data/lib/ruby/string.rb +74 -0
  83. data/lib/ruby/xmlrpc/server.rb +27 -0
  84. data/lib/spider.rb +200 -0
  85. data/lib/typhoeus/request.rb +91 -0
  86. data/lib/typhoeus/response.rb +34 -0
  87. data/lib/ui/cli/cli.rb +744 -0
  88. data/lib/ui/cli/output.rb +279 -0
  89. data/lib/ui/web/log.rb +82 -0
  90. data/lib/ui/web/output_stream.rb +94 -0
  91. data/lib/ui/web/report_manager.rb +222 -0
  92. data/lib/ui/web/server.rb +903 -0
  93. data/lib/ui/web/server/db/placeholder +0 -0
  94. data/lib/ui/web/server/public/banner.png +0 -0
  95. data/lib/ui/web/server/public/bodybg-small.png +0 -0
  96. data/lib/ui/web/server/public/bodybg.png +0 -0
  97. data/lib/ui/web/server/public/css/smoothness/images/pbar-ani.gif +0 -0
  98. data/lib/ui/web/server/public/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  99. data/lib/ui/web/server/public/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  100. data/lib/ui/web/server/public/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  101. data/lib/ui/web/server/public/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  102. data/lib/ui/web/server/public/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  103. data/lib/ui/web/server/public/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  104. data/lib/ui/web/server/public/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  105. data/lib/ui/web/server/public/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  106. data/lib/ui/web/server/public/css/smoothness/images/ui-icons_222222_256x240.png +0 -0
  107. data/lib/ui/web/server/public/css/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  108. data/lib/ui/web/server/public/css/smoothness/images/ui-icons_454545_256x240.png +0 -0
  109. data/lib/ui/web/server/public/css/smoothness/images/ui-icons_888888_256x240.png +0 -0
  110. data/lib/ui/web/server/public/css/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  111. data/lib/ui/web/server/public/css/smoothness/jquery-ui-1.8.9.custom.css +573 -0
  112. data/lib/ui/web/server/public/favicon.ico +0 -0
  113. data/lib/ui/web/server/public/footer.jpg +0 -0
  114. data/lib/ui/web/server/public/icons/error.png +0 -0
  115. data/lib/ui/web/server/public/icons/info.png +0 -0
  116. data/lib/ui/web/server/public/icons/ok.png +0 -0
  117. data/lib/ui/web/server/public/icons/status.png +0 -0
  118. data/lib/ui/web/server/public/js/jquery-1.4.4.min.js +167 -0
  119. data/lib/ui/web/server/public/js/jquery-ui-1.8.9.custom.min.js +781 -0
  120. data/lib/ui/web/server/public/logo.png +0 -0
  121. data/lib/ui/web/server/public/nav-left.jpg +0 -0
  122. data/lib/ui/web/server/public/nav-right.jpg +0 -0
  123. data/lib/ui/web/server/public/nav-selected-left.jpg +0 -0
  124. data/lib/ui/web/server/public/nav-selected-right.jpg +0 -0
  125. data/lib/ui/web/server/public/reports/placeholder +1 -0
  126. data/lib/ui/web/server/public/sidebar-bottom.jpg +0 -0
  127. data/lib/ui/web/server/public/sidebar-h4.jpg +0 -0
  128. data/lib/ui/web/server/public/sidebar-top.jpg +0 -0
  129. data/lib/ui/web/server/public/spider.png +0 -0
  130. data/lib/ui/web/server/public/style.css +604 -0
  131. data/lib/ui/web/server/tmp/placeholder +0 -0
  132. data/lib/ui/web/server/views/dispatcher.erb +85 -0
  133. data/lib/ui/web/server/views/dispatcher_error.erb +14 -0
  134. data/lib/ui/web/server/views/error.erb +1 -0
  135. data/lib/ui/web/server/views/flash.erb +18 -0
  136. data/lib/ui/web/server/views/home.erb +14 -0
  137. data/lib/ui/web/server/views/instance.erb +213 -0
  138. data/lib/ui/web/server/views/layout.erb +95 -0
  139. data/lib/ui/web/server/views/log.erb +40 -0
  140. data/lib/ui/web/server/views/modules.erb +71 -0
  141. data/lib/ui/web/server/views/options.erb +23 -0
  142. data/lib/ui/web/server/views/output_results.erb +51 -0
  143. data/lib/ui/web/server/views/plugins.erb +42 -0
  144. data/lib/ui/web/server/views/report_formats.erb +30 -0
  145. data/lib/ui/web/server/views/reports.erb +55 -0
  146. data/lib/ui/web/server/views/settings.erb +120 -0
  147. data/lib/ui/web/server/views/welcome.erb +38 -0
  148. data/lib/ui/xmlrpc/dispatcher_monitor.rb +204 -0
  149. data/lib/ui/xmlrpc/xmlrpc.rb +843 -0
  150. data/logs/placeholder +0 -0
  151. data/metamodules/autothrottle.rb +74 -0
  152. data/metamodules/timeout_notice.rb +118 -0
  153. data/metamodules/uniformity.rb +98 -0
  154. data/modules/audit/code_injection.rb +136 -0
  155. data/modules/audit/code_injection_timing.rb +115 -0
  156. data/modules/audit/code_injection_timing/payloads.txt +4 -0
  157. data/modules/audit/csrf.rb +301 -0
  158. data/modules/audit/ldapi.rb +103 -0
  159. data/modules/audit/ldapi/errors.txt +26 -0
  160. data/modules/audit/os_cmd_injection.rb +103 -0
  161. data/modules/audit/os_cmd_injection/payloads.txt +2 -0
  162. data/modules/audit/os_cmd_injection_timing.rb +104 -0
  163. data/modules/audit/os_cmd_injection_timing/payloads.txt +3 -0
  164. data/modules/audit/path_traversal.rb +141 -0
  165. data/modules/audit/response_splitting.rb +105 -0
  166. data/modules/audit/rfi.rb +193 -0
  167. data/modules/audit/sqli.rb +120 -0
  168. data/modules/audit/sqli/regexp_ids.txt +90 -0
  169. data/modules/audit/sqli_blind_rdiff.rb +321 -0
  170. data/modules/audit/sqli_blind_timing.rb +103 -0
  171. data/modules/audit/sqli_blind_timing/payloads.txt +51 -0
  172. data/modules/audit/trainer.rb +89 -0
  173. data/modules/audit/unvalidated_redirect.rb +90 -0
  174. data/modules/audit/xpath.rb +104 -0
  175. data/modules/audit/xpath/errors.txt +26 -0
  176. data/modules/audit/xss.rb +99 -0
  177. data/modules/audit/xss_event.rb +134 -0
  178. data/modules/audit/xss_path.rb +125 -0
  179. data/modules/audit/xss_script_tag.rb +112 -0
  180. data/modules/audit/xss_tag.rb +112 -0
  181. data/modules/audit/xss_uri.rb +125 -0
  182. data/modules/recon/allowed_methods.rb +104 -0
  183. data/modules/recon/backdoors.rb +131 -0
  184. data/modules/recon/backdoors/filenames.txt +16 -0
  185. data/modules/recon/backup_files.rb +177 -0
  186. data/modules/recon/backup_files/extensions.txt +28 -0
  187. data/modules/recon/common_directories.rb +138 -0
  188. data/modules/recon/common_directories/directories.txt +265 -0
  189. data/modules/recon/common_files.rb +138 -0
  190. data/modules/recon/common_files/filenames.txt +17 -0
  191. data/modules/recon/directory_listing.rb +171 -0
  192. data/modules/recon/grep/captcha.rb +62 -0
  193. data/modules/recon/grep/credit_card.rb +85 -0
  194. data/modules/recon/grep/cvs_svn_users.rb +73 -0
  195. data/modules/recon/grep/emails.rb +59 -0
  196. data/modules/recon/grep/html_objects.rb +53 -0
  197. data/modules/recon/grep/private_ip.rb +54 -0
  198. data/modules/recon/grep/ssn.rb +53 -0
  199. data/modules/recon/htaccess_limit.rb +82 -0
  200. data/modules/recon/http_put.rb +95 -0
  201. data/modules/recon/interesting_responses.rb +118 -0
  202. data/modules/recon/unencrypted_password_forms.rb +119 -0
  203. data/modules/recon/webdav.rb +126 -0
  204. data/modules/recon/xst.rb +107 -0
  205. data/path_extractors/anchors.rb +35 -0
  206. data/path_extractors/forms.rb +35 -0
  207. data/path_extractors/frames.rb +38 -0
  208. data/path_extractors/generic.rb +39 -0
  209. data/path_extractors/links.rb +35 -0
  210. data/path_extractors/meta_refresh.rb +39 -0
  211. data/path_extractors/scripts.rb +37 -0
  212. data/path_extractors/sitemap.rb +31 -0
  213. data/plugins/autologin.rb +137 -0
  214. data/plugins/content_types.rb +90 -0
  215. data/plugins/cookie_collector.rb +99 -0
  216. data/plugins/form_dicattack.rb +185 -0
  217. data/plugins/healthmap.rb +94 -0
  218. data/plugins/http_dicattack.rb +133 -0
  219. data/plugins/metamodules.rb +118 -0
  220. data/plugins/proxy.rb +248 -0
  221. data/plugins/proxy/server.rb +66 -0
  222. data/plugins/waf_detector.rb +184 -0
  223. data/profiles/comprehensive.afp +74 -0
  224. data/profiles/full.afp +75 -0
  225. data/reports/afr.rb +59 -0
  226. data/reports/ap.rb +55 -0
  227. data/reports/html.rb +179 -0
  228. data/reports/html/default.erb +967 -0
  229. data/reports/metareport.rb +139 -0
  230. data/reports/metareport/arachni_metareport.rb +174 -0
  231. data/reports/plugin_formatters/html/content_types.rb +82 -0
  232. data/reports/plugin_formatters/html/cookie_collector.rb +66 -0
  233. data/reports/plugin_formatters/html/form_dicattack.rb +54 -0
  234. data/reports/plugin_formatters/html/healthmap.rb +76 -0
  235. data/reports/plugin_formatters/html/http_dicattack.rb +54 -0
  236. data/reports/plugin_formatters/html/metaformatters/timeout_notice.rb +65 -0
  237. data/reports/plugin_formatters/html/metaformatters/uniformity.rb +71 -0
  238. data/reports/plugin_formatters/html/metamodules.rb +93 -0
  239. data/reports/plugin_formatters/html/waf_detector.rb +54 -0
  240. data/reports/plugin_formatters/stdout/content_types.rb +73 -0
  241. data/reports/plugin_formatters/stdout/cookie_collector.rb +61 -0
  242. data/reports/plugin_formatters/stdout/form_dicattack.rb +52 -0
  243. data/reports/plugin_formatters/stdout/healthmap.rb +72 -0
  244. data/reports/plugin_formatters/stdout/http_dicattack.rb +53 -0
  245. data/reports/plugin_formatters/stdout/metaformatters/timeout_notice.rb +55 -0
  246. data/reports/plugin_formatters/stdout/metaformatters/uniformity.rb +68 -0
  247. data/reports/plugin_formatters/stdout/metamodules.rb +89 -0
  248. data/reports/plugin_formatters/stdout/waf_detector.rb +48 -0
  249. data/reports/plugin_formatters/xml/content_types.rb +91 -0
  250. data/reports/plugin_formatters/xml/cookie_collector.rb +70 -0
  251. data/reports/plugin_formatters/xml/form_dicattack.rb +57 -0
  252. data/reports/plugin_formatters/xml/healthmap.rb +82 -0
  253. data/reports/plugin_formatters/xml/http_dicattack.rb +57 -0
  254. data/reports/plugin_formatters/xml/metaformatters/timeout_notice.rb +67 -0
  255. data/reports/plugin_formatters/xml/metaformatters/uniformity.rb +82 -0
  256. data/reports/plugin_formatters/xml/metamodules.rb +91 -0
  257. data/reports/plugin_formatters/xml/waf_detector.rb +58 -0
  258. data/reports/stdout.rb +182 -0
  259. data/reports/txt.rb +77 -0
  260. data/reports/xml.rb +231 -0
  261. data/reports/xml/buffer.rb +98 -0
  262. metadata +516 -0
@@ -0,0 +1,57 @@
1
+ begin
2
+ require 'tokyocabinet'
3
+ rescue LoadError
4
+ puts "You need the tokyocabinet gem to use Anemone::Storage::TokyoCabinet"
5
+ exit
6
+ end
7
+
8
+ require 'forwardable'
9
+
10
+ module Anemone
11
+ module Storage
12
+ class TokyoCabinet
13
+ extend Forwardable
14
+
15
+ def_delegators :@db, :close, :size, :keys, :has_key?
16
+
17
+ def initialize(file)
18
+ raise "TokyoCabinet filename must have .tch extension" if File.extname(file) != '.tch'
19
+ @db = ::TokyoCabinet::HDB::new
20
+ @db.open(file, ::TokyoCabinet::HDB::OWRITER | ::TokyoCabinet::HDB::OCREAT)
21
+ @db.clear
22
+ end
23
+
24
+ def [](key)
25
+ if value = @db[key]
26
+ load_value(value)
27
+ end
28
+ end
29
+
30
+ def []=(key, value)
31
+ @db[key] = [Marshal.dump(value)].pack("m")
32
+ end
33
+
34
+ def delete(key)
35
+ value = self[key]
36
+ @db.delete(key)
37
+ value
38
+ end
39
+
40
+ def each
41
+ @db.each { |k, v| yield k, load_value(v) }
42
+ end
43
+
44
+ def merge!(hash)
45
+ hash.each { |key, value| self[key] = value }
46
+ self
47
+ end
48
+
49
+ private
50
+
51
+ def load_value(value)
52
+ Marshal.load(value.unpack("m")[0])
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,40 @@
1
+
2
+ require Arachni::Options.instance.dir['lib'] + 'anemone/http'
3
+
4
+ module Anemone
5
+ class Tentacle
6
+
7
+ #
8
+ # Create a new Tentacle
9
+ #
10
+ def initialize(link_queue, page_queue, opts = {})
11
+ @link_queue = link_queue
12
+ @page_queue = page_queue
13
+ @http = Anemone::HTTP.new(opts)
14
+ @opts = opts
15
+ end
16
+
17
+ #
18
+ # Gets links from @link_queue, and returns the fetched
19
+ # Page objects into @page_queue
20
+ #
21
+ def run
22
+ loop do
23
+ link, referer, depth = @link_queue.deq
24
+
25
+ break if link == :END
26
+
27
+ @http.fetch_pages(link, referer, depth).each { |page| @page_queue << page }
28
+
29
+ delay
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def delay
36
+ sleep @opts[:delay] if @opts[:delay] > 0
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,16 @@
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
+ module Arachni
12
+
13
+ # the universal system version
14
+ VERSION = '0.2.2.1'
15
+
16
+ end
@@ -0,0 +1,346 @@
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 'digest/md5'
12
+ module Arachni
13
+
14
+ require Options.instance.dir['lib'] + 'issue'
15
+
16
+ #
17
+ # Arachni::AuditStore class
18
+ #
19
+ # Represents a finished audit session.<br/>
20
+ # It holds information about the runtime environment,
21
+ # the results of the audit etc...
22
+ #
23
+ # @author: Tasos "Zapotek" Laskos
24
+ # <tasos.laskos@gmail.com>
25
+ # <zapotek@segfault.gr>
26
+ # @version: 0.1.1
27
+ #
28
+ class AuditStore
29
+
30
+ #
31
+ # @return [String] the version of the framework
32
+ #
33
+ attr_reader :version
34
+
35
+ #
36
+ # @return [String] the revision of the framework class
37
+ #
38
+ attr_reader :revision
39
+
40
+ #
41
+ # @return [Hash] the runtime arguments/options of the environment
42
+ #
43
+ attr_reader :options
44
+
45
+ #
46
+ # @return [Array] all the urls crawled
47
+ #
48
+ attr_reader :sitemap
49
+
50
+ #
51
+ # @return [Array<Issue>] the discovered issues
52
+ #
53
+ attr_reader :issues
54
+
55
+ attr_reader :plugins
56
+
57
+ #
58
+ # @return [String] the date and time when the audit started
59
+ #
60
+ attr_reader :start_datetime
61
+
62
+ #
63
+ # @return [String] the date and time when the audit finished
64
+ #
65
+ attr_reader :finish_datetime
66
+
67
+ #
68
+ # @return [String] how long the audit took
69
+ #
70
+ attr_reader :delta_time
71
+
72
+ attr_accessor :framework
73
+
74
+
75
+ ORDER = [
76
+ ::Arachni::Issue::Severity::HIGH,
77
+ ::Arachni::Issue::Severity::MEDIUM,
78
+ ::Arachni::Issue::Severity::LOW,
79
+ ::Arachni::Issue::Severity::INFORMATIONAL
80
+ ]
81
+
82
+ def initialize( audit = {}, framework )
83
+
84
+ @framework = framework
85
+
86
+ # set instance variables from audit opts
87
+ audit.each {
88
+ |k, v|
89
+ self.instance_variable_set( '@' + k.to_s, v )
90
+ }
91
+
92
+ @options = prepare_options( @options )
93
+ @issues = sort( prepare_variations( @issues ) )
94
+ @start_datetime = @options['start_datetime'].asctime
95
+
96
+ if @options['finish_datetime']
97
+ @finish_datetime = @options['finish_datetime'].asctime
98
+ else
99
+ @finish_datetime = Time.now.asctime
100
+ end
101
+
102
+ @delta_time = secs_to_hms( @options['delta_time'] )
103
+
104
+ end
105
+
106
+ #
107
+ # Loads and returns an AuditStore object from file
108
+ #
109
+ # @param [String] file the file to load
110
+ #
111
+ # @return [AuditStore]
112
+ #
113
+ def AuditStore.load( file )
114
+ begin
115
+ Marshal.load( IO.read( file ) )
116
+ rescue
117
+ YAML.load( IO.read( file ) )
118
+ end
119
+ end
120
+
121
+ #
122
+ # Saves 'self' to file
123
+ #
124
+ # @param [String] file
125
+ #
126
+ def save( file )
127
+ @framework = ''
128
+ f = File.open( file, 'w' )
129
+ begin
130
+ Marshal.dump( self, f )
131
+ rescue
132
+ YAML.dump( self, f )
133
+ end
134
+ end
135
+
136
+ #
137
+ # Returns 'self' and all objects in its instance vars as hashes
138
+ #
139
+ # @return [Hash]
140
+ #
141
+ def to_h
142
+
143
+ hash = obj_to_hash( self )
144
+
145
+ issues = []
146
+ hash['issues'].each {
147
+ |issue|
148
+ issues << obj_to_hash( issue )
149
+ }
150
+
151
+ hash['issues'] = issues
152
+ return hash
153
+ end
154
+
155
+ private
156
+
157
+ def sort( issues )
158
+ sorted = []
159
+ issues.each {
160
+ |issue|
161
+ sorted[ORDER.rindex( issue.severity )] ||= []
162
+ sorted[ORDER.rindex( issue.severity )] << issue
163
+ }
164
+
165
+ return sorted.flatten.reject{ |issue| issue.nil? }
166
+ end
167
+
168
+
169
+ #
170
+ # Converts obj to hash
171
+ #
172
+ # @param [Object] obj instance of an object
173
+ #
174
+ # @return [Hash]
175
+ #
176
+ def obj_to_hash( obj )
177
+ hash = Hash.new
178
+ obj.instance_variables.each {
179
+ |var|
180
+
181
+ key = var.to_s.gsub( /@/, '' )
182
+ hash[key] = obj.instance_variable_get( var )
183
+
184
+ }
185
+
186
+ return hash
187
+ end
188
+
189
+ #
190
+ # Prepares the hash to be stored in {AuditStore#options}
191
+ #
192
+ # The 'options' dimention of the array that initializes AuditObjects<br/>
193
+ # needs some more processing before being saved in {AuditStore#options}.
194
+ #
195
+ # @param [Hash]
196
+ #
197
+ # @return [Hash]
198
+ #
199
+ def prepare_options( options )
200
+ options['url'] = options['url'].to_s
201
+
202
+ new_options = Hash.new
203
+ options.each_pair {
204
+ |key, val|
205
+
206
+ new_options[key.to_s] = val
207
+
208
+ case key
209
+
210
+ when 'redundant'
211
+ new_options[key.to_s] = []
212
+ val.each {
213
+ |red|
214
+ new_options[key.to_s] << {
215
+ 'regexp' => red['regexp'].to_s,
216
+ 'count' => red['count']
217
+ }
218
+ }
219
+
220
+ when 'exclude', 'include'
221
+ new_options[key.to_s] = []
222
+ val.each {
223
+ |regexp|
224
+ new_options[key.to_s] << regexp.to_s
225
+ }
226
+
227
+ end
228
+
229
+ }
230
+
231
+ return new_options
232
+ end
233
+
234
+ #
235
+ # Parses the issues in "issue" and aggregates them
236
+ # creating variations of the same attacks.
237
+ #
238
+ # @see Issue#variations
239
+ #
240
+ # @param [Array<Issue>] issues
241
+ #
242
+ # @return [Array<Issue>] new array of Issue instances
243
+ # with populated {Issue#variations}
244
+ #
245
+ def prepare_variations( issues )
246
+
247
+ variation_keys = [
248
+ 'injected',
249
+ 'id',
250
+ 'regexp',
251
+ 'regexp_match',
252
+ 'headers',
253
+ 'response',
254
+ 'opts'
255
+ ]
256
+
257
+ new_issues = {}
258
+ issues.each {
259
+ |issue|
260
+
261
+ var = issue.var || ''
262
+
263
+ __id = issue.mod_name +
264
+ '::' + issue.elem + '::' +
265
+ var + '::' +
266
+ issue.url.split( /\?/ )[0]
267
+
268
+ orig_url = issue.url
269
+ issue.url = issue.url.split( /\?/ )[0]
270
+
271
+ if( !new_issues[__id] )
272
+ new_issues[__id] = issue
273
+ end
274
+
275
+ if( !new_issues[__id].variations )
276
+ new_issues[__id].variations = []
277
+ end
278
+
279
+ issue.headers ||= {}
280
+ issue.headers['request'] = issue.headers[:request] || {}
281
+ issue.headers['response'] = issue.headers[:response] || {}
282
+
283
+ new_issues[__id]._hash = Digest::MD5.hexdigest( __id )
284
+
285
+ modname = ''
286
+ @framework.modules.each_pair {
287
+ |name, mod|
288
+
289
+ if mod.info[:name] == new_issues[__id].mod_name
290
+ modname = name
291
+ break
292
+ end
293
+ }
294
+
295
+ new_issues[__id].internal_modname = modname
296
+
297
+ new_issues[__id].variations << {
298
+ 'url' => orig_url,
299
+ 'injected' => issue.injected,
300
+ 'id' => issue.id,
301
+ 'regexp' => issue.regexp,
302
+ 'regexp_match' => issue.regexp_match,
303
+ 'headers' => issue.headers,
304
+ 'response' => issue.response,
305
+ 'opts' => issue.opts ? issue.opts : {}
306
+ }
307
+
308
+ variation_keys.each {
309
+ |key|
310
+
311
+ if( new_issues[__id].instance_variable_defined?( '@' + key ) )
312
+ new_issues[__id].remove_instance_var( '@' + key )
313
+ end
314
+ }
315
+
316
+ }
317
+
318
+ issue_keys = new_issues.keys
319
+ new_issues = new_issues.to_a.flatten
320
+
321
+ issue_keys.each {
322
+ |key|
323
+ new_issues.delete( key )
324
+ }
325
+
326
+ new_issues
327
+ end
328
+
329
+ #
330
+ # Converts seconds to a (00:00:00) (hours:minutes:seconds) string
331
+ #
332
+ # @param [String,Float,Integer] seconds
333
+ #
334
+ # @return [String] hours:minutes:seconds
335
+ #
336
+ def secs_to_hms( secs )
337
+ secs = secs.to_i
338
+ return [secs/3600, secs/60 % 60, secs % 60].map {
339
+ |t|
340
+ t.to_s.rjust( 2, '0' )
341
+ }.join(':')
342
+ end
343
+
344
+ end
345
+
346
+ end