2026 年 10 月 25 日,安全研究员 Erica Windisch(Cyberdione Labs)发布了 Tailworm 报告。
报告说的是 Tailscale 内置的 SSH 服务。结论很吓人:一台设备失陷,就能以每台不到 1 秒的速度,把网内其他服务器挨个提权成 root——不需要密码,不需要偷密钥,不需要用户交互。
Tailscale 官方截至发稿没有发布安全公告、没有分配 CVE、没有修复版本。工程副总裁 Mike Shaver 在 Reddit 的回应是:不建议所有用户直接禁用 Tailscale SSH。
我用 Tailscale 管家里的 NAS 和几台服务器。这份报告我逐条读了,也把临时避险清单跑了一遍。这篇把漏洞机制、三条利用链、以及我现在怎么改 ACL 全部拆开。
TL;DR
- Tailscale SSH 的服务器跑在
tailscaled里,这个守护进程是 root 权限;标准 OpenSSH 认证后会降权,它不会- Unix socket 转发(
ssh -L/-R)的路径检查和文件操作都以 root 执行,存在 TOCTOU 竞态- 实测链:替换 root 套接字执行 root 命令、通过 Docker/systemd/管理套接字提权、窃取注册密钥把自有设备接进网络
- 唯一被验证能阻断传播的措施:把 ACL 改成"单源到单目标"配对规则
- headscale 0.29.5 无法关闭端口转发,其 SSH 授权等同于开放 root
- 这不是外部未授权远程访问,前提是"已批准设备 + SSH 规则允许转发"
tailscaled 为什么会变成 root 后门?
先讲清楚一个反直觉的设计差异。
你用标准 OpenSSH 登录服务器时,流程是这样的:
1. sshd 以 root 启动,监听 22 端口
2. 用户认证通过
3. sshd fork 出会话进程,降权到该用户的权限
4. 之后所有操作都在该用户权限下执行
关键在于第 3 步。认证完就降权,所以即使会话被利用,也只能拿到这个用户的权限。
Tailscale SSH 不是这样:
| 环节 | 标准 OpenSSH | Tailscale SSH |
|---|---|---|
| 进程 | sshd(独立) | tailscaled 内嵌 SSH 服务器 |
| 权限 | 认证后降权到用户 | 保持 root |
| 套接字操作 | 用户权限 | root 权限 |
| 路径检查 | 用户权限 | root 权限 |
tailscaled 是 Tailscale 的核心守护进程,它必须以 root 运行(要管理网络接口、路由表、WireGuard 隧道)。问题是——Tailscale 把 SSH 服务器也塞进了这个进程。
结果:SSH 会话里发起的套接字操作,不是"以登录用户身份"执行,而是"以 tailscaled 的 root 身份"执行。
三条利用链:从普通会话到 root
报告里演示了三条链,我按危害程度排。
链一:套接字替换(直接拿 root)
Unix 域套接字(Unix socket)是本地进程间通信的方式。很多系统服务监听在套接字上,比如:
- Docker 的
/var/run/docker.sock - systemd 的私有套接字
- Tailscale 自己的本地管理套接字
正常逻辑:你以普通用户身份连这个套接字,服务会检查你的权限,不够就拒绝。
漏洞逻辑:ssh -L / ssh -R 做套接字转发时,创建、连接、删除套接字的操作是以 root 执行的。于是攻击者可以:
1. 把 root 所有的套接字替换成攻击者控制的套接字
2. 对特定服务直接执行 root 命令
报告里实测:通过 SSH 转发连接 Docker 容器管理服务,成功执行高权限指令并读取受保护的系统文件。
链二:TOCTOU 竞态绕过
TOCTOU = Time-of-Check to Time-of-Use。系统在"检查文件路径"和"实际使用文件"之间有一个时间窗口。
攻击者在这个窗口里动手:
1. 系统检查:这个路径合法吗?→ 合法
2. 攻击者瞬间替换成另一个路径
3. 系统使用:实际操作了被替换的路径
报告里这条链的后果是窃取注册新设备的密钥——拿到密钥后,攻击者可以把自己的设备以"受信任服务器"的身份接入你的网络。
链三:蠕虫式横向移动
把前面两条串起来就是完整攻击链:
1. 初始立足点(Web 漏洞/钓鱼/被盗凭据)→ 控制一台已批准设备
2. 提权 → 用上面的 SSH 问题拿到这台设备的 root
3. 侦察 → Tailscale 给每台设备提供 peer 列表,目标一目了然
4. 横向移动 → 实验室实测每台机器不到 1 秒,无需密码、无需偷密钥
报告把整体影响定义为**“可蠕虫化传播”**:一台失陷设备可以向访问规则允许的所有设备扩散,实现"将普通立足点以机器速度转化为全网特权访问"。
需要说清楚:这些都是实验室环境验证,未在真实网络观测到。但机制是真的。
触发前提:先别恐慌,也别侥幸
这个漏洞不是“外部攻击者可以未授权登录你的服务器”。
Mike Shaver 在 Reddit 明确说了:问题发生在 SSH 连接获得授权之后,不是外部攻击者可以未经授权任意登录。
真实触发前提(三条同时满足):
| 前提 | 说明 |
|---|---|
| 已批准设备失陷 | 攻击者已经控制你 tailnet 里的一台设备 |
| SSH 规则允许访问 | ACL 里该设备的身份/标签能连目标服务器 |
| 端口转发被允许 | SSH 规则授予了转发权限 |
所以:
- 你没开 Tailscale SSH → 不受影响
- 你开了但没开端口转发 → 风险大幅降低(但不是零,链二仍可窃取密钥)
- 你用 headscale 自托管 → 转发无法关闭,SSH 授权等同于开放 root
- 你用普通 OpenSSH 走 Tailscale 网络 → 不受影响(Tailscale 只是隧道)
唯一被验证的阻断措施:ACL 配对规则
这是整份报告里最实用的一条。
宽泛的 ACL 规则(常见写法):
{
"acls": [
{"action": "accept", "src": ["group:admins"], "dst": ["*:*"]}
]
}
这条规则的意思是:admins 组里的任何设备,可以访问所有目标。攻击者控制其中一台,就能横穿全网。
配对规则(报告测试中唯一能阻断传播的写法):
{
"acls": [
{"action": "accept", "src": ["user@laptop"], "dst": ["user@nas:22"]},
{"action": "accept", "src": ["user@desktop"], "dst": ["user@server1:22"]}
]
}
一个源设备,只对应一个目标。攻击者拿下 laptop,最多碰到 NAS,碰不到 server1。
代价:规则数量从 1 条变成 N×M 条。设备多了很难维护,但这是唯一被验证有效的隔离手段。
无补丁阶段的临时避险清单
报告发布时 Tailscale 还没修复。官方建议(来自工程副总裁 + 报告本身):
✅ 梳理 ACL 为单源到单目标配对规则
- 删除按身份/标签授权的宽泛规则
- 这是测试中唯一能阻断传播的控制措施
✅ 尽可能关闭 SSH 端口转发
- 官方托管版可按规则配置
- headscale 0.29.5 无法关闭 → 其 SSH 授权应视为已开放 root
✅ 删除所有指向 Unix 套接字的 tailscale serve 转发规则
✅ 开启节点密钥过期(node key expiry)
- 避免被盗设备密钥永久有效
✅ 失陷设备从控制平面删除
- 仅系统重装无法撤销已被复制的密钥
另外两个配置陷阱(报告 F10/F11):
| 项 | 问题 |
|---|---|
TS_SERVE_ALLOW_ALL_INTERFACES |
设置后 serve 会暴露在隧道之外 |
| serve header auth | 共享上下文冲突,访问权限可能混入其他 mount |
我现在怎么改的:NAS 场景实操
我这边是家用 tailnet:一台 NAS(存所有数据)+ 两台服务器 + 几台笔记本。
改之前的 ACL:
{
"acls": [
{"action": "accept", "src": ["group:family"], "dst": ["*:*"]}
]
}
典型的"图省事"写法。改之后:
{
"acls": [
{"action": "accept", "src": ["user@nas"], "dst": ["user@nas:*"]},
{"action": "accept", "src": ["user@desktop-win"], "dst": ["user@nas:22"]},
{"action": "accept", "src": ["user@desktop-win"], "dst": ["user@server1:22"]},
{"action": "accept", "src": ["user@laptop-macos"], "dst": ["user@nas:22"]}
]
}
同时做了三件事:
1. 关掉所有 SSH 规则的端口转发
2. 删掉所有 tailscale serve 的 Unix socket 转发
3. 开启 node key expiry(默认 180 天 → 我改成 90 天)
成本账:
| 项目 | 改前 | 改后 |
|---|---|---|
| ACL 规则数 | 1 条 | 4 条 |
| 新增设备维护 | 加进 group 即可 | 手动加配对规则 |
| 端口转发 | 全开 | 全关 |
| 节点密钥有效期 | 180 天 | 90 天 |
| 可用性影响 | — | 笔记本连 NAS 要多走一次 tailscale up 确认 |
规则数从 1 涨到 4,代价是每次加设备都要手动写。但 NAS 里是全部家当,这个代价我认。
常见问题
Q1: 我不用 Tailscale SSH,只是用 Tailscale 组网,受影响吗?
A: 不受影响。漏洞在 Tailscale 内置的 SSH 服务里。你用普通 OpenSSH 走 Tailscale 隧道,认证后照样降权,没有这个问题。
Q2: headscale 用户怎么办?
A: headscale 0.29.5 无法关闭端口转发,所以你的 SSH 授权等同于开放 root。临时只能靠 ACL 配对规则 + 节点密钥过期。或者干脆关掉 Tailscale SSH,用普通 OpenSSH。
Q3: 官方为什么不出公告?
A: 截至 10 月 25 日发稿,Tailscale 没有发布安全公告、没有分配 CVE、没有修复版本。工程副总裁 Mike Shaver 在 Reddit 说公司已收到报告、此前已联合外部专家排查、正在确认受影响配置场景。他明确不建议所有用户直接禁用 Tailscale SSH。
Q4: 披露方式有争议吗?
A: 有。Windisch 自称是"已报告但未协同披露"——发布前已向 Tailscale 安全邮箱提交报告副本和 PoC(PoC 未公开)。批评者认为未经协同即公开不负责任;也有研究人员质疑"蠕虫级传播"的描述。但 root 提权问题本身的风险评估是普遍认可的。
Q5: 开启 check mode(SSH 再验证模式)能防住吗?
A: 不能。check mode 能增加一道防护(每次登录需要人工确认),但无法解决权限提升问题。漏洞发生在认证之后的套接字操作阶段。
Q6: 重装失陷设备就能清除风险吗?
A: 不能。如果密钥已被复制,重装系统不会撤销密钥。必须从 Tailscale 控制平面删除该设备节点。
Q7: 这是 11 个漏洞里最严重的吗?
A: 不一定。报告里还有实验性功能 conn25 应用连接器的漏洞,允许向未批准目标(含云元数据服务)发送流量。Windisch 认为它对部分组织的影响可能更大。