Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2021-4034 — Root exploit for CVE-2021-4034 (PwnKit) that abuses pkexec's out-of-bounds write to escalate privileges to root on Linux systems. | Kitploit
Tools/GitHubGitHub/v-rzh/cve-2021-4034
Privilege EscalationExploit FrameworksVulnerability AnalysisExploitationBinary Exploitation
GitHubv-rzh/cve-2021-4034

CVE-2021-4034

Root exploit for CVE-2021-4034 (PwnKit) that abuses pkexec's out-of-bounds write to escalate privileges to root on Linux systems.

View Repository
114 years agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2021-4034 Exploit

Root exploit for the PwnKit vulnerability. Check out the original report here.

Use this exploit with an express permission of the target system's owners.

Building

No dependencies needed besides libc. Just run make.

Running

Running without options will execute the exploit:

root@kitploit:~
[linux@linux ~]$ ./exploit
-----------------------------------------------------------------------------
 __\ / __   __  _ __           _ __        |    \ / _ ___
/   V |_ --- _)/ \ _)/| ---|_|/ \__)|_|    |     V |_) _/|_|
\__   |__   /__\_//__ |      |\_/__)  |    |       | \/__| |
-----------------------------------------------------------------------------
sh-5.1# whoami
root
sh-5.1#

You can customize the path to pkexec as well as the "from" charset:

root@kitploit:~
[linux@linux ~]$ ./exploit -h
...
./exploit [-c] [-h] [-f from_charset] [-p /path/to/pkexec]
-----------------------------------------------------------------------------
    -c                  Just teardown - don't exploit
    -p <path>           Path to pkexec (default: "/usr/bin/pkexec")
    -f <from_charset>   Custom "from" charset (default: "UTF-8")
    -h                  Display this message

What's the deal with GIO_USE_VFS?!

I saw a few people on social media ask why do some exploits fail if the GIO_USE_VFS= is not defined? Why do they work with the older versions?

The culprit

Commt daf3d5c2d15466a267221fcb099c59c870098e03 in polkit is the culprit. Here's the relevant part of the diff:

root@kitploit:~
--- a/src/programs/pkexec.c
+++ b/src/programs/pkexec.c
@@ -503,6 +503,9 @@ main (int argc, char *argv[])
   opt_user = NULL;
   local_agent_handle = NULL;

+  /* Disable remote file access from GIO. */
+  setenv ("GIO_USE_VFS", "local", 1);
+
   /* check for correct invocation */
   if (geteuid () != 0)
     {

Versions prior to this commit are exploitable without the need to define the GIO_USE_VFS variable. The versions after - are not exploitable unless this variable is defined. The purpose of the commit is actually a red herring. It's not what the variable means, it's how its presence affects the program environment. For the truth we must look to libc.

Looking in libc

The environment of a process in libc is represented by an array of char *s, pointed to by this global variable:

root@kitploit:~
char **environ;

environ lives on the heap and is occasionally relocated. You might already know where this is going. Check out this code snippet from setenv.c:

root@kitploit:~
#if !_LIBC
# define __environ        environ
# ifndef HAVE_ENVIRON_DECL
extern char **environ;
# endif
#endif

int
__add_to_environ (const char *name, const char *value, const char *combined,
                  int replace)
{
  char **ep;

  // ... skipping

  ep = __environ;

  size = 0;
  if (ep != NULL)
    {
      for (; *ep != NULL; ++ep)
        if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
          break;
        else
          ++size;
    }
  if (ep == NULL || __builtin_expect (*ep == NULL, 1))
    {
      char **new_environ;
      /* We allocated this space; we can extend it.  */
      new_environ = (char **) realloc (last_environ,
                                       (size + 2) * sizeof (char *));

  // ... skipping

      last_environ = __environ = new_environ;
    }

__add_to_environ() is called by both setenv(3) and putenv(3) to accomplish what they promise - set an environment variable. If the environment variable in question is not defined, environ has to be reallocated to accomodate a new entry (a pointer to the new environment key=value pair). If it is defined, the size of the environ array has not changed and thus there is no reason for reallocation. For brevity I've omitted that part of the code - I encourage you to check it out.

Tying it all together

Now let's come back to the exploit. If you've gotten this far, you probably already know the methodology behind this exploit (if not please check out the original report). We are trying to sneak in an environment variable by passing an empty program arguments (argv) to pkexec. When argc is truly empty (not even a program name), the environment variables, which are adjacent, clash with the arguments. We abuse this behavior to force pkexec to write a canonical path of a target executable into the environment. However, before we get to this part of the code this happens:

root@kitploit:~
  setenv ("GIO_USE_VFS", "local", 1);

If this variable is not present in the environment environ will be reallocated, thus never clashing with argv. As a result, the out-of-bounds write will not be affecting the program's environment, causing the exploit to fail.

Download Tool