通过错误配置的 AWS Cognito 接管 AWS 帐户,原文:https://notsosecure.com/hacking-aws-cognito-misconfigurations
环境背景
- 被测应用程序只有一个登录页面,没有公开注册功能
- 目标应用程序使用披露应用程序客户端 ID、用户池 ID、身份池 ID 和区域信息的 AWS Cognito JavaScript 开发工具包
- AWS cognito 配置错误以允许注册新用户
- 注册并登录以获得经过身份验证的身份的 AWS 临时令牌
- AWS 令牌可以访问用于提升访问权限的 Lambda 函数
Amazon Cognito
Amazon Cognito 管理用户身份验证和授权 (RBAC)。用户池允许登录和注册功能。身份池(联合身份)允许经过身份验证和未经身份验证的用户使用临时凭证访问 AWS 资源。
简而言之,用户池存储所有用户,身份池使这些用户能够访问 AWS 服务。
下图显示了 AWS Cognito 身份验证和授权流程。用户通过用户池进行身份验证,成功身份验证后,用户池将 3 个 JWT 令牌(ID、Access 和 Refresh)分配给用户。ID JWT 被传递到身份池,以便接收分配给身份提供者角色的临时 AWS 凭证。
参考:https://aws.amazon.com/cn/blogs/mobile/building-fine-grained-authorization-using-amazon-cognito-user-pools-groups/
攻击过程
在最近的一次渗透测试中,我们偶然发现了一个登录页面。它没有暴露其他与身份验证相关的功能,例如忘记密码或注册页面。
经过进一步调查,我们发现该应用程序使用 AWS Cognito 通过 JavaScript 开发工具包进行身份验证和授权。客户端上的 JavaScript SDK 通过 JavaScript 配置文件公开了 App Client ID、User Pool ID、Identity Pool ID 和区域信息等数据。对于 AWS Cognito 的 JavaScript SDK需要此信息才能访问 Cognito 用户池并验证用户。
Amazon Cognito 具有经过身份验证和未经身份验证的模式来为用户生成 AWS 临时凭证。任何人都可以使用特定的 API 调用获得未经身份验证的访问权限。因此,我们尝试通过使用未经身份验证的身份访问 AWS 凭证,但对未经身份验证的身份的访问被禁用。
此处列出了将 AWS 服务暴露给未经身份验证的身份领域的 一个有趣的案例研究: https://andresriancho.com/wp-content/uploads/2019/06/whitepaper-internet-scale-analysis-of-aws-cognito-security.pdf。
我们发现该应用程序通过 AWS Cognito 错误配置无意中暴露了一些功能。使用 AppClientId,我们在 Amazon Cognito 用户池中创建了一个用户。确认电子邮件与确认代码一起发送到指定的电子邮件。
测试后发现:我们可以使用 ConfirmSignUp API 从注册电子邮件中收到的令牌确认用户帐户。
现在,当我们使用新注册的帐户登录应用程序时,应用程序响应错误,“用户不属于任何组”。故该应用需要应用程序内授予的组权限才可以访问。
我们意识到,该应用程序实际上验证了一个新创建的用户并返回了访问令牌,但不允许该用户访问任何页面,因为该用户不属于任何有权访问该应用程序的组。
现在我们已经验证了访问权限和 ID 令牌。这些值可用于为经过身份验证的身份生成临时 AWS 凭证。
现在我们可以使用 AWS 命令行界面 (CLI) 与 AWS 服务进行交互:
使用“aws sts get-caller-identity”命令,可以确定令牌工作正常。
通过利用我们的云服务枚举脚本,可以观察到 AWS 令牌对 AWS Lambda 函数具有完全权限。这使我们能够探索客户端的 AWS Lambda 配置。我们首先查看 Lambda 函数列表:
aws lambda 列表函数
我们发现其中一个 Lambda 函数 (RotateAccessKeys-CIS) 的 IAM 策略过于宽松。
aws iam list-attached-role-policies --role-name IAM-CIS
我们决定修改 Lambda 函数代码 (RotateAccessKeys-CIS),使其按要求工作,但另外执行了一个允许从环境变量读取 AWS 凭证的命令。
我们从突出显示的代码位置下载了 Lambda 函数代码
aws lambda get-function --function-name RotateAccessKeys-CIS --query 'Code.Location'
下载代码中的“lambda_handler”函数被修改为打印环境变量。
此外,我们创建了一个包含修改后代码的 ZIP 文件,以便它在上传和调用包后执行修改后的 Lambda 函数。
Lambda 函数“RotateAccessKeys-CIS”现已更新。
aws lambda update-function-code --function-name RotateAccessKeys-CIS --zip-file fileb:///root//lambda_function.zip
一旦 Lambda 函数代码按预期更新,我们使用下面提到的命令调用它。此命令调用该函数并在包含 AWS 临时凭证的屏幕上打印日志。
aws lambda invoke --function-name RotateAccessKeys-CIS out --log-type Tail --query 'LogResult' --output text | base64 -d
我们重复了相同的步骤,并确定了一组具有完全 IAM 访问权限的临时凭证。
接下来,我们使用新的 AWS 凭证配置 AWS CLI 以创建新用户“nirahua”,并使用以下命令将名为 AdministratorAccess 的 AWS 托管策略附加到用户。
aws iam create-user --user-name nirahua
aws iam create-login-profile --user-name nirahua --password s8iUzu******
aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --user-name nirahua
如您所见,我们以管理员身份通过 AWS 控制台以新创建的用户身份成功登录。
建议
- 如果不需要,请在 AWS Cognito 上禁用注册
- 在为经过身份验证和未经身份验证的身份配置 AWS Cognito 时,切勿分配超出最低要求的权限。
- 使用 Amazon Cognito 的高级安全功能来保护应用程序用户免受未经授权的访问。