One of the core concepts of secure programming is to mitigate effects of bugs and exploits by running application code with only the minimum set of privileges and resources needed to allow the program to fulfill its tasks. Dropping of privileges during execution, restrictive access permissions on resources will limit adverse effects of aberrant program behavior. But even after dropping privileges, the attack surface of a program, that reduced its privileges during runtime is different and sometimes larger than the attack surface when running on one level all the time. This page presents common programming errors and how to exploit them to gain privileges.
Apart from that, errors in application security design or implementation might not only cause those defense mechanisms to fail to archive their intented goals. They might give an illusion of security, and hence cause programmers to rely on them. That might make them care less about high quality code development when under the impression, that due to restricted privileges, the impact of software bugs will be small.
Usually system calls to drop privileges, e.g. setuid, when called as user root do not fail since the user still has all necessary privileges to do so. It might be unexpected, that a lower privileged still has ways to interfere with such an process to make calls to drop privileges fail. Without cheching the return values, the program will keep running with higher privileges. Thus exploitation of other bugs in the application will also use those elevated privileges. To avoid this is especially relevant in SUID-binaries and daemons, that want to run less privileged after startup.
The most common way is to cause resource starvation to make privilege change calls to fail. For example the setuid call can fail if there are already too many processes running with the target uid. Hence if there is a way for an attacker to fork enough processes with the lower privileged uid, e.g. Apache webserver child processes running as wwwdata exploiting a PHP installation, then a Apache control programs trying to setuid from root to wwwdata might fail doing so.
When a program drops privileges, it can still have file descriptors pointing to resources opened while running with higher privileges. The application might not be able to open these resources, but can continue to use those already open. This might be problematic in some cases:
It is very important to clean up everything before dropping privileges. For example the sequence setuid/exec may allow other processes running as the target user to attach to the process and access all open file descriptors or even forward them to another application using scm (see references).
One of the pecularities of TTYs is that they do not only provide input (stdin) for applications, but that is also possible to add data to the TTY input queue using TIOCSTI ioctl. To do that, the program has to have an open file descriptor pointing to the TTY. When started via command line, a program might run in the background, but can still have open file descriptors pointing to the TTY.
A problem may arise when root user starts an application and the application changes the user id via setuid. Other processes with the same uid might attach to the application and inject code to fill the TTY input queue using TIOCSTI. Since this is the same TTY the interactive shell, that started the application, is using, the data pushed back into the queue is read and executed by the interactive shell running with root privileges. Information about that kind of attack on different applications can be found here.
Last modified 20171228
Contact e-mail: me (%) halfdog.net