COMMAND
setlocale()
SYSTEMS AFFECTED
FreeBSD 2.1.x, 2.2 (prior to December 1996)
PROBLEM
Thomas H. Ptacek reported that anyone who installed FreeBSD 2.2
prior to December of 1996 is vulnerable to locale routine problems
similar to the one that afflicts crt0 start() in FreeBSD 2.1.x
(take a look at crt0 bug on this page).
Specifically, You are able to cause a shell to be executed from
any program that calls setlocale() in FreeBSD 2.2. Thomas tested
this out with dmesg, which promptly gave him an SGID "kmem" shell.
Note that programs that shed privilege using saved-set UIDs are
vulnerable to this problem as well, as the machine code used to
take over the affected programs can easily restore privilege.
The setlocale() call contains a number of potential exploits
through string overflows during environment variable expansion.
Because the 2.1.6 and earlier versions of FreeBSD called
setlocale() in the C runtime code, the problem is especially
acute there in that it essentially effects all binaries on the
system. In FreeBSD 2.2 BETA and later releases, the setlocale()
call was removed from crt0.c and the exploit closed through
additional checks.
The setlocale() library function looks for the environment
variable "PATH_LOCALE" in the current process's environment, and
if it exists, later copies the contents of this variable to a
stack buffer without doing proper bounds checking. If the
environment variable was specially initialized with the proper
amount and type of data prior to running a setuid program, it is
possible to cause the program to overflow its stack and execute
arbitrary code which could allow the user to become root. Any
binary linked on a system with setlocale() built into crt0.c or
which calls setlocale() directly has the buffer overrun
vulnerability. If this binary has the setuid or setgid bits set,
or is called by another setuid/setgid binary (even if that other
setuid/setgid binary does not have this vulnerability),
unauthorized access may be allowed.
SOLUTION
The locale routines were patched at the end of 1996 to cause
PATH_LOCALE (the environment variable who's contents are trampling
all over the stack frames of locale routines) to be ignored if the
euid doesn't match the uid; the patch also avoids the stack
overrun by allocating space for the variable on the heap with
strdup().
People running FreeBSD revisions that don't have this patch will
want to make sure they've applied these patches as soon as
possible. Vulnerability can easily be assessed by setting
LC_CTYPE, filling PATH_LOCALE with 2000 random characters, and
attempting to run /sbin/dmesg (which will segfault if the problem
exists).
FreeBSD recommends recompiling libc with the following patches
and then recompiling all staticly linked binaries (all in /sbin
and /bin as well as chflags, gunzip, gzcat, gzip, ld, tar and
zcat in /usr/bin) eliminates this vulnerability in FreeBSD 2.1.6
and earlier releases:
However, a full solution may require a re-link of all
setuid/setgid local binaries or all local binaries likely to
be called from another setuid/setgid program that were
originally linked statically under one of the affected OSs.
Dynamically linked executables will benefit directly from
this patch once libc is rebuilt and reinstalled and do not
need to be relinked.
Because of the severity of this security hole, a full update
release for FreeBSD 2.1.6 will also be released very shortly,
that release being provisionally assigned the version number of
2.1.7. Patch for this can be found at following address:
ftp://freebsd.org/pub/CERT/patches/SA-97:01/