arachni 0.2.2.1

Sign up to get free protection for your applications and to get access to all the features.
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,27 @@
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
+ #
12
+ # Overloads the {XMLRPC::BasicServer} class with a clear_handlers() method.
13
+ #
14
+ # @author: Tasos "Zapotek" Laskos
15
+ # <tasos.laskos@gmail.com>
16
+ # <zapotek@segfault.gr>
17
+ # @version: 0.1
18
+ #
19
+ module XMLRPC
20
+ class BasicServer
21
+
22
+ def clear_handlers
23
+ @handler.clear
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,200 @@
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 Arachni::Options.instance.dir['lib'] + 'anemone'
12
+ require Arachni::Options.instance.dir['lib'] + 'module/utilities'
13
+
14
+ module Arachni
15
+
16
+ #
17
+ # Spider class
18
+ #
19
+ # Crawls the URL in opts[:url] and grabs the HTML code and headers.
20
+ #
21
+ # @author: Tasos "Zapotek" Laskos
22
+ # <tasos.laskos@gmail.com>
23
+ # <zapotek@segfault.gr>
24
+ # @version: 0.1
25
+ #
26
+ class Spider
27
+
28
+ include Arachni::UI::Output
29
+ include Arachni::Module::Utilities
30
+
31
+ #
32
+ #
33
+ # @return [Options]
34
+ #
35
+ attr_reader :opts
36
+
37
+ attr_reader :pages
38
+
39
+ #
40
+ # Sitemap, array of links
41
+ #
42
+ # @return [Array]
43
+ #
44
+ attr_reader :sitemap
45
+
46
+ #
47
+ # Code block to be executed on each page
48
+ #
49
+ # @return [Proc]
50
+ #
51
+ attr_reader :on_every_page_blocks
52
+
53
+ #
54
+ # Constructor <br/>
55
+ # Instantiates Spider class with user options.
56
+ #
57
+ # @param [Options] opts
58
+ #
59
+ def initialize( opts )
60
+ @opts = opts
61
+
62
+ @anemone_opts = {
63
+ :threads => 1,
64
+ :discard_page_bodies => false,
65
+ :delay => 0,
66
+ :obey_robots_txt => false,
67
+ :depth_limit => false,
68
+ :link_count_limit => false,
69
+ :redirect_limit => false,
70
+ :storage => nil,
71
+ :cookies => nil,
72
+ :accept_cookies => true,
73
+ :proxy_addr => nil,
74
+ :proxy_port => nil,
75
+ :proxy_user => nil,
76
+ :proxy_pass => nil
77
+ }
78
+
79
+ hash_opts = @opts.to_h
80
+ @anemone_opts.each_pair {
81
+ |k, v|
82
+ @anemone_opts[k] = hash_opts[k.to_s] if hash_opts[k.to_s]
83
+ }
84
+
85
+ @anemone_opts = @anemone_opts.merge( hash_opts )
86
+
87
+ @sitemap = []
88
+ @on_every_page_blocks = []
89
+
90
+ # if we have no 'include' patterns create one that will match
91
+ # everything, like '.*'
92
+ @opts.include =[ Regexp.new( '.*' ) ] if @opts.include.empty?
93
+ end
94
+
95
+ #
96
+ # Runs the Spider and passes parsed page to the block
97
+ #
98
+ # @param [Block] block
99
+ #
100
+ # @return [Arachni::Parser::Page]
101
+ #
102
+ def run( &block )
103
+ return if @opts.link_count_limit == 0
104
+
105
+ i = 1
106
+ # start the crawl
107
+ Anemone.crawl( @opts.url, @anemone_opts ) {
108
+ |anemone|
109
+
110
+ # apply 'exclude' patterns
111
+ anemone.skip_links_like( @opts.exclude ) if @opts.exclude
112
+
113
+ # apply 'include' patterns and grab matching pages
114
+ # as they are discovered
115
+ anemone.on_pages_like( @opts.include ) {
116
+ |page|
117
+
118
+ @pages = anemone.pages.keys || []
119
+
120
+ url = url_sanitize( page.url.to_s )
121
+
122
+ # something went kaboom, tell the user and skip the page
123
+ if page.error
124
+ print_error( "[Error: " + (page.error.to_s) + "] " + url )
125
+ print_debug_backtrace( page.error )
126
+ next
127
+ end
128
+
129
+ # push the url in the sitemap
130
+ @sitemap.push( url )
131
+
132
+ print_line
133
+ print_status( "[HTTP: #{page.code}] " + url )
134
+
135
+ # call the block...if we have one
136
+ if block
137
+ exception_jail{
138
+ new_page = Arachni::Parser.new( @opts,
139
+ Typhoeus::Response.new(
140
+ :effective_url => url,
141
+ :body => page.body,
142
+ :headers_hash => page.headers
143
+ )
144
+ ).run
145
+ new_page.code = page.code
146
+ new_page.method = 'GET'
147
+ block.call( new_page.clone )
148
+ }
149
+ end
150
+
151
+ # run blocks specified later
152
+ @on_every_page_blocks.each {
153
+ |block|
154
+ block.call( page )
155
+ }
156
+
157
+ # we don't need the HTML doc anymore
158
+ page.discard_doc!( )
159
+
160
+ # make sure we obey the link count limit and
161
+ # return if we have exceeded it.
162
+ if( @opts.link_count_limit &&
163
+ @opts.link_count_limit <= i )
164
+ return @sitemap.uniq
165
+ end
166
+
167
+ i+=1
168
+ }
169
+ }
170
+
171
+ return @sitemap.uniq
172
+ end
173
+
174
+ #
175
+ # Decodes URLs to reverse multiple encodes and removes NULL characters
176
+ #
177
+ def url_sanitize( url )
178
+
179
+ while( url =~ /%/ )
180
+ url = ( URI.decode( url ).to_s.unpack( 'A*' )[0] )
181
+ end
182
+
183
+ return url
184
+ end
185
+
186
+
187
+ #
188
+ # Hook for further analysis of pages, statistics etc.
189
+ #
190
+ # @param [Proc] block code to be executed for every page
191
+ #
192
+ # @return [self]
193
+ #
194
+ def on_every_page( &block )
195
+ @on_every_page_blocks.push( block )
196
+ self
197
+ end
198
+
199
+ end
200
+ end
@@ -0,0 +1,91 @@
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
+ #
12
+ # Override the on_complete methods of Typhoeus adding support
13
+ # for multiple on_complete blocks.
14
+ #
15
+ # Also added support for on demand training of the response and
16
+ # incremental request id numbers.
17
+ #
18
+ module Typhoeus
19
+
20
+ class Request
21
+
22
+ attr_accessor :id, :proxy, :proxy_username, :proxy_password,
23
+ :proxy_username, :proxy_password, :proxy_type
24
+
25
+ alias :old_initialize :initialize
26
+
27
+ def initialize( url, options = {} )
28
+
29
+ old_initialize( url, options )
30
+
31
+ @proxy_type = options[:proxy_type]
32
+ @proxy_username = options[:proxy_username]
33
+ @proxy_password = options[:proxy_password]
34
+ @proxy_auth_method = options[:proxy_auth_method]
35
+
36
+ @on_complete = []
37
+ @handled_response = []
38
+ @multiple_callbacks = false
39
+ @train = false
40
+ end
41
+
42
+ def on_complete( multi = false, &block )
43
+
44
+ # remember user preference for subsequent calls
45
+ if( multi || @multiple_callbacks )
46
+ @multiple_callbacks = true
47
+ @on_complete << block
48
+ else
49
+ @on_complete = block
50
+ end
51
+
52
+ end
53
+
54
+ def on_complete=( multi = false, proc )
55
+
56
+ # remember user preference for subsequent calls
57
+ if( multi || @multiple_callbacks )
58
+ @multiple_callbacks = true
59
+ @on_complete << proc
60
+ else
61
+ @on_complete = proc
62
+ end
63
+
64
+ end
65
+
66
+ def call_handlers
67
+
68
+ if @on_complete.is_a? Array
69
+
70
+ @on_complete.each do |callback|
71
+ @handled_response << callback.call(response)
72
+ end
73
+
74
+ else
75
+ @handled_response << @on_complete.call(response)
76
+ end
77
+
78
+ call_after_complete
79
+ end
80
+
81
+ def train?
82
+ @train
83
+ end
84
+
85
+ def train!
86
+ @train = true
87
+ end
88
+
89
+ end
90
+
91
+ end
@@ -0,0 +1,34 @@
1
+
2
+ module Typhoeus
3
+ class Response
4
+
5
+ #
6
+ # Converts obj to hash
7
+ #
8
+ # @param [Object] obj instance of an object
9
+ #
10
+ # @return [Hash]
11
+ #
12
+ def to_hash
13
+ hash = Hash.new
14
+ instance_variables.each {
15
+ |var|
16
+ key = var.to_s.gsub( /@/, '' )
17
+ hash[key] = instance_variable_get( var )
18
+
19
+ }
20
+
21
+ hash['headers_hash'] = {}
22
+ headers_hash.each_pair {
23
+ |k, v|
24
+ hash['headers_hash'][k] = v
25
+ }
26
+
27
+ hash.delete( 'request' )
28
+
29
+ return hash
30
+ end
31
+
32
+
33
+ end
34
+ end
@@ -0,0 +1,744 @@
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
+
12
+ module Arachni
13
+
14
+ require Options.instance.dir['lib'] + 'ui/cli/output'
15
+ require Options.instance.dir['lib'] + 'framework'
16
+
17
+ module UI
18
+
19
+ #
20
+ # Arachni::UI:CLI class
21
+ #
22
+ # Provides a command line interface for the Arachni Framework.<br/>
23
+ # Most of the logic is in the Framework class however profiles can only<br/>
24
+ # be loaded and saved at this level.
25
+ #
26
+ # @author: Tasos "Zapotek" Laskos
27
+ # <tasos.laskos@gmail.com>
28
+ # <zapotek@segfault.gr>
29
+ # @version: 0.1.6
30
+ # @see Arachni::Framework
31
+ #
32
+ class CLI
33
+
34
+ #
35
+ # Instance options
36
+ #
37
+ # @return [Options]
38
+ #
39
+ attr_reader :opts
40
+
41
+ # the output interface for CLI
42
+ include Arachni::UI::Output
43
+ include Arachni::Module::Utilities
44
+
45
+ #
46
+ # Initializes the command line interface and the framework
47
+ #
48
+ # @param [Options] opts
49
+ #
50
+ def initialize( opts )
51
+
52
+ @opts = opts
53
+
54
+ # if we have a load profile load it and merge it with the
55
+ # user supplied options
56
+ if( @opts.load_profile )
57
+ load_profile( @opts.load_profile )
58
+ end
59
+
60
+ #
61
+ # the stdout report is the default one for the CLI,
62
+ # each UI should have it's own default
63
+ #
64
+ # always load the stdout report unless the user requested
65
+ # to see a list of the available reports
66
+ #
67
+ # *do not* forget this check, otherwise the reports registry
68
+ # will desync
69
+ #
70
+ if( @opts.reports.empty? && @opts.lsrep.empty? )
71
+ @opts.reports['stdout'] = {}
72
+ end
73
+
74
+ # instantiate the big-boy!
75
+ @arachni = Arachni::Framework.new( @opts )
76
+
77
+
78
+ # echo the banner
79
+ banner( )
80
+
81
+ # work on the user supplied arguments
82
+ parse_opts( )
83
+
84
+ # trap Ctrl+C interrupts
85
+ trap( 'INT' ) { handle_interrupt( ) }
86
+ end
87
+
88
+ #
89
+ # Runs Arachni
90
+ #
91
+ def run( )
92
+
93
+ print_status( 'Initing...' )
94
+
95
+ begin
96
+ # start the show!
97
+ @arachni.run( ){
98
+ @interrupt_handler.join if @interrupt_handler
99
+ }
100
+ print_stats
101
+ rescue Arachni::Exceptions::NoMods => e
102
+ print_error( e.to_s )
103
+ print_info( "Run arachni with the '-h' parameter for help or " )
104
+ print_info( "with the '--lsmod' parameter to see all available modules." )
105
+ print_line
106
+ exit 0
107
+ rescue Arachni::Exceptions => e
108
+ print_error( e.to_s )
109
+ print_info( "Run arachni with the '-h' parameter for help." )
110
+ print_line
111
+ exit 0
112
+ rescue Exception => e
113
+ exception_jail{ raise e }
114
+ exit 0
115
+ end
116
+ end
117
+
118
+ private
119
+
120
+ def print_stats( refresh_time = false )
121
+
122
+ stats = @arachni.stats( refresh_time )
123
+
124
+ audited = stats[:auditmap_size]
125
+ mapped = stats[:sitemap_size]
126
+ progress = ( Float( audited ) / mapped ) * 100
127
+
128
+ print_line
129
+ print_info( "Audit progress: #{progress.to_s[0...5]}% ( #{audited}/#{mapped} pages )" )
130
+ print_line
131
+ print_info( "Sent #{stats[:requests]} requests." )
132
+ print_info( "Received and analyzed #{stats[:responses]} responses." )
133
+ print_info( 'In ' + stats[:time] )
134
+
135
+ avg = 'Average: ' + stats[:avg] + ' requests/second.'
136
+ print_info( avg )
137
+
138
+ print_line
139
+ print_info( "Currently auditing #{stats[:current_page]}" )
140
+ print_info( "Burst response time total #{stats[:curr_res_time]}" )
141
+ print_info( "Burst response count total #{stats[:curr_res_cnt]} " )
142
+ print_info( "Burst average response time #{stats[:average_res_time]}" )
143
+ print_info( "Burst average #{stats[:curr_avg]} requests/second" )
144
+ print_info( "Original max concurrency #{@opts.http_req_limit}" )
145
+ print_info( "Throttled max concurrency #{stats[:max_concurrency]}" )
146
+
147
+ print_line
148
+
149
+ end
150
+
151
+
152
+ #
153
+ # Handles Ctrl+C interrupts
154
+ #
155
+ # Once an interrupt has been trapped the system pauses and waits
156
+ # for user input. <br/>
157
+ # The user can either continue or exit.
158
+ #
159
+ # The interrupt will be handled after a module has finished.
160
+ #
161
+ def handle_interrupt( )
162
+ return if @interrupt_handler && @interrupt_handler.alive?
163
+
164
+ only_positives_opt = only_positives?
165
+ @@only_positives = false
166
+ @interrupt_handler = Thread.new {
167
+
168
+ Thread.new {
169
+ if gets[0] == 'e'
170
+ @@only_positives = false
171
+ unmute!
172
+ @interrupt_handler.kill
173
+
174
+ print_info( 'Exiting...' )
175
+ exit 0
176
+ end
177
+
178
+ @@only_positives = only_positives_opt
179
+ unmute!
180
+ @interrupt_handler.kill
181
+ Thread.kill
182
+ }
183
+
184
+ while( 1 )
185
+
186
+ unmute!
187
+ print_line
188
+ clear_screen
189
+ print_info( 'Results thus far:' )
190
+
191
+ begin
192
+ print_issues( @arachni.audit_store( true ) )
193
+ print_stats( true )
194
+ rescue Exception => e
195
+ exception_jail{ raise e }
196
+ exit 0
197
+ end
198
+
199
+ print_info( 'Continue? (hit \'enter\' to continue, \'e\' to exit)' )
200
+ mute!
201
+
202
+ ::IO::select( nil, nil, nil, 1 )
203
+ end
204
+
205
+ unmute!
206
+ }
207
+
208
+ end
209
+
210
+ def clear_screen
211
+ puts "\e[H\e[2J"
212
+ end
213
+
214
+ def print_issues( audit_store )
215
+
216
+ print_line( )
217
+ print_info( audit_store.issues.size.to_s +
218
+ ' issues have been detected.' )
219
+
220
+ print_line( )
221
+ audit_store.issues.each {
222
+ |issue|
223
+
224
+ print_ok( "#{issue.name} (In #{issue.elem} variable '#{issue.var}'" +
225
+ " - Severity: #{issue.severity} - Variations: #{issue.variations.size.to_s})" )
226
+
227
+ print_info( issue.variations[0]['url'] )
228
+
229
+ print_line( )
230
+ }
231
+
232
+ print_line( )
233
+
234
+ end
235
+
236
+ #
237
+ # It parses and processes the user options.
238
+ #
239
+ # Loads modules, reports, saves/loads profiles etc.<br/>
240
+ # It basically prepares the framework before calling {Arachni::Framework#run}.
241
+ #
242
+ def parse_opts( )
243
+
244
+ if !@opts.repload
245
+
246
+ if( !@opts.mods || @opts.mods.empty? )
247
+ print_info( "No modules were specified." )
248
+ print_info( " -> Will run all mods." )
249
+
250
+ @opts.mods = ['*']
251
+ end
252
+
253
+ if( !@opts.audit_links &&
254
+ !@opts.audit_forms &&
255
+ !@opts.audit_cookies &&
256
+ !@opts.audit_headers
257
+ )
258
+ print_info( "No audit options were specified." )
259
+ print_info( " -> Will audit links, forms and cookies." )
260
+
261
+ @opts.audit_links = true
262
+ @opts.audit_forms = true
263
+ @opts.audit_cookies = true
264
+ end
265
+
266
+ end
267
+
268
+ @arachni.plugins.load_defaults!
269
+ @opts.to_h.each {
270
+ |opt, arg|
271
+
272
+ case opt.to_s
273
+
274
+ when 'help'
275
+ usage
276
+ exit 0
277
+
278
+ when 'arachni_verbose'
279
+ verbose!
280
+
281
+ when 'debug'
282
+ debug!
283
+
284
+ when 'only_positives'
285
+ only_positives!
286
+
287
+ when 'lsmod'
288
+ next if arg.empty?
289
+ lsmod
290
+ exit 0
291
+
292
+ when 'lsplug'
293
+ next if arg.empty?
294
+ lsplug
295
+ exit 0
296
+
297
+ when 'lsrep'
298
+ next if arg.empty?
299
+ lsrep
300
+ exit 0
301
+
302
+ when 'show_profile'
303
+ print_profile( )
304
+ exit 0
305
+
306
+ when 'save_profile'
307
+ exception_jail{ save_profile( arg ) }
308
+ exit 0
309
+
310
+ when 'mods'
311
+ begin
312
+ exception_jail{
313
+ @opts.mods = @arachni.modules.load( arg )
314
+ }
315
+ rescue
316
+ exit 0
317
+ end
318
+
319
+ when 'reports'
320
+ begin
321
+ exception_jail{ @arachni.reports.load( arg.keys ) }
322
+ rescue
323
+ exit 0
324
+ end
325
+
326
+ when 'plugins'
327
+ begin
328
+ exception_jail{ @arachni.plugins.load( arg.keys ) }
329
+ rescue
330
+ exit 0
331
+ end
332
+
333
+ when 'repload'
334
+ exception_jail{ @arachni.reports.run( AuditStore.load( arg ), false ) }
335
+ exit 0
336
+
337
+ end
338
+ }
339
+
340
+ # Check for missing url
341
+ if( !@opts.url && !@opts.repload )
342
+ print_error( "Missing url argument." )
343
+ exit 0
344
+ end
345
+
346
+ end
347
+
348
+ #
349
+ # Outputs all available modules and their info.
350
+ #
351
+ def lsmod
352
+ print_line
353
+ print_line
354
+ print_info( 'Available modules:' )
355
+ print_line
356
+
357
+ mods = @arachni.lsmod( )
358
+
359
+ i = 0
360
+ mods.each {
361
+ |info|
362
+
363
+ print_status( "#{info[:mod_name]}:" )
364
+ print_line( "--------------------" )
365
+
366
+ print_line( "Name:\t\t" + info[:name] )
367
+ print_line( "Description:\t" + info[:description] )
368
+
369
+ if( info[:elements] && info[:elements].size > 0 )
370
+ print_line( "Elements:\t" +
371
+ info[:elements].join( ', ' ).downcase )
372
+ end
373
+
374
+ print_line( "Author:\t\t" + info[:author] )
375
+ print_line( "Version:\t" + info[:version] )
376
+
377
+ if( info[:references] )
378
+ print_line( "References:" )
379
+ info[:references].keys.each {
380
+ |key|
381
+ print_info( key + "\t\t" + info[:references][key] )
382
+ }
383
+ end
384
+
385
+ print_line( "Targets:" )
386
+ info[:targets].keys.each {
387
+ |key|
388
+ print_info( key + "\t\t" + info[:targets][key] )
389
+ }
390
+
391
+ if( info[:issue] &&
392
+ ( sploit = info[:issue][:metasploitable] ) )
393
+ print_line( "Metasploitable:\t" + sploit )
394
+ end
395
+
396
+ print_line( "Path:\t" + info[:path] )
397
+
398
+ i+=1
399
+
400
+ # pause every 3 modules to give the user time to read
401
+ # (cheers to aungkhant@yehg.net for suggesting it)
402
+ if( i % 3 == 0 && i != mods.size )
403
+ print_line
404
+ print_line( 'Hit <space> <enter> to continue, any other key to exit. ' )
405
+
406
+ if gets[0] != " "
407
+ print_line
408
+ return
409
+ end
410
+
411
+ end
412
+
413
+ print_line
414
+ }
415
+
416
+ end
417
+
418
+ #
419
+ # Outputs all available reports and their info.
420
+ #
421
+ def lsrep
422
+ print_line
423
+ print_line
424
+ print_info( 'Available reports:' )
425
+ print_line
426
+
427
+ @arachni.lsrep().each {
428
+ |info|
429
+
430
+ print_status( "#{info[:rep_name]}:" )
431
+ print_line( "--------------------" )
432
+
433
+ print_line( "Name:\t\t" + info[:name] )
434
+ print_line( "Description:\t" + info[:description] )
435
+
436
+ if( info[:options] && !info[:options].empty? )
437
+ print_line( "Options:\t" )
438
+
439
+ info[:options].each {
440
+ |option|
441
+ print_info( "\t#{option.name} - #{option.desc}" )
442
+ print_info( "\tType: #{option.type}" )
443
+ print_info( "\tDefault: #{option.default}" )
444
+ print_info( "\tRequired?: #{option.required?}" )
445
+
446
+ print_line( )
447
+ }
448
+ end
449
+
450
+ print_line( "Author:\t\t" + info[:author] )
451
+ print_line( "Version:\t" + info[:version] )
452
+ print_line( "Path:\t" + info[:path] )
453
+
454
+ print_line
455
+ }
456
+
457
+ end
458
+
459
+ #
460
+ # Outputs all available reports and their info.
461
+ #
462
+ def lsplug
463
+ print_line
464
+ print_line
465
+ print_info( 'Available plugins:' )
466
+ print_line
467
+
468
+ @arachni.lsplug().each {
469
+ |info|
470
+
471
+ print_status( "#{info[:plug_name]}:" )
472
+ print_line( "--------------------" )
473
+
474
+ print_line( "Name:\t\t" + info[:name] )
475
+ print_line( "Description:\t" + info[:description] )
476
+
477
+ if( info[:options] && !info[:options].empty? )
478
+ print_line( "Options:\t" )
479
+
480
+ info[:options].each {
481
+ |option|
482
+ print_info( "\t#{option.name} - #{option.desc}" )
483
+ print_info( "\tType: #{option.type}" )
484
+ print_info( "\tDefault: #{option.default}" )
485
+ print_info( "\tRequired?: #{option.required?}" )
486
+
487
+ print_line( )
488
+ }
489
+ end
490
+
491
+ print_line( "Author:\t\t" + info[:author] )
492
+ print_line( "Version:\t" + info[:version] )
493
+ print_line( "Path:\t" + info[:path] )
494
+
495
+ print_line
496
+ }
497
+
498
+ end
499
+
500
+
501
+ #
502
+ # Loads an Arachni Framework Profile file and merges it with the
503
+ # user supplied options.
504
+ #
505
+ # @param [String] filename the file to load
506
+ #
507
+ def load_profile( profiles )
508
+ exception_jail{
509
+ @opts.load_profile = nil
510
+ profiles.each {
511
+ |filename|
512
+ @opts.merge!( YAML::load( IO.read( filename ) ) )
513
+ }
514
+ }
515
+ end
516
+
517
+ #
518
+ # Saves options to an Arachni Framework Profile file.<br/>
519
+ # The file will be appended with the {PROFILE_EXT} extension.
520
+ #
521
+ # @param [String] filename
522
+ #
523
+ def save_profile( filename )
524
+
525
+ if filename = @opts.save( filename )
526
+ print_status( "Saved profile in '#{filename}'." )
527
+ print_line( )
528
+ else
529
+ banner( )
530
+ print_error( 'Could not save profile.' )
531
+ exit 0
532
+ end
533
+ end
534
+
535
+ def print_profile( )
536
+ print_info( 'Running profile:' )
537
+ print_info( @opts.to_args )
538
+ end
539
+
540
+ #
541
+ # Outputs Arachni banner.<br/>
542
+ # Displays version number, revision number, author details etc.
543
+ #
544
+ # @see VERSION
545
+ # @see REVISION
546
+ #
547
+ # @return [void]
548
+ #
549
+ def banner
550
+
551
+ print_line 'Arachni - Web Application Security Scanner Framework v' +
552
+ @arachni.version + ' [' + @arachni.revision + ']
553
+ Author: Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
554
+ <zapotek@segfault.gr>
555
+ (With the support of the community and the Arachni Team.)
556
+
557
+ Website: http://github.com/Zapotek/arachni
558
+ Documentation: http://github.com/Zapotek/arachni/wiki'
559
+ print_line
560
+ print_line
561
+
562
+ end
563
+
564
+ #
565
+ # Outputs help/usage information.<br/>
566
+ # Displays supported options and parameters.
567
+ #
568
+ # @return [void]
569
+ #
570
+ def usage
571
+ print_line <<USAGE
572
+ Usage: arachni \[options\] url
573
+
574
+ Supported options:
575
+
576
+
577
+ General ----------------------
578
+
579
+ -h
580
+ --help output this
581
+
582
+ -v be verbose
583
+
584
+ --debug show what is happening internally
585
+ (You should give it a shot sometime ;) )
586
+
587
+ --only-positives echo positive results *only*
588
+
589
+ --http-req-limit concurent HTTP requests limit
590
+ (Be carefull not to kill your server.)
591
+ (Default: 60)
592
+ (*NOTE*: If your scan seems unresponsive try lowering the limit.)
593
+
594
+ --http-harvest-last build up the HTTP request queue of the audit for the whole site
595
+ and harvest the HTTP responses at the end of the crawl.
596
+ (In some test cases this option has split the scan time in half.)
597
+ (Default: responses will be harvested for each page)
598
+ (*NOTE*: If you are scanning a high-end server and
599
+ you are using a powerful machine with enough bandwidth
600
+ *and* you feel dangerous you can use
601
+ this flag with an increased '--http-req-limit'
602
+ to get maximum performance out of your scan.)
603
+ (*WARNING*: When scanning large websites with hundreads
604
+ of pages this could eat up all your memory pretty quickly.)
605
+
606
+ --cookie-jar=<cookiejar> netscape HTTP cookie file, use curl to create it
607
+
608
+
609
+ --user-agent=<user agent> specify user agent
610
+
611
+ --authed-by=<who> who authorized the scan, include name and e-mail address
612
+ (It'll make it easier on the sys-admins during log reviews.)
613
+ (Will be appended to the user-agent string.)
614
+
615
+
616
+ Profiles -----------------------
617
+
618
+ --save-profile=<file> save the current run profile/options to <file>
619
+
620
+ --load-profile=<file> load a run profile from <file>
621
+ (Can be used multiple times.)
622
+ (You can complement it with more options, except for:
623
+ * --mods
624
+ * --redundant)
625
+
626
+ --show-profile will output the running profile as CLI arguments
627
+
628
+
629
+ Crawler -----------------------
630
+
631
+ -e <regex>
632
+ --exclude=<regex> exclude urls matching regex
633
+ (Can be used multiple times.)
634
+
635
+ -i <regex>
636
+ --include=<regex> include urls matching this regex only
637
+ (Can be used multiple times.)
638
+
639
+ --redundant=<regex>:<count> limit crawl on redundant pages like galleries or catalogs
640
+ (URLs matching <regex> will be crawled <count> links deep.)
641
+ (Can be used multiple times.)
642
+
643
+ -f
644
+ --follow-subdomains follow links to subdomains (default: off)
645
+
646
+ --obey-robots-txt obey robots.txt file (default: off)
647
+
648
+ --depth=<number> depth limit (default: inf)
649
+ (How deep Arachni should go into the site structure.)
650
+
651
+ --link-count=<number> how many links to follow (default: inf)
652
+
653
+ --redirect-limit=<number> how many redirects to follow (default: inf)
654
+
655
+ --spider-first spider first, audit later
656
+
657
+
658
+ Auditor ------------------------
659
+
660
+ -g
661
+ --audit-links audit link variables (GET)
662
+
663
+ -p
664
+ --audit-forms audit form variables
665
+ (usually POST, can also be GET)
666
+
667
+ -c
668
+ --audit-cookies audit cookies (COOKIE)
669
+
670
+ --exclude-cookie=<name> cookies not to audit
671
+ (You should exclude session cookies.)
672
+ (Can be used multiple times.)
673
+
674
+ --audit-headers audit HTTP headers
675
+ (*NOTE*: Header audits use brute force.
676
+ Almost all valid HTTP request headers will be audited
677
+ even if there's no indication that the web app uses them.)
678
+ (*WARNING*: Enabling this option will result in increased requests,
679
+ maybe by an order of magnitude.)
680
+
681
+
682
+ Modules ------------------------
683
+
684
+ --lsmod=<regexp> list available modules based on the provided regular expression
685
+ (If no regexp is provided all modules will be listed.)
686
+ (Can be used multiple times.)
687
+
688
+
689
+ -m <modname,modname..>
690
+ --mods=<modname,modname..> comma separated list of modules to deploy
691
+ (Use '*' as a module name to deploy all modules or inside module names like so:
692
+ xss_* to load all xss modules
693
+ sqli_* to load all sql injection modules
694
+ etc.
695
+
696
+ You can exclude modules by prefixing their name with a dash:
697
+ --mods=*,-backup_files,-xss
698
+ The above will load all modules except for the 'backup_files' and 'xss' modules.
699
+
700
+ Or mix and match:
701
+ -xss_* to unload all xss modules. )
702
+
703
+
704
+ Reports ------------------------
705
+
706
+ --lsrep list available reports
707
+
708
+ --repload=<file> load audit results from an .afr file
709
+ (Allows you to create new reports from finished scans.)
710
+
711
+ --report='<report>:<optname>=<val>,<optname2>=<val2>,...'
712
+
713
+ <report>: the name of the report as displayed by '--lsrep'
714
+ (Default: stdout)
715
+ (Can be used multiple times.)
716
+
717
+
718
+ Plugins ------------------------
719
+
720
+ --lsplug list available plugins
721
+
722
+ --plugin='<plugin>:<optname>=<val>,<optname2>=<val2>,...'
723
+
724
+ <plugin>: the name of the plugin as displayed by '--lsplug'
725
+ (Can be used multiple times.)
726
+
727
+
728
+ Proxy --------------------------
729
+
730
+ --proxy=<server:port> specify proxy
731
+
732
+ --proxy-auth=<user:passwd> specify proxy auth credentials
733
+
734
+ --proxy-type=<type> proxy type can be http, http_1_0, socks4, socks5, socks4a
735
+ (Default: http)
736
+
737
+
738
+ USAGE
739
+ end
740
+
741
+ end
742
+
743
+ end
744
+ end