Lucene search

K
qualysblogBharat JogiQUALYSBLOG:837A30E6897F8F258644FDEDDF11F66D
HistoryJan 25, 2022 - 5:36 p.m.

PwnKit: Local Privilege Escalation Vulnerability Discovered in polkit’s pkexec (CVE-2021-4034)

2022-01-2517:36:43
Bharat Jogi
blog.qualys.com
390

7.8 High

CVSS3

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

7.2 High

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:L/AC:L/Au:N/C:C/I:C/A:C

The Qualys Research Team has discovered a memory corruption vulnerability in polkit's pkexec, a SUID-root program that is installed by default on every major Linux distribution. This easily exploited vulnerability allows any unprivileged user to gain full root privileges on a vulnerable host by exploiting this vulnerability in its default configuration.

About Polkit pkexec for Linux

Polkit (formerly PolicyKit) is a component for controlling system-wide privileges in Unix-like operating systems. It provides an organized way for non-privileged processes to communicate with privileged processes. It is also possible to use polkit to execute commands with elevated privileges using the command pkexec followed by the command intended to be executed (with root permission).

Potential Impact of PwnKit Vulnerability

Successful exploitation of this vulnerability allows any unprivileged user to gain root privileges on the vulnerable host. Qualys security researchers have been able to independently verify the vulnerability, develop an exploit, and obtain full root privileges on default installations of Ubuntu, Debian, Fedora, and CentOS. Other Linux distributions are likely vulnerable and probably exploitable. This vulnerability has been hiding in plain sight for 12+ years and affects all versions of pkexec since its first version in May 2009 (commit c8c3d83, "Add a pkexec(1) command").

As soon as our Research Team confirmed the vulnerability, Qualys engaged in responsible vulnerability disclosure and has coordinated with both vendor and open-source distributions to announce the vulnerability.

Vulnerability Disclosure Timeline

  • 2021-11-18: Advisory sent to secalert@redhat.
  • 2022-01-11: Advisory and patch sent to distros@openwall.
  • 2022-01-25: Coordinated Release Date (5:00 PM UTC).

Proof of Concept Video of PwnKit Exploit

View this video of a potential exploit path.

PwnKit Scan Video

View this video on how to get visibility of the PwnKit vulnerability using Qualys VMDR.

Technical Details of PwnKit Vulnerability

What follows is an explanation of how the PwnKit vulnerability works.

The beginning of pkexec's main() function processes the command-line arguments (lines 534-568), and searches for the program to be executed, if its path is not absolute, in the directories of the PATH environment variable (lines 610-640):

