目录

1) 引言

Tuned是一个用于Linux的特权守护进程,支持在运行时自动调整各种硬件和内核设置。该守护进程提供了一个受Polkit认证保护的全面D-Bus接口。我们会定期审查新引入的D-Bus系统服务及其更改。Tuned的D-Bus接口经常有新增功能,这是我们自2019年以来进行的第十次审查。通常审查都比较直接,我们也没有什么抱怨,但这次是个例外。

在审查过程中,我们检查了匹配以下Polkit操作的D-Bus方法

com.redhat.tuned.instance_create        (auth_admin:auth_admin:yes)
com.redhat.tuned.instance_destroy       (auth_admin:auth_admin:yes)
net.hadess.PowerProfiles.HoldProfile    (no:no:yes)
net.hadess.PowerProfiles.ReleaseProfile (no:no:yes)

本报告基于tuned版本v2.24.0。

2) D-Bus方法instance_create中的问题

调用instance_create() D-Bus方法允许本地登录用户在无身份验证的情况下调用(Polkit设置为yes)。该方法调用接受包括options字典在内的各种参数,这些参数完全由攻击者控制。

2a) 脚本选项允许本地root漏洞 (CVE-2024-52336)

script_prescript_post选项允许传递任意脚本,这些脚本将由*root*执行。参数在daemon/controller.py:459处提取,未修改地存储在新的Instance对象中,并且仅在plugins/base.py:222中执行脚本路径的唯一验证。

    if not script.startswith("/"):
        log.error("Relative paths cannot be used in script_pre or script_post. " \
                + "Use ${i:PROFILE_DIR}.")
        return False

因此,唯一的要求是传递一个绝对路径。这样,非特权用户控制下的脚本就可以被传递。这使得本地root漏洞成为可能。

重现步骤

以本地登录的非特权用户身份执行以下D-Bus调用

    $ gdbus call -y -d com.redhat.tuned -o /Tuned \
        -m com.redhat.tuned.control.instance_create cpu myinstance \
        '{"script_pre": "/path/to/myscript.sh", "devices": "*"}'

路径/path/to/myscript.sh需要替换为用户控制的可执行脚本或程序的路径。它将由tuned以root权限执行。

2b) 实例名称可以包含任意数据 (CVE-2024-52337)

instance_create()方法的instance_name参数未被净化。此字符串稍后用于日志记录以及tuned-adm get_instances等实用程序的输出,或使用tuned的D-Bus接口获取实例名称的其他第三方程序。

本地攻击者可以在实例名称中包含任意数据,从而实现日志伪造。通过在名称中放置换行符,可以向tuned日志添加看似独立、合法的条目。通过添加终端控制序列,可以影响管理员或其他用户的终端模拟器。以下是此漏洞的概念验证:

    $ EVIL=`echo -e "this is\nevil\033[?1047h"`
    $ gdbus call -y -d com.redhat.tuned -o /Tuned -m com.redhat.tuned.control.instance_create cpu "$EVIL" '{"devices": "*"}'

当另一个用户调用tuned-adm get_instances时,终端模拟器在输出经过精心制作的实例名称时会切换到备用屏幕。

受影响情况

instance_create() D-Bus方法已通过上游提交cddcd233添加,并首次包含在v2.23.0版本标签中。初始版本已经支持脚本选项参数和instance_name参数。

3) PowerProfiles接口中的问题

新的D-Bus方法HoldProfile()ReleaseProfile()使用一个cookie来标识配置的保持。cookie只是一个从零开始连续递增的整数。这意味着系统中的其他用户可以轻松释放其他用户的配置保持。

3b) 用户提供的字符串可能包含任意数据

HoldProfile()调用接受reasonapp_id字符串,这些字符串用于日志记录,并可能通过ProfileHold.as_dict()作为字典返回。这些字符串可能再次包含精心制作的数据,这些数据可能产生与第2b节所示类似的副作用。

建议的修复方案

使用cookie的本地DoS场景仅在多用户系统上,或者当Polkit设置放宽,使得非本地会话也能使用这些D-Bus方法时才是一个问题。一种使其更健壮的方法可能是发出随机的cookie ID,以使攻击不那么容易。

4) Bug修复

上游发布了版本v2.24.1,解决了本报告中描述的问题。提交90c24eea037包含累积修复,如下所示:

  • 插件现在只从受信任的位置加载(_safe_script_path()函数)。
  • 如果用户提供的字符串包含不允许的字符,则会拒绝这些字符串(is_valid_name()函数)。
  • 上游还收紧了instance_create及其他一些他们也认为存在问题的、由本地非特权用户访问的操作的tuned Polkit策略。

对于问题3a),目前没有上游修复。这更多的是一个加固建议。

5) 时间线

2024-11-07 我们已将这些问题报告给Red Hat安全团队。
2024-11-08 Red Hat安全团队确认了这些问题,并向我们传达了CVE分配情况,并建议发布日期为2024年11月26日。
2024-11-11 Red Hat分享了建议的补丁,我们对其进行了审查。
2024-11-26 发布日期已到,并按计划进行了发布。

6) 参考资料