diff --git a/lib/msf/core/rpc/v10/rpc_db.rb b/lib/msf/core/rpc/v10/rpc_db.rb index 8db7f552b7..8ed864d14f 100644 --- a/lib/msf/core/rpc/v10/rpc_db.rb +++ b/lib/msf/core/rpc/v10/rpc_db.rb @@ -12,7 +12,7 @@ private end def find_workspace(wspace = nil) - if(wspace and wspace != "") + if wspace and wspace != "" return self.framework.db.find_workspace(wspace) || error(500, "Invalid workspace") end self.framework.db.workspace @@ -104,6 +104,39 @@ private return opts, opts[:workspace] end + def get_notes(xopts) + ::ActiveRecord::Base.connection_pool.with_connection { + opts, wspace = init_db_opts_workspace(xopts) + notes = [] + + host = self.framework.db.get_host(opts) + return notes if not host + + if opts[:proto] && opts[:port] + services = [] + nret = host.services.find_by_proto_and_port(opts[:proto], opts[:port]) + return ret if nret == nil + services << nret if nret.class == ::Mdm::Service + services |= nret if nret.class == Array + + services.each do |s| + nret = nil + if opts[:ntype] + nret = s.notes.find_by_ntype(opts[:ntype]) + else + nret = s.notes + end + next if nret == nil + notes << nret if nret.class == ::Mdm::Note + notes |= nret if nret.class == Array + end + else + notes = host.notes + end + notes + } + end + public @@ -416,7 +449,7 @@ public wspace.vulns.includes(:service).where(conditions).offset(offset).limit(limit).each do |v| vuln = {} reflist = v.refs.map { |r| r.name } - if(v.service) + if v.service vuln[:port] = v.service.port vuln[:proto] = v.service.proto else @@ -495,7 +528,7 @@ public wspace = find_workspace(wspace) ret = {} ret[:workspace] = [] - if(wspace) + if wspace w = {} w[:name] = wspace.name w[:id] = wspace.id @@ -524,7 +557,7 @@ public ::ActiveRecord::Base.connection_pool.with_connection { db_check workspace = find_workspace(wspace) - if(workspace) + if workspace self.framework.db.workspace = workspace return { 'result' => "success" } end @@ -580,7 +613,7 @@ public ::ActiveRecord::Base.connection_pool.with_connection { db_check wspace = self.framework.db.add_workspace(wspace) - return { 'result' => 'success' } if(wspace) + return { 'result' => 'success' } if wspace { 'result' => 'failed' } } end @@ -620,7 +653,7 @@ public ret[:host] = [] opts = fix_options(xopts) h = self.framework.db.get_host(opts) - if(h) + if h host = {} host[:created_at] = h.created_at.to_i host[:address] = h.address.to_s @@ -669,7 +702,7 @@ public opts, wspace = init_db_opts_workspace(xopts) res = self.framework.db.report_host(opts) - return { :result => 'success' } if(res) + return { :result => 'success' } if res { :result => 'failed' } } end @@ -695,7 +728,7 @@ public ::ActiveRecord::Base.connection_pool.with_connection { opts, wspace = init_db_opts_workspace(xopts) res = self.framework.db.report_service(opts) - return { :result => 'success' } if(res) + return { :result => 'success' } if res { :result => 'failed' } } end @@ -735,9 +768,9 @@ public services = [] sret = nil - if(host && opts[:proto] && opts[:port]) + if host && opts[:proto] && opts[:port] sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port]) - elsif(opts[:proto] && opts[:port]) + elsif opts[:proto] && opts[:port] conditions = {} conditions[:state] = [Msf::ServiceState::Open] if opts[:up] conditions[:proto] = opts[:proto] if opts[:proto] @@ -769,10 +802,12 @@ public } end - # Returns a note. # # @param [Hash] xopts Options. + # @option xopts [String] :addr Host address. + # @option xopts [String] :address Same as :addr. + # @option xopts [String] :host Same as :address. # @option xopts [String] :proto Protocol. # @option xopts [Fixnum] :port Port. # @option xopts [String] :ntype Note type. @@ -794,37 +829,11 @@ public # @example Here's how you would use this from the client: # rpc.call('db.get_note', {:proto => 'tcp', :port => 80}) def rpc_get_note(xopts) - ::ActiveRecord::Base.connection_pool.with_connection { - opts, wspace = init_db_opts_workspace(xopts) - ret = {} ret[:note] = [] - host = self.framework.db.get_host(opts) + notes = get_notes(xopts) - return ret if( not host) - notes = [] - if(opts[:proto] && opts[:port]) - services = [] - nret = host.services.find_by_proto_and_port(opts[:proto], opts[:port]) - return ret if nret == nil - services << nret if nret.class == ::Mdm::Service - services |= nret if nret.class == Array - - services.each do |s| - nret = nil - if opts[:ntype] - nret = s.notes.find_by_ntype(opts[:ntype]) - else - nret = s.notes - end - next if nret == nil - notes << nret if nret.class == ::Mdm::Note - notes |= nret if nret.class == Array - end - else - notes = host.notes - end notes.each do |n| note = {} host = n.host @@ -842,7 +851,6 @@ public ret[:note] << note end ret - } end @@ -872,7 +880,7 @@ public ret = {} ret[:client] = [] c = self.framework.db.get_client(opts) - if(c) + if c client = {} host = c.host client[:host] = host.address @@ -909,7 +917,7 @@ public ::ActiveRecord::Base.connection_pool.with_connection { opts, wspace = init_db_opts_workspace(xopts) res = self.framework.db.report_client(opts) - return { :result => 'success' } if(res) + return { :result => 'success' } if res { :result => 'failed' } } end @@ -944,12 +952,16 @@ public addr = opts[:host] || opts[:address] wspace = opts[:workspace] || self.framework.db.workspace host = wspace.hosts.find_by_address(addr) - service = host.services.find_by_proto_and_port(opts[:proto],opts[:port]) if host.services.count > 0 - opts[:service] = service if service + if host && host.services.count > 0 + service = host.services.find_by_proto_and_port(opts[:proto],opts[:port]) + if service + opts[:service] = service + end + end end res = self.framework.db.report_note(opts) - return { :result => 'success' } if(res) + return { :result => 'success' } if res { :result => 'failed' } } end @@ -997,8 +1009,8 @@ public note[:time] = n.created_at.to_i note[:host] = "" note[:service] = "" - note[:host] = n.host.address if(n.host) - note[:service] = n.service.name || n.service.port if(n.service) + note[:host] = n.host.address if n.host + note[:service] = n.service.name || n.service.port if n.service note[:type ] = n.ntype.to_s note[:data] = n.data.inspect ret[:notes] << note @@ -1058,14 +1070,14 @@ public vulns = [] if opts[:host] or opts[:address] or opts[:addresses] - hosts = opts_to_hosts(opts) + hosts = opts_to_hosts(xopts) end if opts[:port] or opts[:proto] if opts[:host] or opts[:address] or opts[:addresses] - services = opts_to_services(hosts,opts) + services = opts_to_services(hosts,xopts) else - services = opts_to_services([],opts) + services = opts_to_services([],xopts) end end @@ -1144,58 +1156,8 @@ public # @example Here's how you would use this from the client: # rpc.call('db.del_note', {:workspace=>'default', :host=>ip, :port=>443, :proto=>'tcp'}) def rpc_del_note(xopts) - ::ActiveRecord::Base.connection_pool.with_connection { - opts, wspace = init_db_opts_workspace(xopts) - hosts = [] - services = [] - notes = [] + notes = get_notes(xopts) - if opts[:host] or opts[:address] or opts[:addresses] - hosts = opts_to_hosts(xopts) - end - - if opts[:port] or opts[:proto] - if opts[:host] or opts[:address] or opts[:addresses] - services = opts_to_services(hosts,opts) - else - services = opts_to_services([],opts) - end - end - - if opts[:port] or opts[:proto] - services.each do |s| - nret = nil - if opts[:ntype] - nret = s.notes.find_by_ntype(opts[:ntype]) - else - nret = s.notes - end - next if nret == nil - notes << nret if nret.class == ::Mdm::Note - notes |= nret if nret.class == Array - end - elsif opts[:address] or opts[:host] or opts[:addresses] - hosts.each do |h| - nret = nil - if opts[:ntype] - nret = h.notes.find_by_ntype(opts[:ntype]) - else - nret = h.notes - end - next if nret == nil - notes << nret if nret.class == ::Mdm::Note - notes |= nret if nret.class == Array - end - else - nret = nil - if opts[:ntype] - nret = wspace.notes.find_by_ntype(opts[:ntype]) - else - nret = wspace.notes - end - notes << nret if nret.class == ::Mdm::Note - notes |= nret if nret.class == Array - end deleted = [] notes.each do |n| dent = {} @@ -1208,7 +1170,6 @@ public end return { :result => 'success', :deleted => deleted } - } end @@ -1360,7 +1321,7 @@ public opts = fix_options(xopts) opts[:workspace] = find_workspace(opts[:workspace]) if opts[:workspace] res = self.framework.db.report_vuln(opts) - return { :result => 'success' } if(res) + return { :result => 'success' } if res { :result => 'failed' } } end @@ -1398,12 +1359,12 @@ public wspace.events.offset(offset).limit(limit).each do |e| event = {} - event[:host] = e.host.address if(e.host) + event[:host] = e.host.address if e.host event[:created_at] = e.created_at.to_i event[:updated_at] = e.updated_at.to_i event[:name] = e.name - event[:critical] = e.critical if(e.critical) - event[:username] = e.username if(e.username) + event[:critical] = e.critical if e.critical + event[:username] = e.username if e.username event[:info] = e.info ret[:events] << event end @@ -1430,7 +1391,7 @@ public ::ActiveRecord::Base.connection_pool.with_connection { opts, wspace = init_db_opts_workspace(xopts) res = self.framework.db.report_event(opts) - { :result => 'success' } if(res) + { :result => 'success' } if res } end @@ -1465,7 +1426,7 @@ public end res = self.framework.db.report_loot(opts) - { :result => 'success' } if(res) + { :result => 'success' } if res } end @@ -1503,8 +1464,8 @@ public ret[:loots] = [] wspace.loots.offset(offset).limit(limit).each do |l| loot = {} - loot[:host] = l.host.address if(l.host) - loot[:service] = l.service.name || l.service.port if(l.service) + loot[:host] = l.host.address if l.host + loot[:service] = l.service.name || l.service.port if l.service loot[:ltype] = l.ltype loot[:ctype] = l.content_type loot[:data] = l.data @@ -1605,10 +1566,10 @@ public host = self.framework.db.get_host(opts) - return ret if( not host) + return ret if not host vulns = [] - if(opts[:proto] && opts[:port]) + if opts[:proto] && opts[:port] services = [] sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port]) return ret if sret == nil @@ -1725,7 +1686,7 @@ public clients = [] if opts[:host] or opts[:address] or opts[:addresses] - hosts = opts_to_hosts(opts) + hosts = opts_to_hosts(xopts) else hosts = wspace.hosts end @@ -1800,7 +1761,7 @@ public # rpc.call('db.connect', {:driver=>'postgresql'}) def rpc_connect(xopts) opts = fix_options(xopts) - if(not self.framework.db.driver and not opts[:driver]) + if not self.framework.db.driver and not opts[:driver] return { :result => 'failed' } end diff --git a/msfrpcd b/msfrpcd index b334b57c79..bfb882c3e3 100755 --- a/msfrpcd +++ b/msfrpcd @@ -30,9 +30,10 @@ arguments = Rex::Parser::Arguments.new( "-U" => [ true, "Specify the username to access msfrpcd" ], "-P" => [ true, "Specify the password to access msfrpcd" ], "-u" => [ true, "URI for Web server" ], - "-S" => [ false, "Disable SSL on the RPC socket" ], + "-t" => [ true, "Token Timeout (default 300 seconds" ], + "-S" => [ false, "Disable SSL on the RPC socket" ], "-f" => [ false, "Run the daemon in the foreground" ], - "-n" => [ false, "Disable database" ], + "-n" => [ false, "Disable database" ], "-h" => [ false, "Help banner" ]) opts = { @@ -40,7 +41,8 @@ opts = { 'SSL' => true, 'ServerHost' => '0.0.0.0', 'ServerPort' => 55553, - 'ServerType' => 'Msg' + 'ServerType' => 'Msg', + 'TokenTimeout' => 300, } foreground = false @@ -60,6 +62,8 @@ arguments.parse(ARGV) { |opt, idx, val| opts['User'] = val when '-P' opts['Pass'] = val + when "-t" + opts['TokenTimeout'] = val.to_i when "-f" foreground = true when "-u" diff --git a/plugins/msgrpc.rb b/plugins/msgrpc.rb index 0fde3ff249..30c1bee857 100644 --- a/plugins/msgrpc.rb +++ b/plugins/msgrpc.rb @@ -45,6 +45,7 @@ class Plugin::MSGRPC < Msf::Plugin user = opts['User'] || "msf" pass = opts['Pass'] || ::Rex::Text.rand_text_alphanumeric(8) uri = opts['URI'] || "/api" + timeout = opts['TokenTimeout'] || 300 print_status("MSGRPC Service: #{host}:#{port} #{ssl ? " (SSL)" : ""}") print_status("MSGRPC Username: #{user}") @@ -56,7 +57,8 @@ class Plugin::MSGRPC < Msf::Plugin :ssl => ssl, :cert => cert, :uri => uri, - :tokens => { } + :tokens => { }, + :token_timeout => timeout }) self.server.add_user(user, pass)