PulseAudio local race condition privilege escalation vulnerability

--=-tBNsGa/1icyUJVCt3cKm
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

------------------------------------------------------------------------
PulseAudio local race condition privilege escalation vulnerability
------------------------------------------------------------------------
Yorick Koster, June 2009

------------------------------------------------------------------------
Abstract
------------------------------------------------------------------------

The PulseAudio binary is affected by a local race condition. If the=20
binary is installed as SUID root, it is possible to exploit this=20
vulnerability to gain root privileges. This attack requires that a local
attacker can create hard links on the same hard disk partition on which
PulseAudio is installed (i.e. /usr/bin and /tmp reside on the same=20
partition).

------------------------------------------------------------------------
See also
------------------------------------------------------------------------

- CVE-2009-1894 [2]
- GLSA 200907-13 [3] PulseAudio: Local privilege escalation
- USN-804-1 [4] PulseAudio vulnerability

------------------------------------------------------------------------
Tested version
------------------------------------------------------------------------

This issue was successfully verified on the following Linux=20
distributions:

- Ubuntu 9.04 running PulseAudio version 0.9.14
- Debian 5.0 running PulseAudio version 0.9.10
- Mandriva Linux 2009 Spring running PulseAudio version 0.9.15

------------------------------------------------------------------------
Fix
------------------------------------------------------------------------

A patch for PulseAudio was released that addresses this issue. This=20
patch can be obtained from the following location:

http://git.0pointer.de/?p=3Dpulseaudio.git;a=3Dcommit;h=3D84200b423ebfa7e2d=
ad9b1b65f64eac7bf3d2114

As a temporary workaround, remove the SUID bit from the PulseAudio=20
binary.

$ chmod u-s `which pulseaudio`

------------------------------------------------------------------------
Introduction
------------------------------------------------------------------------

PulseAudio [5] is a sound server for POSIX and Win32 systems. A sound=20
server is basically a proxy for your sound applications. It allows you=20
to do advanced operations on your sound data as it passes between your=20
application and your hardware.

On some systems, the PulseAudio binary is installed SUID root to enable=20
real-time scheduling. If set, the daemon will drop root privileges=20
immediately on startup, however it will retain the CAP_NICE capability=20
(on systems that support it), but only if the calling user is a member=20
of the pulse-rt group. For all other users all capabilities are dropped=20
immediately.

------------------------------------------------------------------------
Race condition
------------------------------------------------------------------------

If the PulseAudio binary is started on Linux systems, it checks if the=20
LD_BIND_NOW environment variable is set. If this is not the case,=20
PulseAudio will set the variable and it will reload itself. It tries to=20
determine its path name by looking at the /proc/self/exe symbolic link.=20
This symbolic link will point to the full path name of the current=20
process.

