在广泛使用的 Guix 系统中发现了一个严重的安全漏洞,尤其影响到 guix-daemon。该漏洞可使本地用户的权限升级,从而在多用户环境中篡改编译输出。
问题的核心在于 guix-daemon 对构建输出的处理,尤其是在构建失败时。根据该公告,“guix-daemon 已在构建容器中的相同位置提供了失败的派生构建输出,这很有帮助”。虽然这一功能在某些情况下非常有用,但它也带来了安全风险。
攻击者可以利用这一机制,启动派生构建,生成具有 setuid 或 setgid 位的二进制文件,从而授予特殊权限。如果构建失败,攻击者就会获得二进制文件的访问权限,然后就可以通过升级权限来执行二进制文件。该公告警告说:”攻击者或合作用户可以执行二进制文件,获得权限,然后使用信号和 procfs 组合冻结生成器,通过 /proc/$PID/fd 打开生成器已打开的任何文件,并随心所欲地覆盖文件。
这一漏洞在多用户系统中尤其危险,因为它允许攻击者操纵任何用户启动的构建程序,有可能对广泛使用的程序产生被破坏的输出结果。公告指出,该漏洞也会影响成功的构建,在权限、所有权和时间戳尚未规范化的情况下,会引入一个小的机会窗口。这使得该漏洞更加令人担忧。
为帮助用户确定其系统是否存在漏洞,我们提供了一个概念验证脚本。
(use-modules (guix)
(srfi srfi-34))
(define maybe-setuid-file
;; Attempt to create a setuid file in the store, with one of the build
;; users as its owner.
(computed-file "maybe-setuid-file"
#~(begin
(call-with-output-file #$output (const #t))
(chmod #$output #o6000)
;; Failing causes guix-daemon to copy the output from
;; its temporary location back to the store.
(exit 1))))
(with-store store
(let* ((drv (run-with-store store
(lower-object maybe-setuid-file)))
(out (derivation->output-path drv)))
(guard (c (#t
(if (zero? (logand #o6000 (stat:perms (stat out))))
(format #t "~a is not setuid: your system is not \
vulnerable.~%"
out)
(format #t "~a is setuid: YOUR SYSTEM IS VULNERABLE.
Run 'guix gc' to remove that file and upgrade.~%"
out))))
(build-things store (list (derivation-file-name drv))))))
运行
guix repl -- setuid-exposure-vuln-check.scm
guix repl — setuid-exposure-vuln-check.scm
该脚本会告知用户其 guix-daemon 是否存在漏洞,因此对系统管理员和用户来说都是至关重要的工具。
为缓解这一漏洞,我们引入了两个重要的修复程序:
- 清理失败构建的权限: 现在会对失败的编译输出进行消毒,以确保在将任何 setuid/setgid 位移至存储区之前将其删除。这可防止攻击者访问不受信任的二进制文件。
- 对成功构建的权限进行规范化: 只有在权限完全规范化后,成功的构建输出才会被移至存储区,从而进一步降低了攻击面。
这些修复是近期提交的一部分,建议用户将其 guix-daemon 升级到这些版本。此外,运行 guix gc 将有助于清理可能仍然存在的失败构建输出。
Guix 项目强烈建议所有用户立即升级 guix-daemon。升级程序因使用 Guix 的方式而异,但对大多数用户来说,升级过程简单明了。Guix 系统用户可使用以下命令进行升级:
guix pull
sudo guix system reconfigure /run/current-system/configuration.scm
sudo herd restart guix-daemon
对于在其他发行版上使用 Guix 作为软件包管理器的用户,升级过程包括提取最新更改并重启 guix-daemon 服务:
sudo --login guix pull
sudo systemctl restart guix-daemon.service
该公告还提到了确保守护进程套接字仅限受信任用户使用的重要性,尤其是那些使用 -disable-chroot 的用户。