Casinos Not On GamstopNon Gamstop CasinosCasinos Not On GamstopOnline Casinos UKNon Gamstop Casino
27th Sep 2000 [SBWID-153]
COMMAND
	    catopen() (libc)
SYSTEMS AFFECTED
	    FreeBSD 5.0-CURRENT, 4.x and 3.x prior to 2000-09-27
PROBLEM
	    Following  is   based  on   FreeBSD-SA-00:53  Security   Advisory.
	    catopen() and setlocale() are functions which are used to  display
	    text in a localized format, e.g. for international users.
	    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.
SOLUTION
	    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
	
	    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 (eg. with 'ls -l' and/or other tools)
	       to determine what  security  risk  it   poses  to  your   local
	       environment, eg. 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.
	    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  above  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);
	
	

Internet highlights