「Tailscale SSH 漏洞 TS-2026-009:一个减号如何绕过 ACL 拿到 root 权限」

「Tailscale SSH 漏洞 TS-2026-009:一个减号如何绕过 ACL 拿到 root 权限」

安全TailscaleSSH漏洞LinuxZero Trust

数据源:HN + Lobsters

2026 年 7 月 14 日,Tailscale 发布了 v1.98.9 版本,一口气修复了六个安全公告,其中编号 TS-2026-009 的漏洞引起了安全社区的广泛关注。这个漏洞的利用方式出奇地简单:任何已被授权 SSH 访问的用户,只需以 -i 作为用户名登录,就能直接获得 root shell,完全绕过 Tailscale ACL 中的 autogroup:nonroot 限制。

Tailscale SSH 漏洞示意图

漏洞的技术本质:参数注入

Tailscale SSH 在验证用户身份时,需要查询 Linux 系统的密码数据库来确认用户是否存在。在受影响的版本中,Tailscale SSH 通过调用外部命令 getent(1) 来完成这一操作,并将用户提交的用户名作为命令行参数传入。

问题的核心在于 POSIX 系统的参数解析约定:以 - 开头的字符串会被当作命令行选项处理。当攻击者以 -i 作为用户名连接时,实际执行的命令变成了 getent --no-idn-i--no-idn 的短选项),这会打印出 /etc/passwd 文件的全部内容,且以 root 用户的条目开头。Tailscale SSH 随后会为返回的第一个用户——也就是 root——开启一个交互式 shell。

一条命令即可完成利用:

ssh -l '-i' 100.x.x.x

不需要额外的工具,不需要构建复杂的提权链条。ACL 规则里写的是「非 root 用户」,Tailscale SSH 却没有强制执行。

相关漏洞 TS-2026-006:UID 0 绕过

与此同时,Tailscale 还修复了另一个编号为 TS-2026-006 的相关问题:使用数字 0(root 的 UID)作为用户名,同样可以绕过基于 UID 的 ACL 限制。两个漏洞都在 v1.98.9 中得到了修复。

根本原因:子进程调用 vs 系统库调用

这个漏洞属于教科书级别的参数注入(argument injection)案例。Tailscale SSH 选择调用外部二进制文件 getent(1),而不是直接使用 POSIX C API getpwnam(3)。两者的区别在于:子进程调用会把参数交给命令行解析器处理,而库函数调用则将输入当作纯粹的数据对待。

Hacker News 上的开发者迅速指出了这一点。有评论写道:「合适的修复方案根本不是去调用外部命令,应该使用 getpwnam(3) 或类似的库函数。」另有评论指出:「通过调用 getent passwd 并自行解析结果,不传入任何用户可控参数,可以彻底消除输入过滤的问题。」还有人更直接地表示:「在安全关键的应用中使用 shell 命令来执行操作,代码和数据混在一起,这种模式本该是长期被否定的反面教材。」

Tailscale 当前的修复方案是拒绝以短横线开头的用户名。这是一个务实的快速修复,但它仍然保留了子进程调用——社区普遍认为,后续版本中应当完全移除对 getent(1) 的依赖,改用系统库函数。

影响范围与修复

这个漏洞仅影响 Linux 节点——getent 是 Linux 特有的工具,macOS 和 Windows 上的 Tailscale SSH 不受影响。此外,利用该漏洞需要已有的 Tailscale SSH 访问权限,外部攻击者无法直接通过网络利用。

Tailscale 官方安全公告指出,受影响的主要是依赖 autogroup:nonroot 进行用户限制的 Linux 主机。这类限制被静默绕过,没有任何可见的告警提示——依赖 ACL 作为硬安全边界的团队可能在不知情的情况下暴露了 root 权限。

v1.98.9 于 2026 年 7 月 14 日发布,同时修复的其他漏洞包括:Unix socket 转发权限问题、Tailscale Serve 和 Funnel 的 CPU 耗尽攻击、以及 Tailscale Services 的入站数据包过滤缺陷。六个安全公告在同一版本中发布,暗示着 Tailscale 进行了一次正式的安全审计,而非偶然逐个修复。

用户可以通过 tailscale version 检查当前版本,并在 Tailscale ACL 策略中检查 SSH 规则配置。

社区反应:信任、范式与争论

