Azure Container Registries 凭据泄露场景下的利用思路

译文声明
本文是翻译文章,原作者 Karl Fosaaen
原文地址:https://blog.netspi.com/attacking-acrs-with-compromised-credentials/
译文仅作参考,具体内容表达请见原文

前言

Azure Container Registries(Azure容器注册表)是Microsoft用于管理云上Docker镜像的解决方案(以下简称ACR)。Azure官方对其相关解释如下:
容器注册表是一项存储和分发容器映像的服务 。 Docker Hub 是一个公共容器注册表,支持开放源社区并充当映像的通用目录。 Azure 容器注册表为用户提供映像直接控制、集成身份验证、支持全局分发和网络邻近部署可靠性的异地复制、标记锁定以及其他许多增强功能。除了 Docker 容器映像以外,Azure 容器注册表还支持相关的内容项目,包括开放容器计划 (OCI) 映像格式。
该服务允许使用 AzureAD单次登录 或 ACR管理员账户(Admin user) 来进行身份验证。该账户默认关闭,详情请见

在这篇文章中,我们假设你已经获得了ACR的某些管理员账户(Admin user)凭据。这些凭据可能被意外上传到Github、Jenkins服务或在一个能找到该凭证的任意地址。又或者是,你可能已经使用Get-AzPasswords的最新版来从Azure订阅中转储ACR管理员账户凭据。如果你有权执行此操作的话,可跳转到文章末尾来查看可以利用的Azure CLI命令。

获取到的管理员账户凭据大部分为 用户名/密码 的格式,并附加了ACR URL(例子:exampleacr.azurecr.io)
在此,假设已经拥有了这些管理员账户凭据,接下来将逐步完成访问ACR和在Azure订阅中的权限提升操作。

登录 ACR

在以下 Docker命令中输入用户名,ACR URL和密码:

docker login -u USER_NAME -p PASSWORD EXAMPLEACR.azurecr.io

如果管理员账户凭据正确便可成功登录

枚举容器名称和版本信息

为了访问容器镜像,我们将需要枚举容器名称及其版本信息。通常情况下可以通过一个经过身份验证的Azure CLI会话来执行此操作(请参阅下文),但是由于我们只有ACR管理员账户凭据,因此我们将必须使用Docker Registry API来完成此操作。
首先,我们将使用 _catalog API列出该ACR的所有容器信息。该操作需要身份验证,因此我们将在HTTP Basic认证(Base64 [USER:PASS])标头中使用ACR管理员账户凭据来完成操作。
简要 Powershell 代码如下:

现在我们有了容器列表,接下来我们将要查找每个容器其对应的版本信息。这可以通过如下URL来完成(其中 IMAGE_NAME 是你想要获得版本信息的容器名称)
https://EXAMPLEACR.azurecr.io/v2/IMAGE_NAME/tags/list
简要Powershell代码如下:

为了高效利用,我将上述Powershell代码进行了函数封装(GET-AzACR),工具地址为 MicroBurst
使用效果如下:

PS C:\> Get-AzACR -username EXAMPLEACR -password A_$uper_g00D_P@ssW0rd -registry EXAMPLEACR.azurecr.io
docker pull EXAMPLEACR.azurecr.io/arepository:4
docker pull EXAMPLEACR.azurecr.io/dockercore:1234
docker pull EXAMPLEACR.azurecr.io/devabcdefg:2020
docker pull EXAMPLEACR.azurecr.io/devhijklmn:4321
docker pull EXAMPLEACR.azurecr.io/imagetester:10
docker pull EXAMPLEACR.azurecr.io/qatestimage:1023
...

该脚本会输出拉取过的每个容器名称以及版本信息

说明:工具返回的版本信息可能不是容器的最新版本。该工具并不能获取关于特定版本的全部元数据。如果要查看所有容器的以及对应的所有版本,只需在工具的Get-AzACR命令上添加 -all 参数。
将工具的输出添加到 .ps1 文件,然后运行它以将所有容器镜像拉到本地测试系统(务必注意磁盘空间)。另外,您也可以选择要指定拉取的容器:

PS C:\> docker pull EXAMPLEACR.azurecr.io/dockercore:1234
1234: Pulling from dockercore
[Truncated]
6638d86fd3ee: Download complete
6638d86fd3ee: Pull complete
Digest: sha256:2c[Truncated]73
Status: Downloaded image for EXAMPLEACR.azurecr.io/dockercore:1234
EXAMPLEACR.azurecr.io/dockercore:1234

启动ACR Docker容器

一旦我们本地的测试系统上成功拉取到容器镜像,我们便可以运行它。如下的命令示例用于在名为“dockercore”容器开启一个交互式shell( 以 /bin/bash 终端为例):

docker run -it --entrypoint /bin/bash EXAMPLEACR.azurecr.io/dockercore:1234

通过该交互式shell,我们可以开始查看容器任意本地文件,并可能在其中找到敏感信息。

一个真实的例子

这里有一个最近的 Azure云测试的例子,过程如下:

  • Azure存储帐户公开了包含ACR管理员账户凭据的Terraform脚本
  • NetSPI(博主)通过Docker连接到ACR
  • 通过以上过程列出容器名称和版本信息
  • NetSPI使用Docker命令从ACR中提取容器
  • 在每个容器上运行bash shell并查看可用文件
  • 获取Azure订阅的存储密钥、Key Vault 以及其它服务主体凭据

如何使用Azure CLI 命令

如果你已经可以访问Azure订阅,并且你在ACR上拥有读权限,则Azure CLI是枚举容器名称和版本信息的最优方法。
在经过身份验证的Azure CLI会话中(这里的身份认证指Azure AD单次登录,也就是 az acr login),可以在订阅中列出注册表信息:

PS C:\> az acr list
[
{
"adminUserEnabled": true,
"creationDate": "2019-09-17T20:42:28.689397+00:00",
"id": "/subscriptions/d4[Truncated]b2/resourceGroups/ACRtest/providers/Microsoft.ContainerRegistry/registries/netspiACR",
"location": "centralus",
"loginServer": "netspiACR.azurecr.io",
"name": "netspiACR",
[Truncated]
"type": "Microsoft.ContainerRegistry/registries"
}
]

选择要攻击的注册表(netspiACR),然后使用以下命令列出容器名称:

PS C:\> az acr repository list --name netspiACR
[
"ACRtestImage"
]

列出容器的版本信息(ACRtestImage):

PS C:\> az acr repository show-tags --name netspiACR --repository ACRtestImage
[
"latest"
]

通过Docker认证:

PS C:\> docker login docker login EXAMPLEACR.azurecr.io
Login Succeeded

通过身份验证后,很容易就可以查询到容器名称和标识符,容器拉取过程将与上面相同。

总结

ACR是管理Azure基础结构中Docker镜像的好方案,但是请谨慎使用管理员账户凭据。此外,如果你在ACR使用了高级SKU,请限制ACR对特定网络的访问。即便管理员账户凭据被泄露,这将有助于降低ACR的可用性。最后,注意ACR的读权限。该权限可列出和提取ACR中的任何容器,因此他们可能具有比你预期更多的访问权限。

点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