Critical vulnerability in PolKit allowing root access on most Linux distributions

Qualys Company revealed vulnerability (CVE-2021-4034) in the system component Polkit (formerly PolicyKit), used in distributions to arrange for unprivileged users to perform actions that require elevated access rights. The vulnerability allows an unprivileged local user to elevate their privileges to the root user and gain full control over the system. The issue has been codenamed PwnKit and is notable for producing a working exploit that runs in the default configuration on most Linux distributions.

The problem exists in the pkexec utility included with PolKit, which comes with the SUID root flag and is designed to run commands with other user’s privileges according to PolKit’s rules. Due to the incorrect handling of command-line arguments passed to pkexec, an unprivileged user could bypass authentication and have their code run as root, regardless of the access rules set. For an attack, it does not matter what settings and restrictions are set in PolKit, it is enough that the SUID root attribute is set for the executable file with the pkexec utility.

Pkexec does not check the correctness of the command line argument count (argc) passed when starting a process. The developers of pkexec assumed that the first entry in the argv array always contains the name of the process (pkexec), and the second entry is either NULL or the name of the command run via pkexec. Since the argument counter was not checked against the actual contents of the array and it was assumed that it is always greater than 1, in the case of passing an empty array argv to the process, which the function allows execve on Linux, pkexec treated NULL as the first argument (process name), and the memory beyond the end of the buffer as the next array content.

| argv[0] | argv[1] | ... | argv[argc] | envp[0] | envp[1] | ... | envp[envc] | 
V         V                V           V         V                V 
"program" "-option"           NULL      "value" "PATH=name"          NULL 

The problem is that following the argv array in memory is the envp array containing the environment variables. Thus, given an empty argv array, pkexec retrieves the command being run with elevated privileges from the first element of the environment variable array (argv[1] became identical to envp[0]), the content of which can be controlled by an attacker.

Having received the value of argv[1]pkexec tries to determine the full path to the executable file taking into account the file paths in PATH and write the pointer to the string with the full path back to argv[1]which causes the value of the first environment variable to be overwritten as well, since argv[1] identical to envp[0]. By manipulating the name of the first environment variable, an attacker can substitute another environment variable in pkexec, for example, substitute the “LD_PRELOAD” environment variable, which is not allowed in suid programs, and arrange for the process to load its shared library into the process.

The working exploit uses the GCONV_PATH variable substitution, which is used to determine the path to the symbol transcoding library that is dynamically loaded when calling the g_printerr() function, which uses iconv_open() in its code. By redefining the path in GCONV_PATH, the attacker can achieve loading not the regular iconv library, but his own library, the handlers from which will be executed during the error message at the stage when pkexec is still running as root and before the launch permissions check.

It is noted that although the problem is caused by memory corruption, it can be reliably and repeatably exploited regardless of the hardware architecture used. The prepared exploit has been successfully tested on Ubuntu, Debian, Fedora and CentOS, but can be used on other distributions as well. The original exploit is not publicly available yet, indicating that it is trivial and can be easily recreated by other researchers, so it is important to install the hotfix update as soon as possible on multi-user systems. Polkit is also available for BSD systems and Solaris, but has not been explored for exploitation. What is known is that the attack cannot be carried out in OpenBSD, since the OpenBSD kernel does not allow passing a null argc value when calling execve().

The problem has been present since May 2009, since additions pkexec commands. Vulnerability fix in PolKit is still available in the form patch (corrective release not formed), but because the distribution developers were aware of the problem in advance, most distributions published an update at the same time they disclosed the vulnerability. Issue fixed in RHEL 6/7/8, Debian, ubuntu, openSUSE, SUSE, Fedora, ALT Linux, ROSA, Gentoo, Void Linux, Arch Linux and Manjaro. As a temporary measure to block the vulnerability, you can remove the SUID root flag from the /usr/bin/pkexec program (“chmod 0755 /usr/bin/pkexec”).

Addendum 1: In the public domain appeared first options exploits from third parties developers.

Addendum 2: About a possible vulnerability in PolKit related to the handling of empty arguments and the pkexec suid application, reported back in 2013, but since the researcher did not bring the idea to a working exploit, the warning was ignored and the problem was not fixed.


About Lee Michaelis 142714 Articles
Before starting GamingDeputy, I used to spend my day modding games and searching for new wallpapers. A vivid writer and a blogger. I enjoy giving tech support to people in help (mostly my brother). Racing, MMO, RTS games are my favs.