During a routine external security sweep of Huge Logistics, your team stumbled upon a public git repository. It wasn't just any repository; it contained the entire source code for their new Android application. It might just be the entry point you need to access the company's broader cloud environment. The challenge now is to sift through the application's intricacies, identify potential vulnerabilities, and see if these breadcrumbs lead deeper into Huge Logistics' digital realm. The perimeter is your starting line; how far can you go?
真实场景
在 2500 个 AWS Cognito(客户身份和访问管理 CIAM),可以用于访问 1.3w个非公开 S3 桶,1.2k DynamoDB 表 和 1.5k 个 Lambda 函数
通过使用 Amazon Cognito,开发者可以专注于应用体验,而无需担心构建、保护和扩展解决方案来处理用户管理、认证和跨设备同步。Cognito 主要由两项核心服务组成:用户池(User Pools)和联合身份(Federated Identities,即身份池)。Amazon Cognito 用户池提供了一个安全、可扩展的用户目录,作为一个完全托管的服务,用户池易于设置,无需担心服务器基础设施。用户池提供了内置的、可定制的注册和登录体验。Amazon Cognito 联合身份允许应用程序为用户创建独特的身份,并与身份提供者联合。有了联合身份,应用用户可以获得临时的、有限权限的AWS凭证,以与 Amazon Cognito 同步数据,或安全地访问其他 AWS 服务

- 客户端通过用户池进行身份验证
- 用户池将 3 个 JWT 令牌(Id、Access 和 Refresh)分配给客户端。
- 将 Id JWT 传递到身份池,并通过 JWT 声明选择角色。身份池基于映射到用户所属组的 IAM 角色权限返回 IAM 临时凭证。
- 用户随后可以根据他们的权限对AWS资源进行调用
身份池
代码中导入了
com.amazonaws.auth.CognitoCachingCredentialsProvider 类,即 AWS Cognito 相关的,里面写了身份池 ID、桶名、以及 lambda 函数调用Cognito 可以配置未授权身份,为那些不通过身份提供者进行身份验证的用户发放短期有效的 AWS 凭证,只要请求者拥有一个有效的唯一身份 ID。我们可以尝试通过在源代码中提供身份池 ID 来请求一个唯一的身份 ID。
拿到身份 ID 后,就能请求凭证了
aws configure 然后 aws configure set aws_session_token 配置完后,查看身份通过 aws-enumerator 枚举不到权限,尝试直接读代码中的桶
现在拿到一个私钥,但没服务器啥的
用户池
您的团队还发现了与 Cognito 用户池相关联的 Web 应用程序的一个公开暴露的 Cognito 托管用户界面。URL(以及表单)引用了客户端 ID 16f1g98bfuj9i0g3f8be36kkrl。

在页面注册,会报错,走命令行
这里也通过 username 参数枚举用户是否存在,存在会报错 用户名已存在
报错,说没 confirm
校验验证码
就能成功登录了,就是前面说的,会返回 3 个 token
不过这个 token 一小时会过期,这里通过 jq 直接获取输出的 IdToken
先把 IdToken 通过 JWT 解码拿到 iss,然后拼接通过 IdToken 请求获取唯一身份 ID
获取 STS
设置一下这个 STS,然后查看一下身份
查看该角色默认 AWS 托管策略
依次附加角色策略名、策略版本和版本内容
可以查看所有 Lambda 函数以及查看和调用函数
一个个看,通过 Location 字段可以下载上传的代码压缩包
代码内容
如果没传入 target 就默认请求 http://huge-logistics.com,
target 部分可控请求存在 SSRF请求 example.com
能正常请求,然后尝试请求环境当前进程变量
/proc/self/environ拿到 STS,配置一下查看身份
然后读一下脚本里的桶,就可以拿到 flag 了,另外一个 pdf 是密码本
然后在环境变量里,还有一个 API
看 WP 接口路径是
/2018-06-01/runtime/invocation/next 但不知道哪来的,不过这里属于发散的防御
Cognito
- 用户池应禁用多余的注册功能
- 身份池非业务必须也不应开启
- 应开启 Amazon Cognito 高级安全设置,它可以检测已泄漏的凭证,以及避免使用这些凭证登录,并将任何可疑的登录行为记录在Amazon CloudWatch中。此外,它还具备自适应认证功能,能够对那些看起来有风险的登录尝试(比如来自未知设备或异常地点的登录)进行风险评估,然后根据评估结果自动或手动采取措施,比如禁止登录、要求进行多步骤验证,或者对CloudWatch 中记录的事件进行响应
Lambda
- 应该设置
target参数白名单,如
然后桶其实也可以通过环境变量传进来,就不用硬编码了
如果需要,我们还可以将从用户接收到的事件数据记录到S3桶中进行进一步分析。
S3 桶
SSH私钥和关键容灾文档不应存储在可公开访问的存储桶中
进一步阅读
- https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/ -
- Flickr 作为服务提供方没有校验 Amazon Cognite 邮箱合法用户是否通过邮箱验证过,就直接用了,而且 Flickr 邮箱是不区分大小写,但 AmazonCognite 是区分的。
- 首先受害者邮箱是
[email protected],攻击者先注册一个[email protected]完成邮箱验证后,通过aws cognito-idp update-user-attributes --region us-east-1 --access-token eyJraWQ[...] --user-attributes Name=email,[email protected]aws cli 接口更新自己的邮箱为[email protected],即受害者的大写 - 但从 Amazon Cognite 角度,它区分大小写的,不过尽管攻击者更改了,邮箱其实是未验证状态(Cognite 服务有提供这个字段,但 Flickr 没校验),毕竟攻击者确实没这个邮箱。但登录的时候,Flickr 由于不区分大小写,直接攻击者通过新邮箱,攻击者自己的密码就直接登进去
这个问题防护方法很多,比如直接在 Cognite 配置邮箱未保护字段,就无法自行通过 aws cli 去改了,再者就是一定要校验邮箱的验证状态
- https://www.darkreading.com/cloud-security/dow-jones-data-leak-results-from-an-aws-configuration-error - 道琼斯数百万客户信息数据泄漏,因为 S3 桶的数据配置错误问题,AWS将 “已认证用户” 定义为任何拥有免费AWS账户的人,配置的人会误以为他自己配对了,太典了
- https://andresriancho.com/wp-content/uploads/2019/06/whitepaper-internet-scale-analysis-of-aws-cognito-security.pdf - 对 Cognite 安全性进行一些研究,发现的 2504 个硬编码身份 ID,83.2% 来自 Google Play 上的 apk,8.4%来自 Github,其中 79.2% 像本题一开始那种,有身份 ID 未授权即可使用,然后还存在配置权限过大,可以查看数据库和桶等问题。原因有很多,比如 AWS 官方例子就《有教允许未授权》 Cognite 角色执行相关逻辑…
