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,293 @@
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
+ require Options.instance.dir['lib'] + 'component_options'
14
+
15
+ #
16
+ # Component Manager
17
+ #
18
+ # Handles modules, reports, path extrator modules, plug-ins, pretty much
19
+ # every modular aspect of the framework.
20
+ #
21
+ # It is usually extended to fill-in for system specific functionality.
22
+ #
23
+ # @author: Tasos "Zapotek" Laskos
24
+ # <tasos.laskos@gmail.com>
25
+ # <zapotek@segfault.gr>
26
+ # @version: 0.1
27
+ #
28
+ class ComponentManager < Hash
29
+
30
+ include Arachni::UI::Output
31
+
32
+
33
+ #
34
+ # The following are used by {#parse}:
35
+ # * '*' means all modules
36
+ # * module names prefixed with '-' will be excluded
37
+ #
38
+ WILDCARD = '*'
39
+ EXCLUDE = '-'
40
+
41
+ #
42
+ # @param [String] lib the path to the component library/folder
43
+ # @param [Module] parent the parent module of the components
44
+ #
45
+ def initialize( lib, parent )
46
+ @lib = lib
47
+ @parent = parent
48
+ end
49
+
50
+ #
51
+ # Loads components.
52
+ #
53
+ # @param [Array] components array of names of components to load
54
+ #
55
+ def load( components )
56
+ parse( components ).each {
57
+ |component|
58
+ self.[]( component )
59
+ }
60
+ end
61
+
62
+ #
63
+ # Validates and prepares options for a given component.
64
+ #
65
+ # @param [String] component_name the name of the component
66
+ # @param [Class] component the component
67
+ # @param [Hash] user_opts the user options
68
+ #
69
+ # @return [Hash] the prepared options to be passed to the component
70
+ #
71
+ def prep_opts( component_name, component, user_opts = {} )
72
+ info = component.info
73
+ return {} if !info.include?( :options ) || info[:options].empty?
74
+
75
+ user_opts ||= {}
76
+ options = { }
77
+ errors = { }
78
+ info[:options].each {
79
+ |opt|
80
+
81
+ name = opt.name
82
+ val = user_opts[name]
83
+
84
+ if( opt.empty_required_value?( val ) )
85
+ errors[name] = {
86
+ :opt => opt,
87
+ :value => val,
88
+ :type => :empty_required_value
89
+ }
90
+ elsif( !opt.valid?( val ) )
91
+ errors[name] = {
92
+ :opt => opt,
93
+ :value => val,
94
+ :type => :invalid
95
+ }
96
+ end
97
+
98
+ val = !val.nil? ? val : opt.default
99
+ options[name] = opt.normalize( val )
100
+ }
101
+
102
+ if( !errors.empty? )
103
+ print_errors( component_name, errors )
104
+ end
105
+
106
+ return options
107
+ end
108
+
109
+
110
+ #
111
+ # It parses the component array making sure that its structure is valid
112
+ #
113
+ # @param [Array] components array of component names
114
+ #
115
+ # @return [Array] array of modules to load
116
+ #
117
+ def parse( components )
118
+ unload = []
119
+ load = []
120
+
121
+ return load if components[0] == EXCLUDE
122
+
123
+ components.each {
124
+ |component|
125
+ if component[0] == EXCLUDE
126
+ component[0] = ''
127
+
128
+ if component[WILDCARD]
129
+ unload |= wilcard_to_names( component )
130
+ else
131
+ unload << component
132
+ end
133
+
134
+ end
135
+ }
136
+
137
+ if( !components.include?( WILDCARD ) )
138
+
139
+ avail_components = available( )
140
+
141
+ components.each {
142
+ |component|
143
+
144
+ if component.substring?( WILDCARD )
145
+ load |= wilcard_to_names( component )
146
+ else
147
+
148
+ if( avail_components.include?( component ) )
149
+ load << component
150
+ else
151
+ raise( Arachni::Exceptions::ComponentNotFound,
152
+ "Error: Component #{component} wasn't found." )
153
+ end
154
+ end
155
+
156
+ }
157
+ load.flatten!
158
+
159
+ else
160
+ available( ).map {
161
+ |component|
162
+ load << component
163
+ }
164
+ end
165
+
166
+ return load - unload
167
+ end
168
+
169
+ #
170
+ # Returns a component class object by name, loading it on the fly need be.
171
+ #
172
+ # @param [String] name component name
173
+ #
174
+ # @return [Class]
175
+ #
176
+ def []( name )
177
+
178
+ return fetch( name ) if include?( name )
179
+
180
+ paths.each {
181
+ |path|
182
+
183
+ next if name != path_to_name( path )
184
+ self[path_to_name( path )] = load_from_path( path )
185
+ }
186
+
187
+ return fetch( name ) rescue nil
188
+ end
189
+
190
+ def wilcard_to_names( name )
191
+ if name[WILDCARD]
192
+ return paths.map {
193
+ |path|
194
+ path_to_name( path ) if path.match( Regexp.new( name ) )
195
+ }.compact
196
+ end
197
+
198
+ return
199
+ end
200
+
201
+ #
202
+ # Returns array of available component names.
203
+ #
204
+ # @return [Array]
205
+ #
206
+ def available
207
+ components = []
208
+ paths.each {
209
+ |path|
210
+ name = path_to_name( path )
211
+ components << name
212
+ }
213
+ return components
214
+ end
215
+
216
+ #
217
+ # Converts the name of a component to a file-path.
218
+ #
219
+ # @param [String] name the name of the component
220
+ #
221
+ # @return [String]
222
+ #
223
+ def name_to_path( name )
224
+ paths.each {
225
+ |path|
226
+ return path if name == path_to_name( path )
227
+ }
228
+ return
229
+ end
230
+
231
+ #
232
+ # Converts the path of a component to a component name.
233
+ #
234
+ # @param [String] path the file-path of the component
235
+ #
236
+ # @return [String]
237
+ #
238
+ def path_to_name( path )
239
+ File.basename( path, '.rb' )
240
+ end
241
+
242
+ #
243
+ # Returns the paths of all available components (excluding helper files).
244
+ #
245
+ # @return [Array]
246
+ #
247
+ def paths
248
+ cpaths = paths = Dir.glob( File.join( "#{@lib}**", "*.rb" ) )
249
+ return paths.reject { |path| helper?( path ) }
250
+ end
251
+
252
+ private
253
+
254
+ def print_errors( name, errors )
255
+
256
+ print_line
257
+ print_line
258
+
259
+ print_error( "Invalid options for component: #{name}" )
260
+
261
+ errors.each {
262
+ |optname, error|
263
+
264
+ val = error[:value].nil? ? '<empty>' : error[:value]
265
+
266
+ if( error[:type] == :invalid )
267
+ msg = "Invalid type"
268
+ else
269
+ msg = "Empty required value"
270
+ end
271
+
272
+ print_info( " * #{msg}: #{optname} => #{val}" )
273
+ print_info( " * Expected type: #{error[:opt].type}" )
274
+
275
+ print_line
276
+ }
277
+
278
+ exit
279
+ end
280
+
281
+ def load_from_path( path )
282
+ ::Kernel::load( path )
283
+ return @parent.const_get( @parent.constants[-1] )
284
+ end
285
+
286
+
287
+ def helper?( path )
288
+ return File.exist?( File.dirname( path ) + '.rb' )
289
+ end
290
+
291
+ end
292
+
293
+ end
@@ -0,0 +1,395 @@
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
+ #
14
+ # The following are pretty much rip offs of Metasploit's
15
+ # /lib/msf/core/option_container.rb
16
+ #
17
+ #
18
+
19
+ ###
20
+ #
21
+ # The base class for all options.
22
+ #
23
+ ###
24
+ class OptBase
25
+
26
+ #
27
+ # The name of the option.
28
+ #
29
+ attr_reader :name
30
+
31
+ #
32
+ # Whether or not the option is required.
33
+ #
34
+ attr_reader :required
35
+
36
+ #
37
+ # The description of the option.
38
+ #
39
+ attr_reader :desc
40
+
41
+ #
42
+ # The default value of the option.
43
+ #
44
+ attr_reader :default
45
+
46
+ #
47
+ # Storing the name of the option.
48
+ #
49
+ attr_writer :name
50
+
51
+ #
52
+ # The component that owns this option.
53
+ #
54
+ attr_accessor :owner
55
+
56
+ #
57
+ # The list of potential valid values
58
+ #
59
+ attr_accessor :enums
60
+
61
+
62
+ #
63
+ # Initializes a named option with the supplied attribute array.
64
+ # The array is composed of three values.
65
+ #
66
+ # attrs[0] = required (boolean type)
67
+ # attrs[1] = description (string)
68
+ # attrs[2] = default value
69
+ # attrs[3] = possible enum values
70
+ #
71
+ # @param [String] name the name of the options
72
+ # @param [Array] attrs option attributes
73
+ #
74
+ def initialize( name, attrs = [] )
75
+ @name = name
76
+ @required = attrs[0] || false
77
+ @desc = attrs[1]
78
+ @default = attrs[2]
79
+ @enums = [ *(attrs[3]) ].map { |x| x.to_s }
80
+ end
81
+
82
+ #
83
+ # Returns true if this is a required option.
84
+ #
85
+ def required?
86
+ return required
87
+ end
88
+
89
+ #
90
+ # Returns true if the supplied type is equivalent to this option's type.
91
+ #
92
+ def type?( in_type )
93
+ return (type == in_type)
94
+ end
95
+
96
+ #
97
+ # If it's required and the value is nil or empty, then it's not valid.
98
+ #
99
+ def valid?( value )
100
+ return ( required? && ( value == nil || value.to_s.empty? ) ) ? false : true
101
+ end
102
+
103
+ #
104
+ # Returns true if the value supplied is nil and it's required to be
105
+ # a valid value
106
+ #
107
+ def empty_required_value?( value )
108
+ return ( required? && value.nil? )
109
+ end
110
+
111
+ #
112
+ # Normalizes the supplied value to conform with the type that the option is
113
+ # conveying.
114
+ #
115
+ def normalize( value )
116
+ value
117
+ end
118
+
119
+ #
120
+ # Converts the Options object to hash
121
+ #
122
+ # @return [Hash]
123
+ #
124
+ def to_h
125
+ hash = Hash.new
126
+ self.instance_variables.each {
127
+ |var|
128
+ hash[var.to_s.gsub( /@/, '' )] = self.instance_variable_get( var )
129
+ }
130
+ return hash
131
+ end
132
+
133
+
134
+ protected
135
+
136
+ attr_writer :required, :desc, :default # :nodoc:
137
+ end
138
+
139
+ ###
140
+ #
141
+ # Core option types. The core supported option types are:
142
+ #
143
+ # OptString - Multi-byte character string
144
+ # OptBool - Boolean true or false indication
145
+ # OptPort - TCP/UDP service port
146
+ # OptPath - Path name on disk
147
+ # OptInt - An integer value
148
+ # OptEnum - Select from a set of valid values
149
+ #
150
+ ###
151
+
152
+ ###
153
+ #
154
+ # Mult-byte character string option.
155
+ #
156
+ ###
157
+ class OptString < OptBase
158
+ def type
159
+ return 'string'
160
+ end
161
+
162
+ def normalize(value)
163
+ if (value =~ /^file:(.*)/)
164
+ path = $1
165
+ begin
166
+ value = File.read(path)
167
+ rescue ::Errno::ENOENT, ::Errno::EISDIR
168
+ value = nil
169
+ end
170
+ end
171
+ value
172
+ end
173
+
174
+ def valid?(value=self.value)
175
+ value = normalize(value)
176
+ return false if empty_required_value?(value)
177
+ return super
178
+ end
179
+ end
180
+
181
+ ###
182
+ #
183
+ # Boolean option.
184
+ #
185
+ ###
186
+ class OptBool < OptBase
187
+
188
+ TrueRegex = /^(y|yes|t|1|true)$/i
189
+
190
+ def type
191
+ return 'bool'
192
+ end
193
+
194
+ def valid?(value)
195
+ return false if empty_required_value?(value)
196
+
197
+ if ((value != nil and
198
+ (value.to_s.empty? == false) and
199
+ (value.to_s.match(/^(y|yes|n|no|t|f|0|1|true|false)$/i) == nil)))
200
+ return false
201
+ end
202
+
203
+ true
204
+ end
205
+
206
+ def normalize(value)
207
+ if(value.nil? or value.to_s.match(TrueRegex).nil?)
208
+ false
209
+ else
210
+ true
211
+ end
212
+ end
213
+
214
+ def is_true?(value)
215
+ return normalize(value)
216
+ end
217
+
218
+ def is_false?(value)
219
+ return !is_true?(value)
220
+ end
221
+
222
+ end
223
+
224
+ ###
225
+ #
226
+ # Enum option.
227
+ #
228
+ ###
229
+ class OptEnum < OptBase
230
+
231
+ def type
232
+ return 'enum'
233
+ end
234
+
235
+ def valid?(value=self.value)
236
+ return false if empty_required_value?(value)
237
+
238
+ (value and self.enums.include?(value.to_s))
239
+ end
240
+
241
+ def normalize(value=self.value)
242
+ return nil if not self.valid?(value)
243
+ return value.to_s
244
+ end
245
+
246
+ def desc=(value)
247
+ self.desc_string = value
248
+
249
+ self.desc
250
+ end
251
+
252
+ def desc
253
+ if self.enums
254
+ str = self.enums.join(', ')
255
+ end
256
+ "#{self.desc_string || ''} (accepted: #{str})"
257
+ end
258
+
259
+
260
+ protected
261
+
262
+ attr_accessor :desc_string # :nodoc:
263
+
264
+ end
265
+
266
+ ###
267
+ #
268
+ # Network port option.
269
+ #
270
+ ###
271
+ class OptPort < OptBase
272
+ def type
273
+ return 'port'
274
+ end
275
+
276
+ def valid?(value)
277
+ return false if empty_required_value?(value)
278
+
279
+ if ((value != nil and value.to_s.empty? == false) and
280
+ ((value.to_s.match(/^\d+$/) == nil or value.to_i < 0 or value.to_i > 65535)))
281
+ return false
282
+ end
283
+
284
+ return super
285
+ end
286
+ end
287
+
288
+ ###
289
+ #
290
+ # URL option.
291
+ #
292
+ ###
293
+ class OptUrl < OptBase
294
+ def type
295
+ return 'url'
296
+ end
297
+
298
+ def valid?(value)
299
+ return false if empty_required_value?(value)
300
+
301
+ if (value != nil and value.empty? == false)
302
+ require 'uri'
303
+ require 'socket'
304
+ begin
305
+ ::IPSocket.getaddress( URI( value ).host )
306
+ rescue
307
+ return false
308
+ end
309
+ end
310
+
311
+ return super
312
+ end
313
+ end
314
+
315
+
316
+ ###
317
+ #
318
+ # Network address option.
319
+ #
320
+ ###
321
+ class OptAddress < OptBase
322
+ def type
323
+ return 'address'
324
+ end
325
+
326
+ def valid?(value)
327
+ return false if empty_required_value?(value)
328
+
329
+ if (value != nil and value.empty? == false)
330
+ require 'socket'
331
+ begin
332
+ ::IPSocket.getaddress( value )
333
+ rescue
334
+ return false
335
+ end
336
+ end
337
+
338
+ return super
339
+ end
340
+ end
341
+
342
+
343
+ ###
344
+ #
345
+ # File system path option.
346
+ #
347
+ ###
348
+ class OptPath < OptBase
349
+ def type
350
+ return 'path'
351
+ end
352
+
353
+ def valid?(value)
354
+ return false if empty_required_value?(value)
355
+
356
+ if ((value != nil and value.empty? == false) and
357
+ (File.exists?(value) == false))
358
+ return false
359
+ end
360
+
361
+ return super
362
+ end
363
+ end
364
+
365
+ ###
366
+ #
367
+ # Integer option.
368
+ #
369
+ ###
370
+ class OptInt < OptBase
371
+ def type
372
+ return 'integer'
373
+ end
374
+
375
+ def normalize(value)
376
+ if (value.to_s.match(/^0x[a-fA-F\d]+$/))
377
+ value.to_i(16)
378
+ else
379
+ value.to_i
380
+ end
381
+ end
382
+
383
+ def valid?(value)
384
+ return false if empty_required_value?(value)
385
+
386
+ if value and not normalize(value).to_s.match(/^\d+$/)
387
+ return false
388
+ end
389
+
390
+ return super
391
+ end
392
+ end
393
+
394
+ end
395
+