------------------------------------------------------------------------
435 main (int argc, char *argv[])
436 {
...
534   for (n = 1; n < (guint) argc; n++)
535     {
...
568     }
...
610   path = g_strdup (argv[n]);
...
629   if (path[0] != '/')
630     {
...
632       s = g_find_program_in_path (path);
...
639       argv[n] = path = s;
640     }
------------------------------------------------------------------------

Unfortunately, if the number of command-line arguments argc is 0 - which means if the argument list argv that we pass to execve() is empty, i.e. {NULL} - then argv[0] is NULL. This is the argument list's terminator. Therefore:

  • at line 534, the integer n is permanently set to 1;
  • at line 610, the pointer path is read out-of-bounds from argv[1];
  • at line 639, the pointer s is written out-of-bounds to argv[1].

But what exactly is read from and written to this out-of-bounds argv[1]?

To answer this question, we must digress briefly. When we execve() a new program, the kernel copies our argument, environment strings, and pointers (argv and envp) to the end of the new program's stack; for example:

|---------+---------+-----+------------|---------+---------+-----+------------| 

| 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 

Clearly, because the argv and envp pointers are contiguous in memory, if argc is 0, then the out-of-bounds argv[1] is actually envp[0], the pointer to our first environment variable, "value". Consequently:

  • At line 610, the path of the program to be executed is read out-of-bounds from argv[1] (i.e. envp[0]), and points to "value";
  • At line 632, this path "value" is passed to g_find_program_in_path() (because "value" does not start with a slash, at line 629);
  • Then, g_find_program_in_path() searches for an executable file named "value" in the directories of our PATH environment variable;
  • If such an executable file is found, its full path is returned to pkexec's main() function (at line 632);
  • Finally, at line 639, this full path is written out-of-bounds to argv[1] (i.e. envp[0]), thus overwriting our first environment variable.

So, stated more precisely:

  • If our PATH environment variable is "PATH=name", and if the directory "name" exists (in the current working directory) and contains an executable file named "value", then a pointer to the string "name/value" is written out-of-bounds to envp[0];

OR

  • If our PATH is "PATH=name=.", and if the directory "name=." exists and contains an executable file named "value", then a pointer to the string "name=./value" is written out-of-bounds to envp[0].

In other words, this out-of-bounds write allows us to re-introduce an "unsecure" environment variable (for example, LD_PRELOAD) into pkexec's environment. These "unsecure" variables are normally removed (by ld.so) from the environment of SUID programs before the main() function is called. We will exploit this powerful primitive in the following section.

Last-minute note: polkit also supports non-Linux operating systems such as Solaris and *BSD, but we have not investigated their exploitability. However, we note that OpenBSD is not exploitable, because its kernel refuses to execve() a program if argc is 0.

Solution: How to Patch the PwnKit Vulnerability

Given the breadth of the attack surface for this vulnerability across both Linux and non-Linux OS, Qualys recommends that users apply patches for this vulnerability immediately.

Current Qualys customers can search the vulnerability knowledgebase for CVE-2021-4034 to identify all the QIDs and assets vulnerable for this vulnerability.

Other interested parties can start a free Qualys VMDR trial to get full access to the QIDs (detections) for CVE-2021-4034, where all vulnerable assets can be identified.

The Qualys Research Team has discovered a memory corruption vulnerability in polkit's pkexec, a SUID-root program that is installed by default on every major Linux distribution. This easily exploited vulnerability allows any unprivileged user to gain full root privileges on a vulnerable host by exploiting this vulnerability in its default configuration.


Fix the PwnKit Vulnerability with a Free Trial of Qualys

Get the Free Trial


About Polkit pkexec for Linux

Qualys QID Coverage

Qualys is releasing the QIDs in the table below as they become available starting with vulnsigs version VULNSIGS-2.5.387-2 and in Linux Cloud Agent manifest version lx_manifest-2.5.387.2-1.

QID Title VulnSigs Version
376287 Polkit pkexec Local Privilege Escalation Vulnerability (PwnKit) VULNSIGS-2.5.387-2 / lx_manifest- VULNSIGS-2.5.387.2-1

Discover Vulnerable Linux Servers Using Qualys VMDR

Identify Assets Running Linux Kernel

The following instructs current Qualys customers on how to detect PwnKit in their environment.

The first step in managing this critical vulnerability and reducing risk is the identification of all assets running Linux OS. Qualys VMDR makes it easy to identify such assets.

Query: operatingSystem.category1:Linux

Once the hosts are identified, they can be grouped together with a ‘dynamic tag’, let’s say: “Linux Servers”. This helps by automatically grouping existing hosts with the above vulnerabilities as well as any new Linux assets that spin up in your environment. Tagging makes these grouped assets available for querying, reporting, and management throughout the Qualys Cloud Platform.

Prioritize Based on RTIs

Using Qualys VMDR, the PwnKit vulnerability can be prioritized using the following real-time threat indicators (RTIs):

  • Predicted_High_Risk
  • Privilege_Escalation
  • Easy_Exploit
  • High_Lateral_Movement

Patch With Qualys VMDR

We expect vendors to release patches for this vulnerability in the short term. Qualys Patch Management can be used to deploy those patches to vulnerable assets, when available.

Using the same prioritization based on the RTI method as described above, customers can use the “patch now” button found to the right of the vulnerability to add PwnKit to a patch job. Once patches are released, Qualys will find the relevant patches for this vulnerability and automatically add those patches to a patch job. This will allow customers to deploy those patches to vulnerable devices, all from Qualys Cloud Platform.

Detect Impacted Assets with Threat Protection

VMDR also enables you to automatically map assets vulnerable to PwnKit vulnerabilities using Threat Protect.

Track Vulnerability with VMDR Dashboard

With VMDR Unified Dashboard, you can track this vulnerability, impacted hosts, status, and overall management in real time. With trending enabled for dashboard widgets, you can keep track of these vulnerability trends in your environment using the “PwnKit” Dashboard.

Download and view the "PwnKit" dashboardDownload

Leverage Qualys XDR Identifying Exploit Attempts

Qualys XDR customers can use the rule name titled – “T1068 – Linux: Polkit pkexec Local Privilege Escalation Vulnerability Detected (CVE-2021-4034)” to detect post-exploitation activity on affected systems. Post enablement, customers can also search for vulnerable systems using the following QQL query:

eventName:” The value for the SHELL variable was not found the /etc/shells file“ or “contains suspicious content“

Customers will be able to see output similar to the following screenshot:

Interested customers can contact Qualys Support for a copy of the XDR rule until it is available in the rule library.

Vendor References

Read the PwnKit security advisory

Frequently Asked Questions (FAQs)

What versions are vulnerable?

All Polkit versions from 2009 onwards are vulnerable.

Will the Qualys Research Team publish exploit code for this vulnerability?

No. But given how easy it is to exploit the vulnerability, we anticipate public exploits to become available within a few days of this blog’s post date.

Are there any mitigations for this vulnerability?

If no patches are available for your operating system, you can remove the SUID-bit from pkexec as a temporary mitigation; for example:

# chmod 0755 /usr/bin/pkexec

Is this vulnerability remotely exploitable?

No. But if an attacker can log in as any unprivileged user, the vulnerability can be quickly exploited to gain root privileges.

Is it possible to check for evidence of exploitation?

Yes, this exploitation technique leaves traces in the logs (either "The value for the SHELL variable was not found the /etc/shells file" or "The value for environment variable […] contains suspicious content"). However, please note that this vulnerability is also exploitable without leaving any traces in the logs.

Why is the vulnerability named “PwnKit”?

This is a pun intended on the name of the vulnerable application Polkit.

7.8 High

CVSS3

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

7.2 High

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:L/AC:L/Au:N/C:C/I:C/A:C