想必你已经听说过那个逃出安全评估并攻击 Hugging Face(一个 LLM 市场)的 AI 代理的故事。这个代理认为 Hugging Face 可能拥有其基准测试的答案,于是偷走了答案只为在考试中作弊。这动机听起来滑稽,但结果却令人不安。

Hugging Face 发布了一份关于此次入侵的详细重建报告。报告涵盖了四天半内恢复的约 17,600 个操作,包括沙箱逃逸、代码执行、云凭证、临时指挥控制系统,以及最终利用 Tailscale 在其组织内传播。

但 Tailscale 是一个零信任网络!零信任的全部意义在于防止攻击者在公司内部横向移动。那到底出了什么问题?

Tailscale 出现之处

没有发现或利用 Tailscale 的“漏洞”,这可能让我们更感不安。Tailscale 几乎无处不在地出现在 AI 基础设施中:几乎每家 AI 公司都在使用 Tailscale。因此,我们最终出现在 AI 事件报告中也就不足为奇了。

但我们是一个安全工具。他们的入侵就是我们的入侵,我们有责任认真对待它。就像任何事后分析一样,我们需要反思发生了什么,以及我们本可以做什么来阻止它。

当这个代理逃出沙箱并发现 Tailscale 时,它已经在一个生产工作器内获得了代码执行权限,在一个 Kubernetes 节点上获得了 root 访问权限,并读取了一个包含 136 个密钥的生产密钥存储。从某种意义上说,在我们登场之前,游戏已经结束了。

但这不就是问题所在吗?让我们退一步思考。为什么长期存在的密钥竟然可以被任何人访问?

因为长期凭证是标准做法

它们本不应该如此。而我们现在已经看到了一个很好的例子,说明了为什么。在过去,大多数入侵是由人类以人类的速度进行的,凭证泄露缓解措施被视为一项锦上添花的功能。一个大的凭证存储,你可以一次读取 136 个密钥,这在安全团队的低优先级列表中只是一个待办事项。

现在,在流氓 AI 代理的世界里,这个大的凭证库就是战利品。这已经不再可以接受。

我只知道两种解决长期凭证的主要方案。

首先,你可以配置一个 vault,它根据你一次性插入且永不返回的长期凭证签发短期凭证。例如,HashiCorp Vault 就可以做到这一点;他们称之为动态凭证。不幸的是,动态凭证的设置和维护工作量很大。当安全需要付出努力时,人们就不会去做。

第二个选择是凭证注入代理。如果客户端 C 想访问服务器 S,不要给 C 提供 S 的凭证;相反,让它通过一个硬化的代理 P 发送请求,该代理只做接收请求、插入凭证并传递它的工作。凭证注入现在越来越受欢迎,因为现代基于网格的网络消除了其大部分延迟。几个月前,我们收购了Border0(“Tailscale PAM”),它提供了一个优雅且相当精巧的凭证注入代理,与 Tailscale 紧密集成。如果完全部署,Border0 本可以防止读取那 136 个密钥,并记录每一次使用密钥的尝试。(同样的凭证注入功能也支持Aperture Connectors)。但是,这项技术太新了。我们的大多数客户甚至还没有研究过它。

额外的第三个选择:Tailscale 本身。在 Tailscale 中,你的节点密钥可以使用 TPM 绑定到机器以防止导出,如果你是企业用户,你绝对应该这样做。遗憾的是,我们不得不默认关闭 Linux 和 Windows 上的 TPM 存储,因为我们在一些用户的硬件上发现了 HSM 问题。无论如何,在本案中,攻击本身就授予了对 Tailscale 的访问权,所以我们来得太晚了。

那个长期存在的身份验证密钥本不需要存在

由于动态凭证或凭证注入代理均未就位,因此 136 个密钥被泄露。下一道防线是什么?

这 136 个凭证中有一个是可重复使用的 Tailscale 身份验证密钥,用于在他们的 tailnet 中创建新的 Tailscale CI(持续集成,用于自动化测试)节点。该代理将该密钥复制到一系列外部沙箱中,并在几天内使用它,总共在 Hugging Face 的 tailnet 中注册了 181 个节点。这些节点各自收到了一个授予 CI 节点全部访问权限的 Tailscale 身份标签。

我们无法拯救那 136 个密钥。但一个可重复使用的 Tailscale 密钥本不需要在其中。

