AWS Instance Metadata Service(IMDS)는 취약점 그 자체가 아니다. EC2 안의 software가 instance 정보와 IAM role의 임시 자격 증명을 얻는 local service다. 문제는 SSRF나 과도한 process 권한을 통해 의도하지 않은 코드가 IMDS에 접근할 때 생긴다.
안전한 기준은 IMDSv2만 요구하는 데서 끝나지 않는다. 애플리케이션의 SSRF 방어, 최소 권한 IAM role, container별 workload identity, instance metadata option과 host-level 접근 통제를 함께 적용해야 한다.
IMDS에는 무엇이 들어 있나
IMDS는 EC2 instance 내부에서 IPv4 link-local 주소 169.254.169.254로 접근한다. Nitro 기반의 지원 환경에서는 별도로 활성화한 IPv6 endpoint도 쓸 수 있다. metadata에는 다음과 같은 정보가 포함될 수 있다.
- instance ID, instance type, AMI ID
- network interface와 placement 정보
- instance tag 중 metadata 공개를 허용한 값
- instance profile에 연결된 IAM role의 임시 자격 증명
- launch 때 전달한 user data
특히 IAM role credential은 AWS SDK와 CLI가 자동으로 가져가므로 long-lived access key를 instance에 저장하지 않아도 된다는 장점이 있다. 그러나 instance 안에서 IMDS에 접근할 수 있는 software라면 같은 credential을 얻을 가능성이 있다. user data 역시 인증·암호화된 secret store가 아니므로 password나 장기 encryption key를 넣어서는 안 된다.
외부 공격자가 IMDS에 직접 접속하는가
일반적인 공격 흐름은 외부에서 169.254.169.254로 직접 연결하는 모습이 아니다. 외부 요청을 받은 application이나 proxy가 공격자가 지정한 URL을 대신 요청하면서 local endpoint에 닿는 형태다.
attacker input
│
▼
vulnerable URL fetcher / proxy
│ SSRF
▼
169.254.169.254 (IMDS)
│
└─ metadata or temporary role credentials
이미 remote code execution을 얻은 공격자나 instance 안의 악성 process도 같은 경로를 노릴 수 있다. 따라서 IMDS 방어를 network perimeter 하나로 설명하면 부족하다.
IMDSv1과 IMDSv2의 차이
IMDSv1은 metadata path에 request를 보내는 단순한 request-response 방식이다. IMDSv2는 먼저 PUT /latest/api/token 요청으로 session token을 받고, 이후 metadata request에 그 token을 header로 포함한다.
IMDSv1
GET metadata path ───────────────────────> response
IMDSv2
PUT token path + requested TTL ─────────> token
GET metadata path + token header ───────> response
IMDSv2 token은 해당 instance에 묶이며 정해진 시간이 지나면 만료된다. token PUT response에는 hop limit도 적용된다. 이런 구조는 단순한 open proxy나 제한된 SSRF가 metadata를 읽는 난도를 높이는 defense in depth다.
다만 IMDSv2가 SSRF를 자동으로 제거하지는 않는다. 공격자가 임의 method와 header를 보내고 response까지 읽을 수 있거나, instance에서 code를 실행할 수 있다면 token 절차도 수행할 수 있다. application이 받아들일 URL과 redirect를 통제하는 SSRF 방어는 여전히 필요하다.
방어는 여섯 층으로 나눈다
1. 애플리케이션에서 URL fetch 범위를 제한한다
URL preview, webhook, image fetch, PDF 변환, XML parser와 proxy처럼 server가 대신 외부 resource를 읽는 기능은 SSRF 경계다.
- 가능한 경우 사용자가 URL 전체를 정하게 하지 말고 허용된 service와 resource ID만 받는다.
- scheme, hostname, port를 allowlist로 제한한다.
- DNS resolution 뒤의 실제 destination이 loopback, link-local, private·reserved range인지 검사한다.
- redirect할 때마다 다시 검증하고 redirect 수를 제한한다.
- proxy가 임의 header와 method를 전달하지 않게 한다.
- outbound proxy와 egress policy에서도 metadata address를 차단한다.
문자열이 169.254.169.254와 같은지만 보는 denylist는 IPv6, 다른 IP 표기, DNS rebinding과 redirect를 놓칠 수 있다.
2. EC2에서 IMDSv2를 요구한다
metadata가 필요하다면 HttpTokens=required로 IMDSv1 request를 거부한다. metadata가 전혀 필요하지 않은 workload라면 endpoint 자체를 disable하는 선택도 가능하다.
설정은 instance, AMI, Region별 account default와 launch 요청의 우선순위에 따라 결정된다. account default를 바꿨다고 기존 instance가 자동으로 모두 바뀌는 것은 아니다. Auto Scaling launch template, image 설정과 이미 실행 중인 instance를 각각 확인해야 한다.
IAM policy나 AWS Organizations SCP의 EC2 metadata condition key를 사용하면 IMDSv2를 요구하지 않는 새 instance launch를 제한할 수 있다. 실제 적용 전에는 agent와 application 호환성을 확인해야 한다.
3. hop limit을 맥락에 맞게 최소화한다
metadata response hop limit은 IMDSv2 token PUT response가 통과할 수 있는 network hop 수다. host process만 쓸 때와 network namespace를 거치는 container가 쓸 때 필요한 값이 다를 수 있다. AWS는 container 환경에서 hop limit 1이 문제를 일으킬 수 있으며 새 instance 설정에서 2를 권장한다.
그렇다고 값을 높이는 것이 container isolation을 대신하지는 않는다. 필요한 최소값을 canary에서 확인하고, container가 instance role을 공유하지 않아야 한다면 별도의 workload identity와 network 차단을 함께 사용한다.
4. IAM role의 blast radius를 줄인다
IMDSv2를 우회당하더라도 credential의 권한이 작으면 피해 범위가 줄어든다.
- application이 실제로 호출하는 action과 resource만 허용한다.
- 서로 다른 trust boundary의 workload가 instance role 하나를 공유하지 않게 한다.
- ECS task role, EKS workload identity처럼 container·Pod 단위 identity를 우선 검토한다.
- wildcard permission과 불필요한 role chaining을 줄인다.
- CloudTrail에서 role session의 비정상 API call을 탐지한다.
임시 credential은 자동 rotation되지만, 유효 시간 동안에는 실제 권한을 가진다. “어차피 임시 키”라는 이유로 role policy를 넓게 두면 안 된다.
5. 필요한 process만 IMDS에 접근하게 한다
IMDS를 쓰는 process와 쓰지 않는 process가 같은 host에 있다면 local firewall의 user·group 기반 rule로 접근 범위를 줄일 수 있다. AWS도 Linux iptables, Windows Firewall 등 host-level 통제 방법을 안내한다.
Security Group과 Network ACL만으로 이 경계를 해결하려 해서는 안 된다. 일반 application traffic의 VPC packet filter와 instance local metadata 접근은 경로가 다르다. network appliance가 source/destination check를 끈 채 packet을 forward하는 특수 구성이라면 metadata destination을 명시적으로 drop해야 한다.
host firewall rule은 reboot persistence, user identity, container namespace와 운영 agent 호환성을 함께 시험해야 한다. 예제 rule을 그대로 복사해 적용하는 작업이 아니다.
6. migration과 회귀를 관측한다
기존 fleet에서 바로 IMDSv2-only로 전환하면 오래된 SDK나 monitoring agent가 멈출 수 있다.
- inventory에서 metadata option과 instance role을 확인한다.
- CloudWatch의
MetadataNoToken으로 IMDSv1 사용 흔적을 찾는다. - SDK, CLI, bootstrap script와 agent를 IMDSv2 지원 version으로 올린다.
- canary instance에서
HttpTokens=required와 hop limit을 검증한다. - launch template과 account default를 바꾸고 새 instance부터 확산한다.
- 기존 instance를 별도로 전환한 뒤 error와 credential retrieval 실패를 관측한다.
MetadataNoToken이 0이라는 사실만으로 application의 SSRF 방어가 끝났다는 뜻은 아니다. IMDSv1 호출이 관측되지 않았다는 한 가지 신호일 뿐이다.
운영 점검표
- IMDS가 필요한 workload와 필요 없는 workload를 구분했는가?
- 모든 실행 경로가 IMDSv2를 지원하는가?
HttpTokens, endpoint, IPv6 endpoint와 hop limit의 실제값을 확인했는가?- Auto Scaling과 새 instance launch에도 같은 정책이 적용되는가?
- URL fetch 기능이 redirect와 DNS resolution 뒤 주소까지 검증하는가?
- instance role이 최소 권한이고 container별 identity가 분리돼 있는가?
- user data에 민감 정보가 남아 있지 않은가?
- IMDS 접근 실패와 role credential의 이상 사용을 탐지하는가?
IMDSv2는 반드시 켜야 할 중요한 안전장치지만 단독 해결책은 아니다. SSRF가 local request를 만들지 못하게 하고, metadata 접근 주체를 줄이며, 노출돼도 쓸 수 있는 IAM 권한을 제한하는 것까지가 하나의 방어다.
웹 공격과 방어 경계 정리는 SSRF를 다른 application attack과 함께 볼 때 도움이 된다. credential을 application에 전달하고 회수하는 설계는 HashiCorp Vault 시크릿 관리에서 이어서 볼 수 있다.
참고 자료
'배움과 성장 > DevOps·클라우드' 카테고리의 다른 글
| Kubernetes Spot 중단 대응: 단일 Pod 무중단이 불가능한 이유 (0) | 2024.09.20 |
|---|---|
| Kubernetes requests·limits·QoS: CPU throttling과 OOM 이해 (0) | 2024.09.20 |
| Apache·IIS·NGINX 비교: 웹 서버를 고르는 실무 기준 (2) | 2024.08.15 |
| Kubernetes 컨트롤 플레인과 워커 노드: Pod가 실행되는 통신 흐름 (0) | 2024.08.13 |
| GitHub 인증 오류 해결: 비밀번호 대신 CLI·Credential Manager·SSH 사용하기 (4) | 2023.04.09 |
댓글