msfrpc-client 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,9 @@
1
+ # Metasploit Pro RPC Client
2
+
3
+ This is the official Ruby client for the Metasploit Pro RPC service. Metasploit
4
+ Pro is a commercial penetration testing product provided by Rapid7. For more
5
+ information on Metasploit Pro, please visit the http://www.metasploit.com/ site.
6
+
7
+ # Credits
8
+ Rapid7 LLC
9
+
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ task :build => :update do
4
+ Rake::Task['clean'].execute
5
+ puts "[*] Building msfrpc-client.gemspec"
6
+ system "gem build msfrpc-client.gemspec &> /dev/null"
7
+ end
8
+
9
+ task :release => :build do
10
+ puts "[*] Pushing msfrpc-client to rubygems.org"
11
+ system "gem push msfrpc-client-*.gem &> /dev/null"
12
+ Rake::Task['clean'].execute
13
+ end
14
+
15
+ task :clean do
16
+ system "rm *.gem &> /dev/null"
17
+ end
18
+
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'optparse'
5
+ require 'msfrpc-client'
6
+ require 'rex/ui'
7
+
8
+
9
+ # Use the RPC option parser to handle standard flags
10
+ opts = {}
11
+ parser = Msf::RPC::Client.option_parser(opts)
12
+ parser.parse!(ARGV)
13
+
14
+ # Parse additional options, environment variables, etc
15
+ opts = Msf::RPC::Client.option_handler(opts)
16
+
17
+ # Create the RPC client with our parsed options
18
+ rpc = Msf::RPC::Client.new(opts)
19
+
20
+ $stdout.puts "[*] The RPC client is available in variable 'rpc'"
21
+ if rpc.token
22
+ $stdout.puts "[*] Sucessfully authenticated to the server"
23
+ end
24
+
25
+ $stdout.puts "[*] Starting IRB shell..."
26
+ Rex::Ui::Text::IrbShell.new(binding).run
27
+
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'optparse'
5
+ require 'msfrpc-client'
6
+ require 'rex/ui'
7
+
8
+ def usage(ropts)
9
+ $stderr.puts ropts
10
+
11
+ if @rpc and @rpc.token
12
+ wspaces = @rpc.call("pro.workspaces") rescue {}
13
+ if wspaces.keys.length > 0
14
+ $stderr.puts "Active Projects:"
15
+ wspaces.each_pair do |k,v|
16
+ $stderr.puts "\t#{k}"
17
+ end
18
+ end
19
+ end
20
+ $stderr.puts ""
21
+ exit(1)
22
+ end
23
+
24
+ opts = {
25
+ :format => 'PDF'
26
+ }
27
+
28
+ parser = Msf::RPC::Client.option_parser(opts)
29
+
30
+ parser.separator('Report Options:')
31
+ parser.on("--format FORMAT") do |v|
32
+ opts[:format] = v.upcase
33
+ end
34
+
35
+ parser.on("--project PROJECT") do |v|
36
+ opts[:project] = v
37
+ end
38
+
39
+ parser.on("--output OUTFILE") do |v|
40
+ opts[:output] = v
41
+ end
42
+
43
+ parser.on("--help") do
44
+ $stderr.puts ropts
45
+ exit(1)
46
+ end
47
+ parser.separator('')
48
+
49
+ parser.parse!(ARGV)
50
+ @rpc = Msf::RPC::Client.new(opts)
51
+
52
+ if not @rpc.token
53
+ $stderr.puts "Error: Invalid RPC server options specified"
54
+ $stderr.puts parser
55
+ exit(1)
56
+ end
57
+
58
+ wspace = opts[:project] || usage(parser)
59
+ fname = opts[:output] || usage(parser)
60
+ rtype = opts[:format]
61
+ user = @rpc.call("pro.default_admin_user")['username']
62
+
63
+ task = @rpc.call("pro.start_report", {
64
+ 'DS_WHITELIST_HOSTS' => "",
65
+ 'DS_BLACKLIST_HOSTS' => "",
66
+ 'workspace' => wspace,
67
+ 'username' => user,
68
+ 'DS_MaskPasswords' => false,
69
+ 'DS_IncludeTaskLog' => false,
70
+ 'DS_JasperDisplaySession' => true,
71
+ 'DS_JasperDisplayCharts' => true,
72
+ 'DS_LootExcludeScreenshots' => false,
73
+ 'DS_LootExcludePasswords' => false,
74
+ 'DS_JasperTemplate' => "msfxv3.jrxml",
75
+ 'DS_REPORT_TYPE' => rtype.upcase,
76
+ 'DS_UseJasper' => true,
77
+ 'DS_UseCustomReporting' => true,
78
+ 'DS_JasperProductName' => "Metasploit Pro",
79
+ 'DS_JasperDbEnv' => "production",
80
+ 'DS_JasperLogo' => '',
81
+ 'DS_JasperDisplaySections' => "1,2,3,4,5,6,7,8",
82
+ 'DS_EnablePCIReport' => true,
83
+ 'DS_EnableFISMAReport' => true,
84
+ 'DS_JasperDisplayWeb' => true,
85
+ })
86
+
87
+
88
+ if not task['task_id']
89
+ $stderr.puts "[-] Error generating the report: #{task.inspect}"
90
+ exit(0)
91
+ end
92
+
93
+ puts "[*] Report is generating with Task ID #{task['task_id']}..."
94
+ while true
95
+ select(nil, nil, nil, 0.50)
96
+ stat = @rpc.call("pro.task_status", task['task_id'])
97
+ if stat['status'] == 'invalid'
98
+ $stderr.puts "[-] Error checking task status"
99
+ exit(0)
100
+ end
101
+
102
+ info = stat[ task['task_id'] ]
103
+
104
+ if not info
105
+ $stderr.puts "[-] Error finding the task"
106
+ exit(0)
107
+ end
108
+
109
+ if info['status'] == "error"
110
+ $stderr.puts "[-] Error generating report: #{info['error']}"
111
+ exit(0)
112
+ end
113
+
114
+ break if info['progress'] == 100
115
+ end
116
+
117
+ report = @rpc.call('pro.report_download_by_task', task['task_id'])
118
+ if report and report['data']
119
+ ::File.open(fname, "wb") do |fd|
120
+ fd.write(report['data'])
121
+ end
122
+ $stderr.puts "[-] Report saved to #{::File.expand_path(fname)}"
123
+ else
124
+ $stderr.puts "[-] Error downloading report: #{report.inspect}"
125
+ end
126
+
@@ -0,0 +1,2 @@
1
+ require 'msfrpc-client/client'
2
+
@@ -0,0 +1,214 @@
1
+ # MessagePack for data encoding (http://www.msgpack.org/)
2
+ require 'msgpack'
3
+
4
+ # Standardize option parsing
5
+ require "optparse"
6
+
7
+ # Parse configuration file
8
+ require 'yaml'
9
+
10
+ # Rex library from the Metasploit Framework
11
+ require 'rex'
12
+ require 'rex/proto/http'
13
+
14
+ # Constants used by this client
15
+ require 'msfrpc-client/constants'
16
+
17
+ module Msf
18
+ module RPC
19
+
20
+ class Client
21
+
22
+ attr_accessor :token, :info
23
+
24
+ #
25
+ # Create a new RPC Client instance
26
+ #
27
+ def initialize(info={})
28
+ self.info = {
29
+ :host => '127.0.0.1',
30
+ :port => 3790,
31
+ :uri => '/api',
32
+ :ssl => true,
33
+ :ssl_version => 'SSLv3',
34
+ :context => {}
35
+ }.merge(info)
36
+
37
+ info[:port] = info[:port].to_i
38
+
39
+ self.token = self.info[:token]
40
+
41
+ if not self.token and (info[:user] and info[:pass])
42
+ login(info[:user], info[:pass])
43
+ end
44
+ end
45
+
46
+ #
47
+ # Authenticate using a username and password
48
+ #
49
+ def login(user,pass)
50
+ res = self.call("auth.login", user, pass)
51
+ if(not (res and res['result'] == "success"))
52
+ raise RuntimeError, "authentication failed"
53
+ end
54
+ self.token = res['token']
55
+ true
56
+ end
57
+
58
+ #
59
+ # Prepend the authentication token as the first parameter
60
+ # of every call except auth.login. This simplifies the
61
+ # calling API.
62
+ #
63
+ def call(meth, *args)
64
+ if(meth != "auth.login")
65
+ if(not self.token)
66
+ raise RuntimeError, "client not authenticated"
67
+ end
68
+ args.unshift(self.token)
69
+ end
70
+
71
+ args.unshift(meth)
72
+
73
+ if not @cli
74
+ @cli = Rex::Proto::Http::Client.new(info[:host], info[:port], info[:context], info[:ssl], info[:ssl_version])
75
+ @cli.set_config(
76
+ :vhost => info[:host],
77
+ :agent => "Metasploit Pro RPC Client/#{API_VERSION}",
78
+ :read_max_data => (1024*1024*512)
79
+ )
80
+ end
81
+
82
+ req = @cli.request_cgi(
83
+ 'method' => 'POST',
84
+ 'uri' => self.info[:uri],
85
+ 'ctype' => 'binary/message-pack',
86
+ 'data' => args.to_msgpack
87
+ )
88
+
89
+ res = @cli.send_recv(req)
90
+
91
+ if res and [200, 401, 403, 500].include?(res.code)
92
+ resp = MessagePack.unpack(res.body)
93
+
94
+ if resp and resp.kind_of?(::Hash) and resp['error'] == true
95
+ raise Msf::RPC::ServerException.new(res.code, resp['error_message'] || resp['error_string'], resp['error_class'], resp['error_backtrace'])
96
+ end
97
+
98
+ return resp
99
+ else
100
+ raise RuntimeError, res.inspect
101
+ end
102
+ end
103
+
104
+
105
+ #
106
+ # Class methods
107
+ #
108
+
109
+
110
+ #
111
+ # Provides a parser object that understands the
112
+ # RPC specific options
113
+ #
114
+ def self.option_parser(options)
115
+ parser = OptionParser.new
116
+
117
+ parser.banner = "Usage: #{$0} [options]"
118
+ parser.separator('')
119
+ parser.separator('RPC Options:')
120
+
121
+ parser.on("--rpc-host HOST") do |v|
122
+ options[:host] = v
123
+ end
124
+
125
+ parser.on("--rpc-port PORT") do |v|
126
+ options[:port] = v.to_i
127
+ end
128
+
129
+ parser.on("--rpc-ssl <true|false>") do |v|
130
+ options[:ssl] = v
131
+ end
132
+
133
+ parser.on("--rpc-uri URI") do |v|
134
+ options[:uri] = v
135
+ end
136
+
137
+ parser.on("--rpc-user USERNAME") do |v|
138
+ options[:user] = v
139
+ end
140
+
141
+ parser.on("--rpc-pass PASSWORD") do |v|
142
+ options[:pass] = v
143
+ end
144
+
145
+ parser.on("--rpc-token TOKEN") do |v|
146
+ options[:token] = v
147
+ end
148
+
149
+ parser.on("--rpc-config CONFIG-FILE") do |v|
150
+ options[:config] = v
151
+ end
152
+
153
+ parser.on("--rpc-help") do
154
+ $stderr.puts parser
155
+ exit(1)
156
+ end
157
+
158
+ parser.separator('')
159
+
160
+ parser
161
+ end
162
+
163
+ #
164
+ # Load options from the command-line, environment.
165
+ # and any configuration files specified
166
+ #
167
+ def self.option_handler(options={})
168
+ options[:host] ||= ENV['MSFRPC_HOST']
169
+ options[:port] ||= ENV['MSFRPC_PORT']
170
+ options[:uri] ||= ENV['MSFRPC_URI']
171
+ options[:user] ||= ENV['MSFRPC_USER']
172
+ options[:pass] ||= ENV['MSFRPC_PASS']
173
+ options[:ssl] ||= ENV['MSFRPC_SSL']
174
+ options[:token] ||= ENV['MSFRPC_TOKEN']
175
+ options[:config] ||= ENV['MSFRPC_CONFIG']
176
+
177
+ empty_keys = options.keys.select{|k| options[k].nil? }
178
+ empty_keys.each { |k| options.delete(k) }
179
+
180
+ config_file = options.delete(:config)
181
+
182
+ if config_file
183
+ yaml_data = ::File.read(config_file) rescue nil
184
+ if yaml_data
185
+ yaml = ::YAML.load(yaml_data) rescue nil
186
+ if yaml and yaml.kind_of?(::Hash) and yaml['options']
187
+ yaml['options'].each_pair do |k,v|
188
+ options[k.intern] = v
189
+ end
190
+ else
191
+ $stderr.puts "[-] Could not parse configuration file: #{config_file}"
192
+ exit(1)
193
+ end
194
+ else
195
+ $stderr.puts "[-] Could not read configuration file: #{config_file}"
196
+ exit(1)
197
+ end
198
+ end
199
+
200
+ if options[:port]
201
+ options[:port] = options[:port].to_i
202
+ end
203
+
204
+ if options[:ssl]
205
+ options[:ssl] = (options[:ssl] =~ /(1|Y|T)/i ? true : false )
206
+ end
207
+
208
+ options
209
+ end
210
+
211
+ end
212
+ end
213
+ end
214
+
@@ -0,0 +1,34 @@
1
+ module Msf
2
+ module RPC
3
+
4
+ API_VERSION = "1.0"
5
+
6
+
7
+ class Exception < RuntimeError
8
+ attr_accessor :code, :message
9
+
10
+ def initialize(code, message)
11
+ self.code = code
12
+ self.message = message
13
+ end
14
+ end
15
+
16
+
17
+ class ServerException < RuntimeError
18
+ attr_accessor :code, :error_message, :error_class, :error_backtrace
19
+
20
+ def initialize(code, error_message, error_class, error_backtrace)
21
+ self.code = code
22
+ self.error_message = error_message
23
+ self.error_class = error_class
24
+ self.error_backtrace = error_backtrace
25
+ end
26
+
27
+ def to_s
28
+ "#{self.error_class} #{self.error_message} #{self.error_backtrace}"
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: msfrpc-client
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - HD Moore
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-07-23 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: msgpack
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 5
30
+ segments:
31
+ - 0
32
+ - 4
33
+ - 5
34
+ version: 0.4.5
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: librex
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 95
46
+ segments:
47
+ - 0
48
+ - 0
49
+ - 32
50
+ version: 0.0.32
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: This gem provides a Ruby client API to access the Rapid7 Metasploit Pro RPC service.
54
+ email:
55
+ - hdm@metasploit.com
56
+ executables: []
57
+
58
+ extensions: []
59
+
60
+ extra_rdoc_files:
61
+ - README.markdown
62
+ files:
63
+ - Rakefile
64
+ - README.markdown
65
+ - lib/msfrpc-client/client.rb
66
+ - lib/msfrpc-client/constants.rb
67
+ - lib/msfrpc-client.rb
68
+ - examples/msfrpc_irb.rb
69
+ - examples/msfrpc_pro_report.rb
70
+ has_rdoc: true
71
+ homepage: http://www.metasploit.com/
72
+ licenses:
73
+ - BSD
74
+ post_install_message:
75
+ rdoc_options: []
76
+
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ hash: 57
85
+ segments:
86
+ - 1
87
+ - 8
88
+ - 7
89
+ version: 1.8.7
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ hash: 3
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ requirements: []
100
+
101
+ rubyforge_project:
102
+ rubygems_version: 1.4.2
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Ruby API for the Rapid7 Metasploit Pro RPC service
106
+ test_files: []
107
+