1)简介
我们收到了针对 Deepin 桌面环境的一部分 Deepin api-proxy D-Bus 服务的审核请求。在审核过程中,我们发现此 D-Bus 服务的设计中存在一个重大身份验证缺陷,允许本地用户以各种方式提升权限。
我们在 12 月私下向 Deepin 安全部门报告了这个问题,但一个月都没有收到回复。就在我们准备发布时,上游活跃起来并迅速发布了一个错误修复程序,但遗憾的是,它仍然不完整。
本报告基于dde-api-proxy 版本 1.0.17。这些发现仍然适用于版本 1.0.18。上游已尝试在版本 1.0.19 中修复这些发现,但如第 6 节所述,错误修复尚不充分。
2)身份验证绕过问题
Dde-api-proxyroot以 D-Bus 系统总线的形式运行并提供各种 D-Bus 服务。它之所以引人注目,是因为它附带了大量 D-Bus 配置文件,但代码却很少。原因是该服务仅在其客户端和实际的 Deepin D-Bus 服务之间转发 D-Bus 请求。我们认为这是为了向后兼容,因为 Deepin D-Bus 接口名称发生了变化,可惜该组件的 GitHub 存储库对其用途知之甚少。
在启动期间,代理服务会主动注册所请求的旧版 D-Bus 接口并创建与实际 Deepin D-Bus 服务的连接,消息将被转发到该服务。当客户端向某个旧版服务名称发送消息时,代理会handleMessage()通过其现有连接同步转发该消息(参见),并将回复返回给客户端。
然而,这种代理 D-Bus 消息的相当简单的方法存在一个重大的安全漏洞:
-
代理作为 运行root。
-
代理将来自任意本地用户的消息转发到实际的 D-Bus 服务,无需任何身份验证要求。
-
实际的D-Bus服务并不知道代理的情况,他们认为这root是在要求他们执行操作。
因此,在 dde-api-proxy 的帮助下,非 root 用户通常无法访问的旧式 D-Bus 方法将无需身份验证即可访问。
3)复制者
不使用 Polkit 的 D-Bus 方法
以下是基于 Deepin Grub2 服务对该问题的简单演示。该服务仅检查 D-Bus 客户端的 UID 以验证特权操作。在下面显示的第一个命令中使用了实际的 D-Bus 服务名称,并且该服务拒绝该操作,因为调用者没有特权:
user$ gdbus call -y -d org.deepin.dde.Grub2
-o /org/deepin/dde/Grub2 -m org.deepin.dde.Grub2.SetTimeout 100
Error: GDBus.Error:org.deepin.dde.DBus.Error.Unnamed: not allow :1.167 call this method
在下一个命令中,使用了旧的 D-Bus 服务名称,这次目标服务执行操作,因为它认为请求来自特权 UID 0 客户端(dde-api-proxy):
user$ gdbus call -y -d com.deepin.daemon.Grub2
-o /com/deepin/daemon/Grub2 -m com.deepin.daemon.Grub2.SetTimeout 10
()
使用 Polkit 的 D-Bus 方法
在上一个示例中,Polkit 身份验证并未涉及。当涉及身份验证时,调用者将被视为“管理员”,从而导致类似的权限提升。我们在 Deepin 帐户服务中找到了一个使用 Polkit 的合适示例。此服务提供大量系统操作,其中包括将用户添加到组的可能性。它检查“org.deepin.dde.accounts.user-administration”Polkit 操作的授权,默认情况下,只有提供管理员凭据的用户才能在本地会话中执行此操作。
以下gdbus调用尝试将 UID 为 1000 的非特权用户添加到root组中。此调用仅在 (Deepin) 图形会话中运行时才有效。实际的帐户服务接口在此处调用,因此操作失败(需要输入 root 密码)。
user$ gdbus call -y -d org.deepin.dde.Accounts1 -o /org/deepin/dde/Accounts1/User1000
-m org.deepin.dde.Accounts1.User.AddGroup root
Error: GDBus.Error:org.deepin.dde.DBus.Error.Unnamed: Policykit authentication failed
当切换到 dde-api-proxy 提供的传统帐户服务接口时,操作成功而无需任何身份验证请求,因为帐户服务再次认为 UID 为 0 的 root 是提出此请求的客户端:
user$ gdbus call -y -d com.deepin.daemon.Accounts -o /com/deepin/daemon/Accounts/User1000
-m com.deepin.daemon.Accounts.User.AddGroup root
()
4)受影响的 D-Bus 接口
我们没有研究通过 dde-api-proxy 提供给未经身份验证的本地用户的所有特权 D-Bus 方法。在某些代理接口上,只允许调用一组特定的“过滤方法”。不过,其余接口对调用的方法没有限制。乍一看,dde-api-proxy 提供的以下 D-Bus 接口似乎存在有趣的攻击面:
-
账户服务(无方法过滤列表)
-
网络代理设置(无方法过滤列表)
-
PasswdConf1 WriteConfig 方法
-
Lastore 服务(Apt 后端,无方法过滤列表)
-
Lastore manager安装包方法
5) 建议的错误修复
身份验证绕过深深植根于 dde-api-proxy 的设计中,因此修复起来很困难。以下小节将介绍解决该问题的可能方法。
a) 放弃特权
代理可以暂时放弃无特权调用者凭证的权限,创建新的 D-Bus 连接并将消息转发给正确的服务。如果相关 D-Bus 服务使用 Polkit 进行身份验证,这仍然无法正常工作,因为 Polkit 会区分调用者是否处于活动会话中。但是,D-Bus 代理服务永远不会处于会话中。这意味着身份验证要求可能比必要的更严格。至少这种方法比目前的做法更安全。
b) 重新实现身份验证检查
代理可以自行实现所有必要的身份验证检查。这样可以执行正确的身份验证,但会导致大量代码重复。这还增加了代理服务和实际服务的身份验证要求不同步的危险。
c) 在受影响的服务中实现旧接口
最后,dde-api-proxy 可以完全放弃,并可以在每个受影响的服务中实现向后兼容性。当然,这是一种比 dde-api-proxy 试图实现的方法更不通用的方法。
6) 上游错误修复
在一段较长的沉默期之后,上游意外地回复了我们的报告,并建立了一个短暂的禁令期,直到 1 月 17 日发布了错误修复。该错误修复位于上游提交 95b50dd中,该提交已进入版本 1.0.19。
对于错误修复,上游按照我们在第 5.b) 节中提出的建议进行,在代理服务中实施冗余的 Polkit 授权检查。代理提供的敏感 D-Bus 方法列表现在在源代码中维护。所有这些方法都受到单个新引入的 Polkit 操作“org.deepin.dde.api.proxy”的保护,该操作需要管理员身份验证。
不过,该错误修复引入了一个新问题。Polkit 授权检查实现如下:
bool checkAuthorization(const QString &actionId, const QString &service,const QDBusConnection &connection) const
{
auto pid = connection.interface()->servicePid(service).value();
auto authority = PolkitQt1::Authority::instance();
auto result = authority->checkAuthorizationSync(actionId,
PolkitQt1::UnixProcessSubject(pid),
PolkitQt1::Authority::AllowUserInteraction);
/* snip */
}
此代码将客户端的进程 ID (PID) 转发给 Polkit 服务进行身份验证。这种使用 Polkit UnixProcessSubject 的方式已被弃用很长时间,因为它容易受到竞争条件的影响,从而允许绕过此类授权检查。此问题 由前 SUSE 安全工程师 Sebastian Krahmer 于 2013 年发现,并被分配了 CVE-2013-4288。
上游在发布之前没有与我们分享错误修复,因此我们无法阻止此不完整的错误修复。应该可以通过切换到 SystemBusName 主题进行身份验证来修复不完整的错误修复。
即使修复有所改进,我们认为这种方法并不理想,因为它需要上游对所有代理方法进行适当维护。如果稍后添加新方法,安全问题可能会再次出现。此外,新引入的 Polkit 操作使代理服务变得不那么透明,可能会影响用户体验。对单个 D-Bus 方法的身份验证要求没有更细粒度的控制,所有这些代理 D-Bus 方法的身份验证消息都是通用的,对最终用户没有帮助。
7)可能的解决方法
除了从系统中删除 dde-api-proxy 之外,我们没有发现任何可行的方法来解决此问题。
8)CVE 分配
此发现是 dde-api-proxy 中的一个更大的设计问题,它允许本地 root(组)攻击和可能更多类似的攻击媒介。我们决定向 Mitre 请求 CVE,让社区意识到这个问题。Mitre 分配了 CVE-2025-23222 来跟踪此问题。
正式来说,需要为第 6 节中描述的不完整的错误修复所引入的新安全问题分配另一个 CVE,但我们目前还没有这样做。
9)时间轴
2024-12-18 | 我们通过电子邮件向 [email protected] 报告了该问题,该项目的联系页面上有记录。该电子邮件被邮件服务器拒绝。 |
2024-12-18 | 我们联系了 [email protected],询问报告 Deepin 安全问题的正确方法是什么。我们很快得到了回复,他们建议我们访问他们的(公共)错误跟踪器或 [email protected]。 |
2024-12-19 | 我们通过电子邮件向 [email protected] 报告了该问题,并提供协调披露。这次电子邮件没有被拒绝。 |
2025-01-07 | 由于我们尚未收到 Deepin 安全部门的回复,因此我们再次发送了一封电子邮件,要求在 2025-01-12 之前给予初步回复,否则我们将发布该信息。 |
2025-01-13 | 由于我们仍未收到回复,我们开始着手发布完整报告。我们向 Mitre 请求了 CVE。 |
2025-01-14 | Mitre 已分配 CVE-2025-23222。 |
2025-01-16 | 上游联系人意外回复并确认了该问题,并表示他们正在修复错误。我们再次询问是否需要协调披露,并转发了分配的 CVE。 |
2025-01-17 | 上游回复称,他们希望维持禁运至 2025-01-20。 |
2025-01-23 | 由于发布日期上游没有看到任何活动,并且我们没有收到通知,因此我们询问上游发布是否会按计划进行。 |
2025-01-24 | 上游向我们指出了错误修复,该修复已于 2025-01-17 发布,且未再有任何消息。 |
2025-01-24 | 由于错误修复已发布,我们决定发布所有信息。在审查错误修复时,我们意识到它不完整,并通过电子邮件通知上游。 |
原文始发于微信公众号(Ots安全):dde-api-proxy:Deepin D-Bus 代理服务中的身份验证绕过(CVE-2025-23222)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论