Files
metasploit-gs/lib/msf/core/exploit/postgres.rb
T
Tod Beardsley 01adf60550 See #730. First pass at a Postgres Query module. Doesn't handle errors very well yet (still need to work all that out and create some test cases).
git-svn-id: file:///home/svn/framework3/trunk@8344 4d416f70-5f16-0410-b530-b9f4589650da
2010-02-02 01:40:48 +00:00

121 lines
3.8 KiB
Ruby

require 'msf/core'
module Msf
###
#
# This module exposes methods for querying a remote PostgreSQL service.
#
###
module Exploit::Remote::Postgres
require 'postgres_msf'
include Msf::Db::PostgresPR
attr_accessor :postgres_conn
#
# Creates an instance of a MSSQL exploit module.
#
def initialize(info = {})
super
# Register the options that all Postgres exploits may make use of.
register_options(
[
Opt::RHOST,
Opt::RPORT(5432),
OptString.new('DATABASE', [ true, 'The database to authenticate against', 'template1']),
OptString.new('USERNAME', [ true, 'The username to authenticate as', 'postgres']),
OptString.new('PASSWORD', [ true, 'The password for the specified username', '']),
OptBool.new('VERBOSE', [false, 'Enable verbose output', false])
], Msf::Exploit::Remote::Postgres)
register_autofilter_ports([ 5432 ])
register_autofilter_services(%W{ postgresql })
end
# postgres_login takes a number of arguments (defaults to the datastore for
# appropriate values), and will either populate self.postgres_conn and return
# :connected, or will return :error, :error_databse, or :error_credentials
# Fun fact: if you get :error_database, it means your username and password
# was accepted (you just failed to guess a correct running database instance).
#
# TODO: Clean this up some.
def postgres_login(args={})
postgres_logout if self.postgres_conn
db = args[:database] || datastore['DATABASE']
username = args[:username] || datastore['USERNAME']
password = args[:password] || datastore['PASSWORD']
ip = args[:server] || datastore['RHOST']
port = args[:port] || datastore['RPORT']
uri = "tcp://#{ip}:#{port}"
begin
self.postgres_conn = Connection.new(db,username,password,uri)
rescue RuntimeError => e
case e.to_s.split("\t")[1]
when "C3D000"
print_error "#{ip}:#{port} Postgres - Bad database name: #{db} (Credentials '#{username}:#{password}' is OK)"
return :error_database # Note this means the user:pass is good!
when "C28000"
print_error "#{ip}:#{port} Postgres - Bad username or password: '#{username}:#{password}'"
return :error_credentials
else
print_error "#{ip}:#{port} Postgres - Error: #{e.inspect}"
return :error
end
end
if self.postgres_conn
print_good "#{ip}:#{port} Postgres - Logged in to '#{db}' with '#{username}':'#{password}'" if datastore['VERBOSE']
return :connected
end
end
# Logs out of a database instance.
def postgres_logout
ip = datastore['RHOST']
port = datastore['RPORT']
if self.postgres_conn
self.postgres_conn.close if(self.postgres_conn.kind_of?(Connection) && self.postgres_conn.instance_variable_get("@conn"))
self.postgres_conn = nil
end
print_status "#{ip}:#{port} Postgres - Disconnected." if datastore['VERBOSE']
end
# TODO: Deal with malformed queries.
def postgres_query(sql=nil,doprint=false)
ip = datastore['RHOST']
port = datastore['RPORT']
postgres_login unless self.postgres_conn
if self.postgres_conn
sql ||= datastore['SQL']
print_status "#{ip}:#{port} Postgres - querying with '#{sql}'" if datastore['VERBOSE']
resp = self.postgres_conn.query(sql)
postgres_print_reply(resp,sql) if doprint
end
end
# TODO: write out the error conditions.
def postgres_print_reply(resp=nil,sql=nil)
ip = datastore['RHOST']
port = datastore['RPORT']
return nil unless resp.kind_of? Connection::Result
print_status "#{ip}:#{port} Postgres Query: Type: #{resp.cmd_tag} | Query Text: #{sql}"
if resp.rows and resp.fields and resp.rows.size > 0
print_status "#{ip}:#{port} Row Count: #{resp.rows.size}"
tbl = Rex::Ui::Text::Table.new(
'Indent' => 1,
'Header' => "",
'Columns' => resp.fields.map {|x| x.name}
)
resp.rows.each {|row| tbl << row.map { |x| x.nil? ? "NIL" : x } }
print_line(tbl.to_s)
end
end
end
end