By Jake Edge
October 27, 2010
Tavis Ormandy has been busy of late, poking around in the guts of GNU
libc. Out of that have come two separate local privilege escalations that
exploit an obscure corner (the dynamic linker auditing API) of glibc, while
the exploits themselves use—abuse—some Linux features that many
probably aren't aware of. These vulnerabilities and exploits provide good
examples of the way that security researchers look at code and
systems—a way of looking that more developers would do well to emulate.
The runtime library auditing API is a way for developers to intercept the
actions of the dynamic linker to see the steps that it is taking while
searching for .so files and resolving symbols from them. When a
program is executed with the LD_AUDIT environment variable
pointing to one or more shared libraries, the linker will make callbacks
into functions in those libraries for various events that happen in the
linking process. There are various events specified in the rtld-audit
man page, including searching for an object, opening an object, binding to
a symbol, and so on. It seems like a useful facility, but one that is
likely not in the toolbox of many Linux developers.
The simpler of the two problems that Ormandy found was that setuid
programs will open whatever arbitrary library a user specifies in
LD_AUDIT, as long as that library lives on the trusted library path. The more well-known LD_PRELOAD environment
variable, which preloads the specified libraries before the linker searches
for others, is specifically prohibited from operating on setuid
programs unless the library is on the trusted path and has the
setuid bit set. Exploiting ping (or some other setuid program)
with LD_PRELOAD would be trivial—a user-provided library could
remap any call ping made to anything the attacker wanted—so
it was an
obvious restriction. LD_AUDIT using non-setuid libraries was evidently not so obvious.
The problem with allowing user-provided libraries to be used for auditing
setuid programs is not anywhere in the auditing API, but is
instead inherent in the way the runtime linker processes libraries. When
the library is opened with dlopen() to determine whether the
auditing callback symbols are present, any library initialization routines
must be
run. So, an exploit is done by finding a vulnerable system library
(it must be on the trusted path) that was not written with setuid
execution in mind (and thus does not have that bit set in the filesystem).
In his description of the
flaw, Ormandy gives an example of using the libpcprofile.so
library, which writes an output file to the path specified by the
PCPROFILE_OUTPUT environment variable. Using ping for
its setuid nature, he sets LD_AUDIT to the library,
points PCPROFILE_OUTPUT where he wants, and
ping ends up putting a user-writable file in
/etc/cron.d. The details will vary depending on the distribution,
but most will be vulnerable to the flaw.
There is nothing particularly special about libpcprofile.so, as
Ormandy describes ways to find other vulnerable system libraries, which are
likely to be numerous—those libraries weren't meant to be used by
privileged programs.
The other vulnerability is
more difficult to exploit, but stems from a similar laxness in
LD_AUDIT handling. In the Linux executable file format, ELF,
library search paths can be specified in the executable itself using
DT_RPATH or DT_RUNPATH tags. Those tags can contain a
$ORIGIN value, which is replaced with location of the executable
in the filesystem. That way, a library used by a single executable can be
located in a program-specific location rather than in the system library
directories.
The ELF specification recommends that $ORIGIN be disallowed for
setuid executables, but glibc ignores that recommendation.
Ormandy doesn't really see a problem with that:
It is tough to form a thorough complaint about this glibc behaviour however,
as any developer who believes they're smart enough to safely create suid
programs should be smart enough to understand the implications of $ORIGIN
and hard links on load behaviour. The glibc maintainers are some of the
smartest guys in free software, and well known for having a "no hand-holding"
stance on various issues, so I suspect they wanted a better argument than this
for modifying the behaviour (I pointed it out a few years ago, but there was
little interest).
Unfortunately, the $ORIGIN substitution code was reused in the
LD_AUDIT path. There was seemingly an attempt to restrict the use
of $ORIGIN in LD_AUDIT for privileged programs, but it
was insufficient. $ORIGIN will be expanded if it is the
only entry in LD_AUDIT. Since $ORIGIN expands to the
directory that contained the program, it isn't necessarily obvious that
there is anything there to exploit. But, there are known ways to exploit this
kind of situation.
If the directory that contains the executable can be replaced with an
exploit library object between the time $ORIGIN is expanded and
when the
value is used, the library will be loaded and the attacker can do what they
like. It is essentially a
race condition, but one that can be reliably won by the attacker.
Ormandy's example basically pauses the execution of a ping that
has been hardlinked into an attacker-controlled directory after the
expansion of $ORIGIN has been done. He then removes the directory
and its contents, and puts a library that has exploit code in its
initialization function in the place of the directory.
That particular exploit mechanism is fairly modern, using relatively recent
Linux kernel features, but there are others. Ormandy describes several
other ways to exploit the flaw, with differing requirements (e.g. a C
compiler or winning an easily winnable race) that might serve different
attack strategies. While both are local privilege escalations, they very
well might be used in conjunction with a web application or other flaw to
turn them into a remote root vulnerability.
Both of these vulnerabilities are quite serious for systems that allow
untrusted users to log in. Their impact on other systems depends on
whether there are other vulnerable, network-facing programs. While it is a
bit ironic that it was an audit of LD_AUDIT behavior that found
these bugs, it seems clear that there isn't enough of that kind of auditing
being done for Linux systems. It's always a bit worrisome to think of how
many of these kinds of flaws are still lingering out there.
Comments (33 posted)
Brief items
The Mozilla Security Blog
warns
of a new Firefox vulnerability which is already being exploited.
"
Users who visited an infected site could have been affected by the
malware through the vulnerability. The trojan was initially reported as
live on the Nobel Peace Prize site, and that specific site is now being
blocked by Firefox's built-in malware protection. However, the exploit code
could still be live on other websites." Disabling JavaScript (or
running NoScript) will block exploit attempts.
Comments (42 posted)
New vulnerabilities
festival: code execution
| Package(s): | festival |
CVE #(s): | CVE-2010-3996
|
| Created: | October 22, 2010 |
Updated: | November 3, 2010 |
| Description: |
From the openSUSE advisory:
festival_server uses an unsafe LD_LIBRARY_PATH. Local users
could exploit that to execute code as another user if that
user runs festival_server. |
| Alerts: |
|
Comments (none posted)
glibc: privilege escalation
| Package(s): | glibc |
CVE #(s): | CVE-2010-3847
|
| Created: | October 21, 2010 |
Updated: | April 15, 2011 |
| Description: |
From the Red Hat advisory:
It was discovered that the glibc dynamic linker/loader did not handle the
$ORIGIN dynamic string token set in the LD_AUDIT environment variable
securely. A local attacker with write access to a file system containing
setuid or setgid binaries could use this flaw to escalate their privileges.
(CVE-2010-3847)
For a detailed look, see Tavis Ormandy's report.
|
| Alerts: |
|
Comments (none posted)
glibc: privilege escalation
| Package(s): | glibc |
CVE #(s): | CVE-2010-3856
|
| Created: | October 22, 2010 |
Updated: | January 12, 2011 |
| Description: |
From the Debian advisory:
Ben Hawkes and Tavis Ormandy discovered that the dynamic loader in GNU
libc allows local users to gain root privileges using a crafted
LD_AUDIT environment variable.
|
| Alerts: |
|
Comments (none posted)
libsmi: arbitrary code execution
| Package(s): | libsmi |
CVE #(s): | CVE-2010-2891
|
| Created: | October 22, 2010 |
Updated: | January 25, 2011 |
| Description: |
From the Mandriva advisory:
A buffer overflow was discovered in libsmi when long OID was given
in numerical form. This could lead to arbitrary code execution.
|
| Alerts: |
|
Comments (none posted)
pidgin: denial of service
| Package(s): | pidgin |
CVE #(s): | CVE-2010-3711
|
| Created: | October 21, 2010 |
Updated: | March 14, 2011 |
| Description: |
From the Red Hat advisory:
Multiple NULL pointer dereference flaws were found in the way Pidgin
handled Base64 decoding. A remote attacker could use these flaws to crash
Pidgin if the target Pidgin user was using the Yahoo! Messenger Protocol,
MSN, MySpace, or Extensible Messaging and Presence Protocol (XMPP) protocol
plug-ins, or using the Microsoft NT LAN Manager (NTLM) protocol for
authentication. (CVE-2010-3711)
|
| Alerts: |
|
Comments (none posted)
tuxguitar: code execution
| Package(s): | tuxguitar |
CVE #(s): | CVE-2010-3385
|
| Created: | October 21, 2010 |
Updated: | October 27, 2010 |
| Description: |
From the Red Hat bugzilla entry:
Raphael Geissert conducted a review of various packages in Debian and found
that tuxguitar contained a script that could be abused by an attacker to
execute arbitrary code [1].
The vulnerability is due to an insecure change to LD_LIBRARY_PATH, and
environment variable used by ld.so(8) to look for libraries in directories
other than the standard paths. When there is an empty item in the
colon-separated list of directories in LD_LIBRARY_PATH, ld.so(8) treats it as a
'.' (current working directory). If the given script is executed from a
directory where a local attacker could write files, there is a chance for
exploitation.
|
| Alerts: |
|
Comments (none posted)
Page editor: Jake Edge
Next page: Kernel development>>