Bugtraq mailing list archives
ncurses 4.1 security bug
From: dps () IO STARGATE CO UK (Duncan Simpson)
Date: Tue, 7 Jul 1998 20:06:11 +0100
ncurses version 4.1 fails to drop priviledges before opening the termcap database and you can set any file(s) you like. I am not sure any setuid program allows an exploit but this is not good in any case. Here is a patch that stops that game. (Using the patch requires autoconf because I have not supplied diffs against the configure script). Terminfo information can be put anywhere by an environment variable and it will follow symlinks. This seems less dangerous but also wants plugging. There are 3 version of each plug supplied: setfsuid, setreuid and seteuid plus saved ids. You can define KEEP_PRIVS if you still wish to take the risk. Duncan (-: --- ncurses/read_termcap.c.dist Tue Jul 7 18:40:52 1998 +++ ncurses/read_termcap.c Tue Jul 7 19:23:34 1998 @@ -43,6 +43,14 @@ #include <term.h> #include <tic.h> #include <term_entry.h> +#include <unistd.h> + +#ifdef HAVE_FSUID_H +#include <sys/fsuid.h> +#endif /* HAVE_FSUID_H */ +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif /* HAVE_SYS_TYPES_H */ #if HAVE_FCNTL_H #include <fcntl.h> @@ -397,6 +405,10 @@ int tc_not_resolved; int current; int lineno; +#ifndef KEEP_PRIVS + uid_t fsuid; + gid_t fsgid; +#endif /* KEEP_PRIVS */ /* * Return with ``loop detected'' error if we've recurred more than @@ -442,7 +454,43 @@ if (fd >= 0) { (void)lseek(fd, (off_t)0, SEEK_SET); } else { +#ifndef KEEP_PRIVS +#ifdef HAVE_SETFSUID + /* drop privs to make sure file allowed */ + fsuid=setfsuid(getuid()); + fsgid=setfsgid(getgid()); +#else + fsuid=getuid(); + fsgid=getgid(); +#ifdef HAVE_SETREUID + /* Swap real and effective uid */ + setreuid(geteuid(), getuid()); + serregid(getegid(), getgid()); +#else + seteuid(getuid()); /* Saved ids or broken */ + setegid(getgid()); +#endif /* HAVE_SETREUID */ +#endif /* HACE_SETFSUID */ +#endif /* KEEP PRIVS */ fd = open(db_array[current], O_RDONLY, 0); +#ifndef KEEP_PRIVS +#ifdef HAVE_SETFSUID + /* Safe to restore them now */ + uid=setfsuid(fsuid); + gid=setfsgid(fsgid); +#else +#ifdef HAVE_SETREUID + /* Swap real and effective uid */ + setreuid(geteuid(), getuid()); + serregid(getegid(), getgid()); +#else + seteuid(fsuid); /* Saved ids or broken */ + setegid(fsgid); +#endif /* HAVE_SETREUID */ +#endif /* HACE_SETFSUID */ + +#endif /* KEEP PRIVS */ + if (fd < 0) { /* No error on unfound file. */ if (errno == ENOENT) --- configure.in.old Tue Jul 7 18:52:52 1998 +++ configure.in Tue Jul 7 19:15:12 1998 @@ -396,6 +396,9 @@ ttyent.h \ unistd.h \ values.h \ +sys/types.h \ +sys/fsuid.h \ +errno.h \ ) # check for HPUX's ANSI compiler @@ -460,6 +463,12 @@ usleep \ vfscanf \ vsscanf \ +setfsuid \ +setfsgid \ +setreuid \ +setregid \ +seteuid \ +setuid \ ) if test $ac_cv_func_sigaction = yes; then --- ncurses/read_entry.c.dist Tue Jul 7 19:48:08 1998 +++ ncurses/read_entry.c Tue Jul 7 19:52:03 1998 @@ -31,6 +31,12 @@ #if HAVE_FCNTL_H #include <fcntl.h> #endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_FSUID_H +#include <sys/fsuid.h> +#endif #include <sys/stat.h> #include <term.h> @@ -83,8 +89,49 @@ int name_size, bool_count, num_count, str_count, str_size; int i, fd, numread; char buf[MAX_ENTRY_SIZE]; - - if ((fd = open(filename, O_RDONLY)) < 0) +#ifndef KEEP_PRIVS + uid_t fsuid; + gid_t fsgid; +#endif /* KEEP_PRIVS */ + +#ifndef KEEP_PRIVS +#ifdef HAVE_SETFSUID + /* drop privs to make sure file allowed */ + fsuid=setfsuid(getuid()); + fsgid=setfsgid(getgid()); +#else + fsuid=getuid(); + fsgid=getgid(); +#ifdef HAVE_SETREUID + /* Swap real and effective uid */ + setreuid(geteuid(), getuid()); + serregid(getegid(), getgid()); +#else + seteuid(getuid()); /* Saved ids or broken */ + setegid(getgid()); +#endif /* HAVE_SETREUID */ +#endif /* HACE_SETFSUID */ +#endif /* KEEP PRIVS */ + fd=open(filename, O_RDONLY); +#ifndef KEEP_PRIVS +#ifdef HAVE_SETFSUID + /* drop privs to make sure file allowed */ + fsuid=setfsuid(getuid()); + fsgid=setfsgid(getgid()); +#else + fsuid=getuid(); + fsgid=getgid(); +#ifdef HAVE_SETREUID + /* Swap real and effective uid */ + setreuid(geteuid(), getuid()); + serregid(getegid(), getgid()); +#else + seteuid(getuid()); /* Saved ids or broken */ + setegid(getgid()); +#endif /* HAVE_SETREUID */ +#endif /* HACE_SETFSUID */ +#endif /* KEEP PRIVS */ + if (fd<0) return(0); T(("read terminfo %s", filename));
Current thread:
- ncurses 4.1 security bug Duncan Simpson (Jul 07)
- Re: ncurses 4.1 security bug Perry E. Metzger (Jul 07)
- Re: ncurses 4.1 security bug Alan Cox (Jul 08)
- Re: ncurses 4.1 security bug Perry E. Metzger (Jul 08)
- Re: ncurses 4.1 security bug Alan Cox (Jul 08)
- Re: ncurses 4.1 security bug Warner Losh (Jul 09)
- Re: ncurses 4.1 security bug David Schwartz (Jul 09)
- Re: ncurses 4.1 security bug matthew green (Jul 10)
- Re: ncurses 4.1 security bug Theo de Raadt (Jul 10)
- Re: ncurses 4.1 security bug Wietse Venema (Jul 12)
- Seattle Lab fixes security issue in SLmail Aleph One (Jul 12)
- Re: ncurses 4.1 security bug Alan Cox (Jul 08)
- Re: ncurses 4.1 security bug Perry E. Metzger (Jul 07)