3571e53040
patches for easier mirroring, to eliminate a special copy, to make www.freebsd.org/security a full copy of security.freebsd.org and be eventually be the same. For now files are just sitting there. The symlinks are missing. Discussed on: www (repository location) Discussed with: simon (so)
297 lines
11 KiB
Text
297 lines
11 KiB
Text
-----BEGIN PGP SIGNED MESSAGE-----
|
|
|
|
=============================================================================
|
|
FreeBSD-SA-00:53 Security Advisory
|
|
FreeBSD, Inc.
|
|
|
|
Topic: catopen() may pose security risk for third party code
|
|
|
|
Category: core
|
|
Module: libc
|
|
Announced: 2000-09-27
|
|
Affects: FreeBSD 5.0-CURRENT, 4.x and 3.x prior to the correction date.
|
|
Corrected: Problem 1: 2000-08-06 (FreeBSD 5.0-CURRENT)
|
|
2000-08-22 (FreeBSD 4.1-STABLE)
|
|
2000-09-07 (FreeBSD 3.5-STABLE)
|
|
Problem 2: 2000-09-08 (FreeBSD 5.0-CURRENT, 4.1-STABLE and
|
|
3.5-STABLE)
|
|
Credits: Problem 1: Discovered during internal auditing
|
|
Problem 2: Ivan Arce <iarce@core-sdi.com>
|
|
FreeBSD only: NO
|
|
|
|
I. Background
|
|
|
|
catopen() and setlocale() are functions which are used to display text
|
|
in a localized format, e.g. for international users.
|
|
|
|
II. Problem Description
|
|
|
|
There are two problems addressed in this advisory:
|
|
|
|
1) The catopen() function did not correctly bounds-check an internal
|
|
buffer which could be indirectly overflowed by the setting of an
|
|
environment variable. A privileged application which uses catopen()
|
|
could be made to execute arbitrary code by an unprivileged local user.
|
|
|
|
2) The catopen() and setlocale() functions could be made to use an
|
|
arbitrary file as the source for localized data and message catalogs,
|
|
instead of one of the system files. An attacker could create a file
|
|
which is a valid locale file or message catalog but which contains
|
|
special formatting characters which may allow certain badly written
|
|
privileged applications to be exploited and execute arbitrary code as
|
|
the privileged user.
|
|
|
|
This second vulnerability is slightly different from the problem
|
|
originally discovered by Ivan Arce of Core-SDI which affects multiple
|
|
UNIX operating systems, which involved a different environment
|
|
variable and which FreeBSD is not susceptible to. However
|
|
Vulnerability 2 was discovered in FreeBSD after the publication the
|
|
Core-SDI advisory, and has the same effect on vulnerable applications.
|
|
|
|
NOTE that the FreeBSD base system is not believed to be vulnerable to
|
|
either of these problems, nor are any vulnerable third party programs
|
|
(including FreeBSD ports) currently known. Therefore the impact on the
|
|
majority of FreeBSD systems is expected to be nonexistent.
|
|
|
|
III. Impact
|
|
|
|
Certain setuid/setgid third-party software (including FreeBSD
|
|
ports/packages) may be vulnerable to a local exploit yielding
|
|
privileged access. No such software is however currently known.
|
|
|
|
It is believed that no program in the FreeBSD base system is
|
|
vulnerable to these bugs.
|
|
|
|
The problems were corrected prior to the release of FreeBSD 4.1.1.
|
|
|
|
IV. Workaround
|
|
|
|
Vulnerability 1 described above is the more serious of the two, since
|
|
it does not require the application to contain a coding flaw in order
|
|
to exploit it. A scanning utility is provided to detect privileged
|
|
binaries which use the catopen() function (both statically and
|
|
dynamically linked binaries), which should be either rebuilt, or have
|
|
their privileges limited to minimize potential risk.
|
|
|
|
It is not feasible to detect binaries which are vulnerable to the
|
|
second vulnerability, however the provided utility will also report
|
|
statically linked binaries which use the setlocale() functions and
|
|
which *may* potentially be vulnerable. Most of the binaries reported
|
|
will not in fact be vulnerable, but should be recompiled anyway for
|
|
maximum assurance of security. Note that some FreeBSD system binaries
|
|
may be reported as possibly vulnerable by this script, however this
|
|
is not the case.
|
|
|
|
Statically linked binaries which are identified as vulnerable or
|
|
potentially vulnerable should be recompiled from source code after
|
|
patching and recompiling libc, if possible, in order to correct the
|
|
vulnerability. Dynamically linked binaries will be corrected by simply
|
|
patching and recompiling libc as described below.
|
|
|
|
As an interim measure, consider removing any identified setuid or
|
|
setgid binary, removing set[ug]id privileges from the file, or
|
|
limiting the file access permissions, as appropriate.
|
|
|
|
Of course, it is possible that some of the identified files may be
|
|
required for the correct operation of your local system, in which case
|
|
there is no clear workaround except for limiting the set of users who
|
|
may run the binaries, by an appropriate use of user groups and
|
|
removing the "o+x" file permission bit.
|
|
|
|
1) Download the 'scan_locale.sh' and 'test_locale.sh' scripts from
|
|
|
|
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/tools/SA-00:53/scan_locale.sh
|
|
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/tools/SA-00:53/test_locale.sh
|
|
|
|
e.g. with the fetch(1) command:
|
|
|
|
# fetch ftp://ftp.freebsd.org/pub/FreeBSD/CERT/tools/SA-00:53/scan_locale.sh
|
|
Receiving scan_locale.sh (337 bytes): 100%
|
|
337 bytes transferred in 0.0 seconds (1.05 MBps)
|
|
# fetch ftp://ftp.freebsd.org/pub/FreeBSD/CERT/tools/SA-00:53/test_locale.sh
|
|
Receiving test_locale.sh (889 bytes): 100%
|
|
889 bytes transferred in 0.0 seconds (1.34 MBps)
|
|
|
|
2) Verify the md5 checksums and compare to the value below:
|
|
|
|
# /sbin/md5 scan_locale.sh
|
|
MD5 (scan_locale.sh) = efea80f74b05e7ddbc0261ef5211e453
|
|
# /sbin/md5 test_locale.sh
|
|
MD5 (test_locale.sh) = 2a485bf8171cc984dbc58b4d545668b4
|
|
|
|
3) Run the scan_locale.sh script against your system:
|
|
|
|
# sh scan_locale.sh ./test_locale.sh /
|
|
|
|
This will scan your entire system for setuid or setgid binaries which
|
|
make use of the exploitable function catopen(), or the potentially
|
|
exploitable function setlocale(). Each returned binary should be
|
|
examined (e.g. with 'ls -l' and/or other tools) to determine what
|
|
security risk it poses to your local environment, e.g. whether it can
|
|
be run by arbitrary local users who may be able to exploit it to gain
|
|
privileges.
|
|
|
|
Note that this script reports setlocale() usage (i.e. vulnerability 2)
|
|
only in statically linked binaries, not dynamically linked binaries,
|
|
because of the high rate of false positives. It is likely that the
|
|
majority of such setlocale() binaries identified are not insecure and
|
|
their identification by this script should not be taken as evidence
|
|
that they are vulnerable, but they should be recompiled anyway for
|
|
maximum assurance of security.
|
|
|
|
4) Remove the binaries, or reduce their file permissions, as appropriate.
|
|
|
|
V. Solution
|
|
|
|
Upgrade your vulnerable FreeBSD system to 4.1-STABLE or 3.5-STABLE
|
|
after the correction date, or patch your present system source code
|
|
and rebuild. Then run the scan_locale.sh script as instructed in
|
|
section IV and identify any statically-linked binaries as reported by
|
|
the script. These should either be removed, recompiled, or have
|
|
privileges restricted to secure them against this vulnerability (since
|
|
statically-linked binaries will not be affected by simply recompiling
|
|
the shared libc library).
|
|
|
|
To patch your present system: save the patch below into a file, and
|
|
execute the following commands as root:
|
|
|
|
cd /usr/src/lib/libc
|
|
patch < /path/to/patch/file
|
|
make all
|
|
make install
|
|
|
|
Patches for FreeBSD systems before the correction date:
|
|
|
|
Index: msgcat.c
|
|
===================================================================
|
|
RCS file: /usr2/ncvs//src/lib/libc/nls/msgcat.c,v
|
|
retrieving revision 1.21
|
|
retrieving revision 1.27
|
|
diff -u -r1.21 -r1.27
|
|
--- nls/msgcat.c 2000/01/27 23:06:33 1.21
|
|
+++ nls/msgcat.c 2000/09/01 11:56:31 1.27
|
|
@@ -91,8 +91,9 @@
|
|
__const char *catpath = NULL;
|
|
char *nlspath;
|
|
char *lang;
|
|
- long len;
|
|
char *base, *cptr, *pathP;
|
|
+ int spcleft;
|
|
+ long len;
|
|
struct stat sbuf;
|
|
|
|
if (!name || !*name) {
|
|
@@ -106,10 +107,10 @@
|
|
} else {
|
|
if (type == NL_CAT_LOCALE)
|
|
lang = setlocale(LC_MESSAGES, NULL);
|
|
- else {
|
|
- if ((lang = (char *) getenv("LANG")) == NULL)
|
|
- lang = "C";
|
|
- }
|
|
+ else
|
|
+ lang = getenv("LANG");
|
|
+ if (lang == NULL || strchr(lang, '/') != NULL)
|
|
+ lang = "C";
|
|
if ((nlspath = (char *) getenv("NLSPATH")) == NULL
|
|
#ifndef __NETBSD_SYSCALLS
|
|
|| issetugid()
|
|
@@ -129,13 +130,22 @@
|
|
*cptr = '\0';
|
|
for (pathP = path; *nlspath; ++nlspath) {
|
|
if (*nlspath == '%') {
|
|
+ spcleft = sizeof(path) - (pathP - path);
|
|
if (*(nlspath + 1) == 'L') {
|
|
++nlspath;
|
|
- strcpy(pathP, lang);
|
|
+ if (strlcpy(pathP, lang, spcleft) >= spcleft) {
|
|
+ free(base);
|
|
+ errno = ENAMETOOLONG;
|
|
+ return(NLERR);
|
|
+ }
|
|
pathP += strlen(lang);
|
|
} else if (*(nlspath + 1) == 'N') {
|
|
++nlspath;
|
|
- strcpy(pathP, name);
|
|
+ if (strlcpy(pathP, name, spcleft) >= spcleft) {
|
|
+ free(base);
|
|
+ errno = ENAMETOOLONG;
|
|
+ return(NLERR);
|
|
+ }
|
|
pathP += strlen(name);
|
|
} else *(pathP++) = *nlspath;
|
|
} else *(pathP++) = *nlspath;
|
|
@@ -186,7 +196,7 @@
|
|
MCSetT *set;
|
|
long lo, hi, cur, dir;
|
|
|
|
- if (!cat || setId <= 0) return(NULL);
|
|
+ if (cat == NULL || setId <= 0) return(NULL);
|
|
|
|
lo = 0;
|
|
if (setId - 1 < cat->numSets) {
|
|
@@ -212,8 +222,8 @@
|
|
if (hi - lo == 1) cur += dir;
|
|
else cur += ((hi - lo) / 2) * dir;
|
|
}
|
|
- if (set->invalid)
|
|
- (void) loadSet(cat, set);
|
|
+ if (set->invalid && loadSet(cat, set) <= 0)
|
|
+ return(NULL);
|
|
return(set);
|
|
}
|
|
|
|
@@ -225,7 +235,7 @@
|
|
MCMsgT *msg;
|
|
long lo, hi, cur, dir;
|
|
|
|
- if (!set || set->invalid || msgId <= 0) return(NULL);
|
|
+ if (set == NULL || set->invalid || msgId <= 0) return(NULL);
|
|
|
|
lo = 0;
|
|
if (msgId - 1 < set->numMsgs) {
|
|
@@ -318,7 +328,7 @@
|
|
off_t nextSet;
|
|
|
|
cat = (MCCatT *) malloc(sizeof(MCCatT));
|
|
- if (!cat) return(NLERR);
|
|
+ if (cat == NULL) return(NLERR);
|
|
cat->loadType = MCLoadBySet;
|
|
|
|
if ((cat->fd = _open(catpath, O_RDONLY)) < 0) {
|
|
@@ -351,7 +361,7 @@
|
|
|
|
cat->numSets = header.numSets;
|
|
cat->sets = (MCSetT *) malloc(sizeof(MCSetT) * header.numSets);
|
|
- if (!cat->sets) NOSPACE();
|
|
+ if (cat->sets == NULL) NOSPACE();
|
|
|
|
nextSet = header.firstSet;
|
|
for (i = 0; i < cat->numSets; ++i) {
|
|
Index: setlocale.c
|
|
===================================================================
|
|
RCS file: /home/ncvs/src/lib/libc/locale/setlocale.c,v
|
|
retrieving revision 1.27
|
|
retrieving revision 1.28
|
|
diff -u -r1.27 -r1.28
|
|
--- locale/setlocale.c 2000/09/04 03:43:24 1.27
|
|
+++ locale/setlocale.c 2000/09/08 07:29:48 1.28
|
|
@@ -129,7 +129,7 @@
|
|
if (!env || !*env)
|
|
env = getenv("LANG");
|
|
|
|
- if (!env || !*env)
|
|
+ if (!env || !*env || strchr(env, '/'))
|
|
env = "C";
|
|
|
|
(void) strncpy(new_categories[category], env, ENCODING_LEN);
|
|
|
|
-----BEGIN PGP SIGNATURE-----
|
|
Version: 2.6.2
|
|
|
|
iQCVAwUBOdKTo1UuHi5z0oilAQH9QwQAhEdiXOU7A/hZpMBKU5bWz6alLqr7o4wp
|
|
YcypPTnSoMQ2OkFlmuX9sdcgRfwl3gZ1z3QfjhE/eXG7rYSerEyxqcBqgQOBbCUH
|
|
vURxPEIRqV90DMMZAp62viA1X1Vyx/Ie2WXG/r5Wck1/Zu6BSxsUo3yiWD4gFoVb
|
|
L1f0kBgl2/A=
|
|
=YtCH
|
|
-----END PGP SIGNATURE-----
|