Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2023-24329-lab — 자체 포함된 Docker 랩으로, CVE-2023-24329(Python urllib 파서 차이를 이용하여 URL 스킴 및 호스트 필터를 우회하는 취약점)를 시연하며, 실습형 보안 교육을 위한 취약 및 패치 환경을 제공합니다. | Kitploit
도구/GitHubGitHub/jithinodattu/cve-2023-24329-lab
Vulnerability AnalysisExploitationWeb SecurityCTFPenetration TestingLearning & EducationLabs & Practice
GitHubjithinodattu/cve-2023-24329-lab

CVE-2023-24329-lab

자체 포함된 Docker 랩으로, CVE-2023-24329(Python urllib 파서 차이를 이용하여 URL 스킴 및 호스트 필터를 우회하는 취약점)를 시연하며, 실습형 보안 교육을 위한 취약 및 패치 환경을 제공합니다.

저장소 보기
4개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2023-24329 — 파서 차이 연구소

교육 목적으로만 사용하세요. 이 연구소는 안전하고 격리된 환경에서 실제 취약점을 시연하기 위해 존재합니다. 소유하지 않은 시스템에서 절대 실행하지 마세요. 의도적으로 손상된 필터 코드를 프로덕션 시스템에서 절대 재사용하지 마세요.

Python < 3.11.4에서 urllib.parse.urlparse()의 파서 차이로 인해 URL 스킴 및 호스트 필터를 우회할 수 있는 CVE-2023-24329를 시연하는 독립형 Docker 연구소입니다.

이 연구소는 file:// URL과 내부 호스트 이름을 명시적으로 차단하는 API가 트릭을 당해 자체 컨테이너의 /etc/passwd를 읽고 비공개 내부 서비스에 접근하는 모습을 보여준 후, 패치된 Python에서는 동일한 익스플로잇이 실패함을 증명합니다.


취약점

Python의 urlparse()와 기본 HTTP/파일 페처(fetcher)는 선행 공백이 있는 URL을 처리하는 방식이 다릅니다. 영향을 받는 버전에서:

root@kitploit:~
from urllib.parse import urlparse

urlparse(" file:///etc/passwd").scheme   # → ""   (비어 있음 — 필터 통과)
urlparse(" file:///etc/passwd").hostname # → None (비어 있음 — 필터 통과)

그러나 urllib.request.urlopen(" file:///etc/passwd")는 공백을 제거하고 file:///etc/passwd를 가져옵니다.

파서가 보는 것과 페처가 수행하는 것 사이의 차이 — 이것이 취약점입니다.

Python 3.11.4에서는 파싱 전에 선행 공백/제어 문자를 제거하여 이 차이를 없앰으로써 이 문제를 수정했습니다.


데모 — 세 단계


아키텍처

격리된 Docker 브리지 네트워크(cve-lab-net) 상의 4개 서비스:

internal-service에는 호스트 포트 매핑이 없습니다 — Docker 네트워크 내부에서만 접근 가능하며, 실제 신뢰 경계를 시뮬레이션합니다.


사전 요구 사항

  • Docker Desktop (또는 Docker Engine + Compose 플러그인)
  • 이미지용 약 500MB 디스크 공간

빠른 시작

root@kitploit:~
git clone <repo-url>
cd CVE-2023-24329-lab

단계 1 — 기준: 필터가 유지되는지 확인

root@kitploit:~
docker compose -f docker-compose.vulnerable.yml up --build -d
docker compose -f docker-compose.vulnerable.yml exec attacker python exploit.py baseline

단계 1 — 기준 필터 유지

단계 2 — 익스플로잇: 필터 우회

root@kitploit:~
docker compose -f docker-compose.vulnerable.yml exec attacker python exploit.py exploit

단계 2 — 우회 성공, /etc/passwd 및 내부 비밀 노출

단계 3 — 패치: 동일한 페이로드, 패치된 Python

root@kitploit:~
docker compose -f docker-compose.vulnerable.yml down
docker compose -f docker-compose.fixed.yml up --build -d
docker compose -f docker-compose.fixed.yml exec attacker python exploit.py verify

단계 3 — Python 3.11.4에서 패치 유지

정리

root@kitploit:~
docker compose -f docker-compose.fixed.yml down

디렉터리 구조

root@kitploit:~
CVE-2023-24329-lab/
├── docker-compose.vulnerable.yml   # Python 3.11.3 (영향 받는 버전)
├── docker-compose.fixed.yml        # Python 3.11.4 (패치된 버전)
├── vulnerable-api/
│   ├── app.py                      # 순진한 필터가 있는 Flask API
│   ├── requirements.txt
│   └── Dockerfile
├── internal-service/
│   ├── app.py                      # 가짜 내부 메타데이터 엔드포인트
│   ├── requirements.txt
│   └── Dockerfile
└── attacker/
    ├── exploit.py                  # 데모 드라이버 (기준 / 익스플로잇 / 검증)
    ├── requirements.txt
    └── Dockerfile

