COMMAND
ncurses
SYSTEMS AFFECTED
ncurses 4.2, 5.0 (earlier?)
PROBLEM
Jouko Pynnen found following. The CRT screen handling library
ncurses contains buffer overflows, making programs using it
vulnerable. If the programs are setuid or setgid, a local user
may elevate their privilege. The problem exists in ncurses
versions 4.2 and 5.0, probably earlier, and libocurses. The
overflows can be exploited if the library implementation supports
loading of user defined terminfo files from ~/.terminfo.
The problem has been tested and found on
* SuSE Linux 6.4, Red Hat Linux 6.1. A setuid program using
ncurses ("cda" in the xmcd package) was successfully
exploited to spawn a root shell.
* FreeBSD, the program /usr/bin/systat is setgid and uses
libncurses. An exploit was made which gives a shell with
egid=kmem. The kmem group has read access to /dev/kmem and
memory of all processes via /proc/<pid>/mem, and could be
used to read e.g. crypted or cleartext passwords,
authorization keys, or any other info that might be in
programs' memory space.
* OpenBSD, having /usr/bin/systat setgid kmem too. No test
exploit was made, but the program segfaults when given an
"evil" terminfo file. Making a similar exploit is probably
possible. This applies to other BSD systems as well, but
haven't been tested or confirmed.
All programs using ncurses aren't necessarily vulnerable, e.g.
"screen" is setuid root on some systems and uses ncurses, but it
doesn't seem to use the vulnerable functions at least directly
(investigated on Red Hat Linux, other systems may vary).
When using telnet to connect to a remote system, telnetd on some
platforms doesn't ignore TERMINFO_DIRS or TERMCAP environment
variables (e.g. OpenBSD). This means the problem could be
remotely exploitable under some conditions on some platforms.
This hasn't been confirmed with an exploit, however by setting
TERMCAP the OpenBSD telnetd can be made read any file as root. If
the file is something like /dev/zero, the telnetd process reads it
infinitely until the system runs out of memory.
The file ncurses/tty/lib_mvcur.c contains functions for moving
around the cursor. Some of the functions contain calls to
strcpy() without bound checking. The target of the strcpy's is a
local fixed size buffer in onscreen_mvcur():
static inline int
onscreen_mvcur(int yold,int xold,int ynew,int xnew, bool ovw)
/* onscreen move from (yold, xold) to (ynew, xnew) */
{
char use[OPT_SIZE], *sp;
... a few lines later:
sp = tparm(SP->_address_cursor, ynew, xnew);
if (sp)
{
tactic = 0;
(void) strcpy(use, sp);
The function tparm() returns a control string for screen
manipulation, originating from the terminfo file read according
to the environment variables TERM and TERMINFO_DIRS. Even though
ncurses implementations on some platforms reportedly ignore
TERMINFO_DIRS while running setuid/setgid, they check ~/.terminfo/
for the capability files in any case.
OPT_SIZE seems to be defined as 512. tparm() can be made return a
string of arbitrary length containing arbitrary data, so
exploitation is usually quite trivial. There are a few of similar
strcpy() calls in other functions in the file. Many other ncurses
functions may also call the cursor moving functions (e.g.
endwin()) so in order to be vulnerable, a program needn't call
mvcur().
SOLUTION
The authors of ncurses and OS vendors have been informed over a
week ago and they have, or will release fix packages shortly.
A temporary solution is to remove the setuid/setgid bits of
programs using ncurses. To check if a program uses ncurses, type
(on most systems):
ldd /path/to/program
If libncurses or libocurses is mentioned in the library listing
and the program is setuid/setgid, then there's a possibility for
it to be exploited. If 'ldd' doesn't exist on the system (or the
program is statically linked) you can try something like
grep -li TERMINFO /path/to/program
If it outputs the file path, the program probably uses ncurses or
derivative. To remove the setuid/setgid bits, issue the command:
chmod ug-s /path/to/file
FWIW - no version of NetBSD is distributed with ncurses as the
base curses library, it is available in the package system as an
addon. There are no str* calls performed on user supplied data
(including the termcap information) and we use a new termcap
interface that bounds checks information from the termcap
entries. An audit of the NetBSD source tree was performed in May
2000 to replace the old, unbounded, termcap interface with the
updated one.
For Caldera Systems:
- OpenLinux Desktop 2.3
- ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/RPMS/
- ftp://ftp.calderasystems.com/pub/updates/OpenLinux/2.3/current/SRPMS
* RPMS/ncurses-4.2-6.i386.rpm
* RPMS/ncurses-devel-4.2-6.i386.rpm
* RPMS/ncurses-devel-static-4.2-6.i386.rpm
* RPMS/ncurses-termcap-devel-4.2-6.i386.rpm
* RPMS/ncurses-termcap-devel-static-4.2-6.i386.rpm
* SRPMS/ncurses-4.2-6.src.rpm
- OpenLinux eServer 2.3 and OpenLinux eBuilder for ECential 3.0
- ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/RPMS/
- ftp://ftp.calderasystems.com/pub/updates/eServer/2.3/current/SRPMS
* RPMS/ncurses-4.2-6.i386.rpm
* RPMS/ncurses-devel-4.2-6.i386.rpm
* RPMS/ncurses-devel-static-4.2-6.i386.rpm
* RPMS/ncurses-termcap-devel-4.2-6.i386.rpm
* RPMS/ncurses-termcap-devel-static-4.2-6.i386.rpm
* SRPMS/ncurses-4.2-6.src.rpm
- OpenLinux eDesktop 2.4
- ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/RPMS/
- ftp://ftp.calderasystems.com/pub/updates/eDesktop/2.4/current/SRPMS
* RPMS/ncurses-4.2-6.i386.rpm
* RPMS/ncurses-devel-4.2-6.i386.rpm
* RPMS/ncurses-devel-static-4.2-6.i386.rpm
* RPMS/ncurses-termcap-devel-4.2-6.i386.rpm
* RPMS/ncurses-termcap-devel-static-4.2-6.i386.rpm
* SRPMS/ncurses-4.2-6.src.rpm
For SuSE Linux:
ftp://ftp.suse.com/pub/suse/noarch/perms-ncurses.sh
For FreeBSD:
fetch ftp://ftp.FreeBSD.org/pub/FreeBSD/CERT/patches/SA-00:68/ncurses.tar.gz
fetch ftp://ftp.FreeBSD.org/pub/FreeBSD/CERT/patches/SA-00:68/ncurses.tar.gz.asc
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-3-stable/devel/ncurses-5.2.tgz
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-4-stable/devel/ncurses-5.2.tgz
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/alpha/packages-4-stable/devel/ncurses-5.2.tgz
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/i386/packages-5-current/devel/ncurses-5.2.tgz
ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/alpha/packages-5-current/devel/ncurses-5.2.tgz
For Red Hat:
ftp://updates.redhat.com/6.2/alpha/ncurses-5.0-12.alpha.rpm
ftp://updates.redhat.com/6.2/alpha/ncurses-devel-5.0-12.alpha.rpm
ftp://updates.redhat.com/6.2/sparc/ncurses-5.0-12.sparc.rpm
ftp://updates.redhat.com/6.2/sparc/ncurses-devel-5.0-12.sparc.rpm
ftp://updates.redhat.com/6.2/i386/ncurses-5.0-12.i386.rpm
ftp://updates.redhat.com/6.2/i386/ncurses-devel-5.0-12.i386.rpm
ftp://updates.redhat.com/6.2/SRPMS/ncurses-5.0-12.src.rpm
ftp://updates.redhat.com/7.0/i386/ncurses-5.2-2.i386.rpm
ftp://updates.redhat.com/7.0/i386/ncurses-devel-5.2-2.i386.rpm
ftp://updates.redhat.com/7.0/SRPMS/ncurses-5.2-2.src.rpm
For Debian:
http://security.debian.org/dists/potato/updates/main/source/ncurses_5.0-6.0potato1.diff.gz
http://security.debian.org/dists/potato/updates/main/source/ncurses_5.0-6.0potato1.dsc
http://security.debian.org/dists/potato/updates/main/source/ncurses_5.0.orig.tar.gz
http://security.debian.org/dists/potato/updates/main/binary-all/ncurses-base_5.0-6.0potato1_all.deb
http://security.debian.org/dists/potato/updates/main/binary-all/ncurses-term_5.0-6.0potato1_all.deb
http://security.debian.org/dists/potato/updates/main/binary-alpha/libncurses5-dbg_5.0-6.0potato1_alpha.deb
http://security.debian.org/dists/potato/updates/main/binary-alpha/libncurses5-dev_5.0-6.0potato1_alpha.deb
http://security.debian.org/dists/potato/updates/main/binary-alpha/libncurses5_5.0-6.0potato1_alpha.deb
http://security.debian.org/dists/potato/updates/main/binary-alpha/ncurses-bin_5.0-6.0potato1_alpha.deb
http://security.debian.org/dists/potato/updates/main/binary-arm/libncurses5-dbg_5.0-6.0potato1_arm.deb
http://security.debian.org/dists/potato/updates/main/binary-arm/libncurses5-dev_5.0-6.0potato1_arm.deb
http://security.debian.org/dists/potato/updates/main/binary-arm/libncurses5_5.0-6.0potato1_arm.deb
http://security.debian.org/dists/potato/updates/main/binary-arm/ncurses-bin_5.0-6.0potato1_arm.deb
http://security.debian.org/dists/potato/updates/main/binary-i386/libncurses5-dbg_5.0-6.0potato1_i386.deb
http://security.debian.org/dists/potato/updates/main/binary-i386/libncurses5-dev_5.0-6.0potato1_i386.deb
http://security.debian.org/dists/potato/updates/main/binary-i386/libncurses5_5.0-6.0potato1_i386.deb
http://security.debian.org/dists/potato/updates/main/binary-i386/ncurses-bin_5.0-6.0potato1_i386.deb
http://security.debian.org/dists/potato/updates/main/binary-m68k/libncurses5-dbg_5.0-6.0potato1_m68k.deb
http://security.debian.org/dists/potato/updates/main/binary-m68k/libncurses5-dev_5.0-6.0potato1_m68k.deb
http://security.debian.org/dists/potato/updates/main/binary-m68k/libncurses5_5.0-6.0potato1_m68k.deb
http://security.debian.org/dists/potato/updates/main/binary-m68k/ncurses-bin_5.0-6.0potato1_m68k.deb
http://security.debian.org/dists/potato/updates/main/binary-powerpc/libncurses5-dbg_5.0-6.0potato1_powerpc.deb
http://security.debian.org/dists/potato/updates/main/binary-powerpc/libncurses5-dev_5.0-6.0potato1_powerpc.deb
http://security.debian.org/dists/potato/updates/main/binary-powerpc/libncurses5_5.0-6.0potato1_powerpc.deb
http://security.debian.org/dists/potato/updates/main/binary-powerpc/ncurses-bin_5.0-6.0potato1_powerpc.deb
http://security.debian.org/dists/potato/updates/main/binary-sparc/libncurses5-dbg_5.0-6.0potato1_sparc.deb
http://security.debian.org/dists/potato/updates/main/binary-sparc/libncurses5-dev_5.0-6.0potato1_sparc.deb
http://security.debian.org/dists/potato/updates/main/binary-sparc/libncurses5_5.0-6.0potato1_sparc.deb
http://security.debian.org/dists/potato/updates/main/binary-sparc/ncurses-bin_5.0-6.0potato1_sparc.deb
For Immunix OS:
http://www.immunix.org/ImmunixOS/6.2/updates/RPMS/ncurses-5.0-12_StackGuard.i386.rpm
http://www.immunix.org/ImmunixOS/6.2/updates/RPMS/ncurses-devel-5.0-12_StackGuard.i386.rpm
http://www.immunix.org/ImmunixOS/6.2/updates/SRPMS/ncurses-5.0-12_StackGuard.src.rpm
http://www.immunix.org/ImmunixOS/7.0-beta/updates/RPMS/ncurses-5.2-2_StackGuard.i386.rpm
http://www.immunix.org/ImmunixOS/7.0-beta/updates/RPMS/ncurses-devel-5.2-2_StackGuard.i386.rpm
http://www.immunix.org/ImmunixOS/7.0-beta/updates/SRPMS/ncurses-5.2-2_StackGuard.src.rpm
For Turbo Linux:
ftp://ftp.turbolinux.com/pub/updates/6.0/security/ncurses-5.2-2.i386.rpm
ftp://ftp.turbolinux.com/pub/updates/6.0/security/ncurses-devel-5.2-2.i386.rpm
ftp://ftp.turbolinux.com/pub/updates/6.0/SRPMS/ncurses-5.2-2.src.rpm