M8seven/cve-2026-11837-ansible-posix-authorized-key

GitHub: M8seven/cve-2026-11837-ansible-posix-authorized-key

该项目是 Ansible `ansible.posix.authorized_key` 模块中因符号链接跟随导致本地提权漏洞(CVE-2026-11837)的技术分析报告与复现参考。

Stars: 1 | Forks: 0

# CVE-2026-11837:ansible.posix `authorized_key` 本地提权 在 Ansible 的 `ansible.posix.authorized_key` 模块中,由于对用户的 `~/.ssh` 目录和 `authorized_keys` 文件执行了跟随符号链接的 `chown`(以及跟随符号链接的文件创建操作),导致了本地权限提升。 这是我报告的一个漏洞的技术记录,该漏洞被 Red Hat Product Security(CNA)分配了 **CVE-2026-11837**。在此发布仅作为技术记录,并非主张其新颖性:该问题是先前修复未覆盖的模块中 [CVE-2024-9902](https://access.redhat.com/security/cve/CVE-2024-9902) 的**同级漏洞**。 ## 官方参考 - Red Hat CVE 记录:https://access.redhat.com/security/cve/CVE-2026-11837 - Red Hat Bugzilla 缺陷:https://bugzilla.redhat.com/show_bug.cgi?id=2487424 - 受影响模块源码:https://github.com/ansible-collections/ansible.posix/blob/main/plugins/modules/authorized_key.py | | | |---|---| | **CVE** | CVE-2026-11837 | | **组件** | `ansible.posix` 集合,文件 `plugins/modules/authorized_key.py`,函数 `keyfile()` | | **类型** | 权限提升(本地)。CWE-59 / CWE-61(链接跟随)以及 CWE-282(不当的权限管理) | | **CVSS** | 7.3(高危) | | **公开** | 2026-06-10 | | **报告者** | Valentino Paulon | ## 概述 当以 root 用户运行的 playbook 使用 `ansible.posix.authorized_key` 来管理本地用户的密钥时,该模块的 `keyfile()` 辅助函数会: - 使用普通的 `os.chown`(而非 `os.lchown`)更改用户 `~/.ssh` 目录以及 `~/.ssh/authorized_keys` 的所有权,并且 - 使用普通的 `open(..., "w")`(未使用 `O_NOFOLLOW`)创建密钥文件。 在默认的 `follow=False` 设置下,该模块既不会跟随并替换符号链接,也不会拒绝符号链接;它直接在路径上操作,因此内核会跟随非特权目标用户预先在其自己的 `~/.ssh` 中放置的任何符号链接。这产生了两种攻击方式,能将 root 控制的路径所有权转移给非特权用户,随后该用户即可提权至 root。这两种方式均已在仓库的最新版本(HEAD)上完成端到端复现。 ## 受影响的代码与根本原因 `keyfile()`(位于 `plugins/modules/authorized_key.py`),采用默认设置 `manage_dir=True`,`follow=False`: ``` if manage_dir: if not os.path.exists(sshdir): # os.path.exists FOLLOWS symlinks try: os.mkdir(sshdir, int('0700', 8)) ... os.chown(sshdir, uid, gid) # UNCONDITIONAL, plain chown, follows symlink os.chmod(sshdir, int('0700', 8)) # follows symlink if not os.path.exists(keysfile): # follows symlink ... f = open(keysfile, "w") # plain open(), no O_NOFOLLOW, follows symlink ... try: os.chown(keysfile, uid, gid) # UNCONDITIONAL, plain chown, follows symlink os.chmod(keysfile, int('0600', 8)) # follows symlink except OSError: pass ``` `sshdir` 和 `keysfile` 派生自目标用户的 passwd 主目录(`pwd.getpwnam(user).pw_dir`),这是一个由非特权目标用户拥有并控制的目录。`follow` 参数(默认为 `False`)仅选择是否对路径调用 `os.path.realpath()`;在这两种情况下,都没有 `os.path.islink` 检查、`O_NOFOLLOW` 打开操作、`os.lchown`,也没有对已存在的符号链接执行取消链接并替换的操作。没有进行任何权限降级(`seteuid`/`setfsuid`);一切都以 root 身份运行。 这两个 `os.chown` 调用是**无条件**运行的,位于 `if not os.path.exists(...)` 保护条件之外,因此无论目录/文件是否已经存在,它们都会触发。这正是使得这两种攻击方式都能稳定成功的原因。 ## 两种攻击方式 两者均在一次性 Linux 虚拟机上使用最新版本(HEAD)的 `ansible.posix` 完成了端到端确认。`victim` 是一个非特权本地用户(uid 1000)。该模块以 root 身份运行,与操作员的 playbook 运行方式完全一致。金丝雀文件代替了敏感的 root 目标。 **攻击途径 1:目录符号链接(对已存在的 root 所属目录执行 chown)** 1. 以 `victim` 身份:`ln -s /root/AD_CANARY ~/.ssh`(其中 `/root/AD_CANARY` 是一个已存在的 root 所属目录)。 2. 操作员为 `victim` 运行 `authorized_key` 任务。 3. 观察结果:`/root/AD_CANARY` 的所有权由 `root:root` 变更为 `victim:victim`。`os.chown(sshdir, ...)` 调用跟随了 `~/.ssh` 符号链接,并将一个 root 所属的目录交给了非特权用户。 **攻击途径 2:悬空文件符号链接(创建并对新的 root 路径文件执行 chown)** 1. 以 `victim` 身份(此时 `~/.ssh` 是一个普通目录):`ln -s /root/AF_CANARY ~/.ssh/authorized_keys`(目标不存在)。 2. 操作员为 `victim` 运行 `authorized_key` 任务。 3. 观察结果:`/root/AF_CANARY` 被创建,所有者为 `victim:victim`,模式为 0600。`open(keysfile, "w")` 通过符号链接创建了目标,随后 `os.chown(keysfile, ...)` 将其所有权移交。 在这两种情况下,非特权用户最终都成为了某个 root 控制路径的所有者。将链接指向 `/etc` 下的目录(攻击途径 1),或者指向 `/etc/cron.d/` 或 `/etc/sudoers.d/` 下的新文件(攻击途径 2),即可通过标准的后续利用获取 root 权限,此时已成为所有者的用户可以重写目标内容。 ## 与 CVE-2024-9902 的关系 这是 [CVE-2024-9902](https://access.redhat.com/security/cve/CVE-2024-9902)(位于 ansible-core 中 `user` 模块的 `generate_ssh_key`)的同级漏洞,后者已经处理了同一类跟随符号链接的问题。`authorized_key` 位于独立的 `ansible.posix` 集合中,并未被先前的修复所更改;跟随符号链接的 `chown`/创建模式依然存在且未受保护。该漏洞被作为先前修复未触及的模块中已被接受的同类问题报告,而非作为一个全新的根本原因。 ## 影响与客观前提条件 - 在由 Ansible 管理的主机上,非特权本地用户可提权至 root。 - 取决于操作员是否运行了针对受害者账户的 `ansible.posix.authorized_key` 任务(这也是该模块的常见用法)。本地用户只需在其自己的 `~/.ssh` 中预先布置好符号链接;他们不需要运行 playbook。这属于由操作员触发的行为:与 CVE-2024-9902 的触发模型相同,Red Hat 对此接受的缓解措施是“不要针对不受信任的账户运行”。此前提条件已被明确指出,而不是被评定为自行触发。 ## 修复建议 - 创建密钥文件时不跟随符号链接且具有排他性:使用 `os.open(keysfile, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600)` 并对文件描述符进行操作;如果 `sshdir` 或 `keysfile` 是符号链接,则拒绝操作(或根据 `follow=False` 文档字符串约定的协议执行取消链接并替换)。 - 将 `os.chown(...)` 替换为 `os.lchown`,或者对安全打开的描述符使用 `os.fchown`,同样地,使用 `os.fchmod` 代替 `os.chmod`,这样所有权和权限就不会通过链接被转移。 - 对无条件的 `chown`/`chmod` 进行条件限制,使其仅应用于模块自身刚刚安全创建的路径上,而不是可能预先存在的(可能是符号链接的)路径上。 ## 披露时间线 | 日期 | 事件 | |------|-------| | 2026-06-08 | 报告至 `security@ansible.com`(并抄送 CNA:Red Hat Product Security),将其界定为 CVE-2024-9902 的同级漏洞 | | 2026-06-10 | 分配并发布 CVE-2026-11837;接受致谢 | ## 许可证 MIT。详见 [LICENSE](LICENSE)。
标签:Ansible, CSV导出, 本地提权, 权限管理, 模型越狱, 漏洞分析, 符号链接漏洞, 系统提示词, 路径探测, 逆向工具