취약한 API와 패치된 API 서비스는 동일한 소스 코드를 공유합니다 — 기본 이미지 Python 버전만 다릅니다. 이것이 연구소의 핵심 과학적 통제 속성입니다.


우회 작동 방식

취약한 API 필터 (단순화됨):

root@kitploit:~
parsed = urllib.parse.urlparse(url)

if parsed.scheme.lower() in {"file", "gopher", "ftp", "data"}:
    return 403  # 차단됨

if parsed.hostname in {"localhost", "127.0.0.1", "internal-service"}:
    return 403  # 차단됨

urllib.request.urlopen(url)  # 원본, 수정되지 않은 문자열 가져오기

우회 페이로드는 앞에 하나의 공백입니다:

root@kitploit:~
 file:///etc/passwd
^
공백 (0x20)

Python ≤ 3.11.3에서 urlparse는 스킴이 비어 있고 호스트네임이 없다고 봅니다 → 필터 통과. urlopen은 공백을 제거합니다 → file:///etc/passwd를 가져옴.

Python ≥ 3.11.4에서 urlparse는 먼저 공백을 제거합니다 → scheme=file을 올바르게 인식 → 필터가 403으로 차단.


수정 사항 (패치된 Python이 하는 일)

CPython 이슈 #102153 — 수정 사항은 파싱 전에 URL 시작 부분의 C0 제어 문자와 공백을 제거합니다. 패치 후 파서와 페처가 URL에 대해 동일하게 인식하므로 이러한 방식으로 필터를 우회할 수 없습니다.

Python 버전에 관계없이 올바른 방어 패턴:

root@kitploit:~
# 파싱 → 부분에서 재구성 → 재구성된 URL을 다운스트림에 전달.
# 필터와 페처 모두 동일한 문자열에서 작동합니다.
parsed = urllib.parse.urlparse(url)
safe_url = parsed.geturl()  # 구성 요소에서 재구성
urllib.request.urlopen(safe_url)

주요 교육 포인트

  1. 파서 차이는 일회성 버그가 아닌 취약점 클래스입니다. 동일한 아이디어가 HTTP 요청 밀반입, SAML 혼동 공격, log4j의 ${jndi:...} 우회를 유발합니다.
  2. 파서가 거짓말을 할 때 차단 목록은 실패합니다. 잘못된 입력을 열거하는 것은 지는 게임입니다.
  3. 원시 입력 문자열이 아닌 재구성된 URL을 검증하세요.
  4. 하나의 사소한 버전, 하나의 작은 패치, 엄청난 결과. CPython 수정 사항은 몇 줄에 불과합니다.

참고 자료

  • NVD: CVE-2023-24329
  • CPython 이슈: github.com/python/cpython/issues/102153
  • 원본 공개: Yebo Cao — "CVE-2023-24329 Yebo Cao" 검색
  • 더 넓은 클래스: PortSwigger — SSRF 필터 우회 기술
  • 더 넓은 클래스: James Kettle — HTTP 역동기화 공격

안전 장치

  • internal-service 포트를 호스트에 노출하지 마세요.
  • 이 연구소를 프로덕션 네트워크에 연결된 머신에서 실행하지 마세요.
  • vulnerable-api/app.py의 필터 코드는 교육 목적으로 의도적으로 손상되었습니다 — 실제 시스템에 복사하지 마세요.

라이선스

MIT — 교육 목적으로 자유롭게 사용, 공유, 수정 가능하며 출처 표시가 필요합니다.

도구 다운로드
단계보여지는 것설명
1 — 기준file:///etc/passwd → 403 blocked scheme필터가 합리적으로 보임
2 — 익스플로잇공백이 앞에 있는 동일한 URL → 200 + /etc/passwd 내용 및 내부 비밀하나의 공백이 전체 필터를 무력화
3 — 패치Python 3.11.4에서 동일한 페이로드 → 403 blocked패치된 urlparse가 먼저 공백을 제거; 필터가 올바르게 차단
서비스Python 버전역할호스트 포트
vulnerable-api3.11.3순진한 URL 필터가 있는 대상 API8000
fixed-api3.11.4동일한 코드, 패치된 인터프리터8000
internal-service3.12가짜 내부 메타데이터 엔드포인트없음
attacker3.12익스플로잇 드라이버없음