2019년 미국의 대형 금융지주회사 캐피탈 원이 해킹을 당해 1억명이 넘는 고객의 정보가 유출된 사례가 있습니다. 캐피탈원은 AWS를 사용중이었고, 공격자는 서버측 요청 위조 공격(SSRF) 취약점)을 이용해 AWS EC2의 인스턴스 메타 데이터 서비스(IMDS)에 액세스하여 AWS Access Key에 접근할 수 있었습니다.
애플리케이션 보안을 위한 WAF가 설정되어 있었으나 공격을 차단할 수 있는 적절한 설정이 되어있지 않았고, 자격 증명을 사용해 고객 정보가 저장된 S3 버킷에 액세스 할 수 있었습니다. (참고: Case Study: AWS and Capital One, https://sarangcho.co.kr/142 )
IMDS가 무엇이길래 액세스 정보까지 알아낼 수 있었던걸까요?
인스턴스 메타데이터는 말 그대로 인스턴스에 대한 데이터입니다. 이 데이터를 사용해서 인스턴스를 구성하거나 관리 할 수 있고 사용자 데이터(user data)에도 액세스 할 수 있습니다.
인스턴스를 시작하는 데 사용되는 AMI ID, 인스턴스와 연결된 IAM 역할의 정보, 인스턴스와 연결된 IAM 역할이 있는 경우 역할의 이름과 역할과 연결된 임시 보안 자격 증명도 메타데이터에 포함됩니다.
위와 같은 인스턴스 메타데이터를 조회하는 서비스를 인스턴스 메타데이터 서비스, IMDS(Instance Metadata Service)라고 합니다.
예를 들어 A 인스턴스가 있다면, A 인스턴스 내에서만 인스턴스 메타데이터와 사용자 데이터에 접근할 수 있습니다. 다른 인스턴스에서는 A인스턴스 메타데이터에 접근할 수 없지만, A인스턴스에 직접 액세스 할 수만 있다면 그게 사용자이든, 인스턴스에서 실행중인 소프트웨어든 관계없이 메타데이터를 볼 수 있습니다.
이말인 즉슨 ❗️공격자가 인스턴스 메타데이터에 접근할 수 있다면 임시 보안 자격 증명에 액세스할 수 있다는 뜻입니다.
위 내용을 인지한 상태로 실습을 진행해보겠습니다. 제공해주신 CloudFormation을 사용해 실습 환경을 구성했습니다.
가지고 있는 SSH Keypair를 선택하고, 마지막 단계에서 IAM 리소스 생성 승인을 체크하고 실행합니다.
스택 실행이 완료되면 WebServer
, Attacker
2개의 EC2가 생성됩니다. 두 인스턴스 모두 80,22 번 포트에 대해 모든 IP를 허용하도록 설정되어 있습니다.
여기서는 WebServer EC2의 메타데이터 서비스를 사용해 임시 자격 증명을 발급받고, Attacker인스턴스에서 WebServer의 임시 자격 증명을 사용해 S3에 접근하는 실습을 진행합니다.
IAM 자격증명 설정 되어 있는 PC에서 AWS CLI를 사용해 각각의 EC2 정보를 확인해보겠습니다.
# 생성된 EC2의 IP 출력
aws cloudformation describe-stacks --stack-name iamlab --query 'Stacks[*].Outputs[*].OutputValue' |jq
출력한 IP를 사용해 EC2에 접속합니다.
ssh -i <ssh-keyname>.pem ec2-user@<위 출력 IP>
[WebServer]
1. IMDS의 IP주소인 169.254.169.254
를 사용해 실행중인 인스턴스의 메타데이터에는 어떤 것들이 있는지 확인해보겠습니다.
ami-id, iam 등 조회할 수 있는 인스턴스 메타데이터 범주들이 표시됩니다.
curl -s http://169.254.169.254/latest/meta-data/
2. 여기서 iam 정보를 호출하면 인스턴스에 연결된 IAM 역할 이름을 반환합니다.
curl -s http://169.254.169.254/latest/meta-data/iam/info
3. 2에서 획득한 IAM 역할 이름을 사용하여 임시 자격 증명을 발급해보겠습니다. Accesskey, Secretkey와 Token 정보가 모두 출력됩니다.
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/IAMLabInstanceRole | jq
[Attacker]
1. Attacker EC2에 접속해 S3 버킷 목록을 나열해보겠습니다.
aws s3 ls
2. WebServer 인스턴스에서 탈취(?)한 임시 자격증명을 설정하고, S3 버킷 목록을 나열해보겠습니다.
# 위에서 출력된 AccessKeyId , SecretAccessKey , SessionToken 으로 임시자격증명 적용
export AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
export AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
export AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
# s3 버킷 조회
aws s3 ls
3. EC2에 연결된 IAM 역할은 없지만 WebServer 인스턴스의 임시 자격증명을 사용해 S3 버킷 목록 나열이 가능했다는 것을 알 수 있습니다.
# 어떤 인스턴스의 ID와 역할인가?
aws sts get-caller-identity | jq
AWS상에서 일어나는 모든 동작들은 API성으로 이루어져 CloudTrail에 기록됩니다. CloudTrail 콘솔에서 AssumeRole
API 호출에 대한 기록을 살펴보겠습니다.
AssumeRole 이벤트란?
사용자 또는 AWS 서비스가 IAM 역할을 맡을 때 생성되는 이벤트로, 역할이 수임되면 API 요청에 사용할 수 있는 임시 보안 자격 증명이 발급됩니다.
언제 어디서 어떤 주체에 의해 이벤트가 발생했는지 상세하게 기록된 것을 확인할 수 있습니다. 작업 주체, 발급된 자격증명 정보 등의 내용이 포함됩니다. 특정 동작을 필터링해서 알람을 받도록 설정하는 것도 자격 증명이 남용되는 것을 방지하는 하나의 방법이 될 수 있을 것 같습니다.
인스턴스 메타데이터에 접근할 때 IMDSv1과 v2 모두 사용할 수 있지만 OWASP에서는 보안상 IMDSv2를 사용하는 것을 권장하고 있습니다.
콘솔에서 [인스턴스 설정] > [인스턴스 메타데이터 옵션 수정] > [인스턴스 메타데이터 서비스] 에서 IMDSv2 를 필수로 설정합니다.
# IMDSv1
curl http://169.254.169.254/latest/meta-data/
# IMDSv2
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/
IMDSv2 명령어를 사용해 ami-id를 확인해보겠습니다.
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/ami-id
💡 모든 인스턴스에 콘솔 클릭클릭 노가다를 하는 것은 상당히 비효율적이기에 IAM 정책 또는 SCP에서 IAM 조건 키를 사용하여 IMDSv2를 사용해야 하도록 구성된 경우에만 인스턴스를 시작할 수 있도록 설정하는 방법도 있습니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "RequireImdsV2",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringNotEquals": {
"ec2:MetadataHttpTokens": "required"
}
}
}
]
}
콘솔에서 [인스턴스 설정] > [인스턴스 메타데이터 옵션 수정] > [인스턴스 메타데이터 서비스] 항목을 비활성화하여 인스턴스에서 IMDS를 사용하지 못하도록 설정할 수 있습니다.
[Webserver] 인스턴스에서 메타데이터 서비스를 비활성화하고 다시 메타데이터를 조회해봤습니다. 전과 달리 403 - Forbidden 에러가 발생합니다.
로컬 방화벽 규칙을 사용해 IMDS의 IP주소인 169.254.169.254
자체에 접근하지 못하도록 설정할 수 있습니다. (참고: IMDS 액세스 제한)
부끄럽지만 인스턴스 메타데이터 옵션에 이렇게 다양한 정보가 존재하는지, 해킹의 포인트가 될 수 있다는 사실을 모르고 살았습니다. 공격자의 입장에서 생각해보는게 보안을 강화하는 첫걸음이라는 생각이 들었습니다. 스터디 2주차밖에 되지 않았지만 생각의 지평이 크게 확장되고 있다는 느낌이 듭니다.
더불어 정답이 없다는 생각도 들어요. 그래서 더 어려운 것 같습니다.
제가 있는 회사에서는 SSM(Session Manager)를 사용한 인스턴스 접속이 액세스 키를 관리할 필요가 없기 때문에 보안상 우수하다고 여기는데, 분리되지 않은 단말기에서 인스턴스에 접근 가능하기 때문에 SSM 사용을 제한해야한다는 의견도 있더라구요. 다들 어떻게 사용하고 계시는지 궁금합니다. !
+) 스크린샷에 있는 EC2와 기타 정보들은 모두 삭제된 리소스입니다.
CloudNet@팀의 AHSS(AWS Hacking & Security 스터디) 학습 내용과 제가 공부한 내용을 정리한 글입니다.
더 좋은 방법이나 틀린 내용이 있으면 말씀해주세요 :)
AWS S3 취약점 및 보안 (0) | 2023.09.02 |
---|---|
키페어 없이 AWS CLI를 사용하여 EC2 인스턴스에 SSH로 연결하기 (0) | 2023.06.21 |
System Manager로 특정 시간에 EC2 인스턴스 시작/중지 자동화하기 (0) | 2023.06.03 |
EC2 상태 변경 알람 Slack으로 받아보기 (0) | 2023.06.01 |
AWS User Notifications로 AWS EC2 상태 변경 알람 받기 (0) | 2023.05.25 |
댓글 영역