int main(int argc, char *argv[]) {
[...]
#if defined(__linux__) && defined(__OPTIMIZE__)
	/*
		Disable lazy relocations to make usage of external libraries
		more deterministic for our RT threads. We abuse __OPTIMIZE__ as
		a check whether we are a debug build or not.
	*/
=09
	if (!getenv("LD_BIND_NOW")) {
		char *rp;
=09
		/* We have to execute ourselves, because the libc caches the
		* value of $LD_BIND_NOW on initialization. */
=09
		pa_set_env("LD_BIND_NOW", "1");
		pa_assert_se(rp =3D pa_readlink("/proc/self/exe"));
		pa_assert_se(execv(rp, argv) =3D=3D 0);
	}
#endif

Normally, /proc/self/exe will point to something like=20
/usr/bin/pulseaudio. However by using hard links, it is possible to=20
cause /proc/self/exe to point to a different location.

$ cd /tmp
$ ls -la /proc/self/exe
lrwxrwxrwx 1 yorick yorick 0 2009-06-09 16:31 /proc/self/exe ->=20
/bin/ls
$ ln `which ls` ls
$ ./ls -la /proc/self/exe
lrwxrwxrwx 1 yorick yorick 0 2009-06-09 16:31 /proc/self/exe ->=20
/tmp/ls

In addition, if a hard link is created, the SUID bit is preserved.

$ ln `which pulseaudio` pulseaudio
$ ls -la pulseaudio=20
-rwsr-xr-x 2 root root 71616 2009-04-09 02:12 pulseaudio

A race condition exists in the reload mechanism of PulseAudio. An=20
attacker can exploit this issue by creating a hard link pointing to the=20
PulseAudio binary. After this it can execute this binary through the=20
hard link. At this moment /proc/sef/exe will point to the hard link.=20
Before PulseAudio is restarted, the attacker can replace the hard link=20
with a different (executable) file or (symbolic) link. If PulseAudio is=20
restarted, it will use a path name that at this moment points to a=20
different file, for example a command shell. Root privileges are not=20
dropped when PulseAudio is reloading, thus allowing a local attacker to=20
gain root privileges.

Please note, this attack is only possible if the attacker can create=20
hard links on the same hard disk partition on which PulseAudio is=20
installed (i.e. /usr/bin and /tmp reside on the same partition).

------------------------------------------------------------------------
Proof of concept
------------------------------------------------------------------------

The following proof of concept can be used to exploit this issue. The=20
proof of concept tries to exploit this issue by creating hard links in=20
the /tmp directory.

pa_race [6]

$ ./pa_race
I: caps.c: Limited capabilities successfully to CAP_SYS_NICE.
I: caps.c: Dropping root privileges.
I: caps.c: Limited capabilities successfully to CAP_SYS_NICE.
N: main.c: Called SUID root and real-time and/or high-priority=20
scheduling was requested in the configuration. However, we lack the=20
necessary privileges:
N: main.c: We are not in group pulse-rt, PolicyKit refuse to
 grant us the requested privileges and we have no increase=20
RLIMIT_NICE/RLIMIT_RTPRIO resource limits.
N: main.c: For enabling real-time/high-priority scheduling please=20
acquire the appropriate PolicyKit privileges, or become a member of=20
pulse-rt, or increase the RLIMIT_NICE/RLIMIT_RTPRIO resource
 limits for this user.
E: pid.c: Daemon already running.
E: main.c: pa_pid_file_create() failed.
[...]
uid=3D0(root) gid=3D0(root) groups=3D4(adm), 20(dialout), 24(cdrom),=20
25(floppy), 29(audio), 30(dip), 44(video), 46(plugdev), 107(fuse),=20
109(lpadmin), 115(admin), 1000(yorick)
#=20

------------------------------------------------------------------------
References
------------------------------------------------------------------------

[1] http://www.akitasecurity.nl/advisory.php?id=3DAK20090602
[2] http://cve.mitre.org/cgi-bin/cvename.cgi?name=3DCVE-2009-1894
[3] http://www.gentoo.org/security/en/glsa/glsa-200907-13.xml
[4] http://www.ubuntu.com/usn/usn-804-1
[5] http://pulseaudio.org/
[6] http://www.akitasecurity.nl/advisory/AK20090602/pa_race

------------------------------------------------------------------------
--=20
------------------------------------------------------------------------
Akita Software Security (Kvk 37144957)
http://www.akitasecurity.nl/
------------------------------------------------------------------------
Key fingerprint =3D 5FC0 F50C 8B3A 4A61 7A1F  2BFF 5482 D26E D890 5A65
http://keyserver.pgp.com/vkd/DownloadKey.event?keyid=3D0x5482D26ED8905A65

--=-tBNsGa/1icyUJVCt3cKm
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEABECAAYFAkpgTYoACgkQVILSbtiQWmWoewCcCMqzIA2dJix4OzIpwk2dkL5P
aFgAnA+Zu1zFgyt5F/qQy1tSGVcXMHbH
=xlUt
-----END PGP SIGNATURE-----

--=-tBNsGa/1icyUJVCt3cKm--