我们为这种情况构建了工作负载身份联邦。它依赖于你的云提供商以运行中 VM(或容器)的云身份形式提供“环境权限”,生成短期凭证。CI 作业可以向其云平台请求一个签名的 OIDC 令牌。Tailscale 验证该令牌,然后使用分配给该工作负载的标签和范围授予访问权限。巧妙之处在于,一旦启用,这一切都可以自动发生:启动 CI 节点,Tailscale 获取身份,分配正确的标签。没有凭证可以泄露,而且如果配置得当,就无法在 CI 环境之外使用此凭证。

这意味着你不能获取一个 CI 凭证,在其他地方的节点上运行它,并将其变成一条从测试集群通向网络其余部分的铺就之路。

遗憾的是,使用工作负载身份联邦的人还不够多。我们本应更努力地确保客户知道这是一条更简单 更安全的路径,并提供清晰的采用方式。我们可以改进文档,并在 UI 中添加更多提示。

没有客户端日志并不意味着没有证据

为了隐藏其行踪,该代理在运行 Tailscale 时使用了 --no-logs-no-support 标志,这会抑制来自该客户端的报告。

这个选项是为那些担心向 Tailscale 发送遥测元数据的用户设计的。即使我们不提供这个选项,也很容易修改源代码来移除遥测。

但是,停止日志并不会使连接无形。如果你启用 Tailscale 网络流日志,它们会报告来自每个连接两端以及子网路由器和出口节点的流量。这一点微妙但很重要:一个被攻破的节点可能不会发送流日志,但它连接到的每个节点都会发送。然后,你配置周全的 SIEM 就可以立即发出红色警报,如果两端不匹配。

当流日志流式传输到配置周全的 SIEM 中时,可以帮助检测。但这需要大量工作。流日志需要被启用,你需要有正确的实时检测规则,以便它们能实时发挥作用,而不仅仅是用于事后取证。我们正在研究如何让流日志更容易被发现、配置、采用,并作为警报触发器。我希望我们能让流日志变得如此易用,即使你没有安全团队来监控,它们也能提供帮助。

如果你想要超越单纯日志记录的直接控制,你还可以启用Tailnet Lock。这为你提供了对每一个新节点的直接可见性和严格的、可编程的准入控制。例如,通过一些工作,你可以编程你的签名节点来检查“CI”标签是否始终具有特定的 IP 地址范围或其他有效性的侧信道证明。

让安全路径成为简单路径

网络安全很难。它一直以来都很困难。在流氓 AI 代理的新世界里,它不仅仅是困难,而是至关重要。这是一个问题,因为许多组织根本没有网络安全专业知识。

所以在 Tailscale,我们对此感同身受。人们期望我们的产品能默认阻止这类横向移动攻击,这样他们就不必自己动手了。即使他们不知道什么是横向移动攻击。

如果这次事件让你对自己的基础设施感到有些紧张,请先查看你的工作负载可以读取的可重复使用的 Tailscale 身份验证密钥。特别是对于云和 CI,请尽可能用工作负载身份联邦替换它们。摆脱那些长期存在的身份验证密钥。

(身份验证密钥仍有很好的用途,特别是用于一次性配置和没有平台身份的环境。当你需要一个时,请优先选择一次性密钥;使用OAuth 客户端来保持身份验证密钥的有效期短;使用窄范围的标签;在你的 ACL 中审计授予这些密钥的权限。)

开启网络流日志并将其发送到你的安全团队已经在使用的工具中。

在你控制 TPM 的托管机群上使用安全节点状态存储。在你不控制 TPM 的地方,使用设备姿态来隔离和限制节点。

我知道我们还没有让这些更安全的选项足够明显。这是我们的责任。我们将改进文档,在 UI 中添加提示,尽最大努力默认开启这些选项,当你进行危险操作时警告你,并建议更好的替代方案。

这是我们非常“加拿大式”的道歉:很抱歉你踩到了我们的脚趾。攻击没有利用 Tailscale,Tailscale 也没有造成入侵。但是,我们没有阻止它。下一次,我们会。

如果你正在运行 Tailscale 并想深入了解,请联系我们的支持和解决方案工程团队。我们可以帮助你加强设置,并在下一个 AI 代理发现之前帮你找到粗糙的边缘。