Hacker News 上,该话题获得了 115 分和 48 条评论。讨论的核心围绕着几个主题展开。

资深安全研究者 tptacek 的评价颇具黑色幽默:「这是一种古老而经典的安全漏洞类型,至少可以追溯到 AIX 3 时代。很高兴看到他们还在制造这种经典的 bug。」他同时补充了漏洞细节:「如果你在 Tailscale ACL 中有对某台主机的 SSH 访问权限,你可以用 -i 登录并获得 root 登录权限。」

关于 Tailscale SSH 本身的信任模型,社区意见出现了分化。有用户表示:「我是 Tailscale 的重度用户,所以我对他们相当信任,但我从未使用过 Tailscale SSH 功能。我感觉 OpenSSH 的安全记录几乎无懈可击,不明白为什么要在一个对安全如此敏感的工具上做替换。」另一部分用户则持不同观点:「这里的 SSH 漏洞只在攻击者已经在网络中的前提下才适用。它违反了你的 Tailscale ACL,但不是任意的外部 root SSH 访问。可以说,这比在公开可访问的机器上使用普通的 SSH 更安全。」

对于修复方案的质量,社区提出了进一步的质疑。一条高赞评论写道:「Tailscale SSH 现在拒绝以短横线开头的用户名——就这?真正的修复应该是使用 -- 来分隔参数。」对此有人回应:「-- 并非在所有版本的 getent 上都有效。」更深层的批评直指根本:「这是一个仓促的修复,只是为了尽快把补丁推出去。正确处理的方式是直接调用 glibc。」但也有人认为用户名策略是有意义的防御层次:「拒绝无效用户名是一个合理的政策措施,但每次调用外部工具而不清理输入时,你都在朝着某个方向赌一把。」

还有一个讨论焦点是 Anthropic 和 Ada Logics 作为漏洞报告方的身份。有用户推测:「Ada Logics 可能通过 Project Glasswing 获得了 Anthropic 的 Mythos 模型访问权限,并在漏洞研究过程中发现了这个利用方式。」这一细节侧面反映了 AI 辅助安全审计正在渗透到基础设施安全领域。

此外,也有用户对 Tailscale 使用自有编号体系而非申请 CVE 编号提出了疑问。社区中的一种解释是:「这让组织能够更直接地控制披露的时间节奏和叙事方式。组织有时会绕过 CVE 编号机构(CNA)的官僚流程,选择自行发布。通常在社区压力下,CVE 编号会在自行披露之后补充。」

对 Zero Trust 网络工具的启示

TS-2026-009 的意义不仅在于 Tailscale SSH 本身。它触及了一个更广泛的问题:Zero Trust 网络工具正在从单纯的网络层隔离扩展到应用层功能,包括 SSH、HTTP 代理和服务暴露——每一次功能扩展都带来了新的攻击面。

Tailscale 作为 WireGuard 之上的网络层 VPN 隔离工具获得口碑,但其 SSH 功能的底层实现依赖了一个 Go 语言的用户空间 TCP 栈(基于 gVisor 的 netstack)来处理连接。这不是 OpenSSH 那个经过二十五年战场检验的代码库。有 Hacker News 用户尖锐评论道:「Tailscale SSH:用一个创业公司的 Go 重写来替代一个经过二十五年战争检验的代码库,然后对它有 bug 感到惊讶。」

深度防御的原则在这里仍然有效:在高安全需求的节点上,使用 Tailscale 负责网络层 VPN 隔离,同时保留 OpenSSH 负责认证和会话管理。这种分层策略体现了对 Tailscale 设计边界的清醒认知。

关于 Tailscale 正在进行的 Rust 重写工程,也有社区成员指出,这类逻辑错误「即使是用 Rust 重写也无法自动避免」。参数注入是一个逻辑层面的问题,与内存安全无关——编程语言的切换并不能替代安全的 API 设计。

本文的素材来自公开信息和社区讨论。如果你对这个话题有更深入的一手经验,欢迎指出文中的不足。

参考链接

  • Tailscale Security Advisory TS-2026-009
  • byteiota: TS-2026-009: Tailscale SSH Root Bypass, Patch Now
  • Hacker News Discussion: TS-2026-009: Insecure argument handling in Tailscale SSH permitted root access
  • Tailscale SSH Documentation
  • Tailscale v1.98.9 Changelog