
fastcore의 untar_dir()에서 발생하는 tar-slip 경로 순회 취약점인 CVE-2026-65320을 문서화하며, 임의 파일 쓰기 및 코드 실행을 보여주는 무해한 개념 증명을 포함합니다.
untar_dir()를 통한 fastcore의 경로 순회(Tar Slip) 취약점심각도: 치명적, CVSS 3.1 9.8
벡터 (v3.1): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
영향받는 버전: fastcore <= 2.2.30
수정 버전: 작성 시점 기준 미수정
CWE: CWE-22 (경로명의 제한된 디렉터리 제한 부적절, '경로 순회')
구성 요소: fastcore.xtras.untar_dir() → fastcore.xtras._unpack() → shutil.unpack_archive()
고위험 런타임: Python < 3.14 (Python 3.14에서는 안전한 data tar 필터가 기본값이 됨)
보고자: Rahul Karne
CNA: VulnCheck
fastcore.xtras.untar_dir(fname, dest)는 아카이브를 "dest로" untar하는 문서화된 헬퍼입니다.
내부적으로 이 함수는 아카이브를 표준 라이브러리의 shutil.unpack_archive()에 전달하며, 추출 필터도 없고, 아카이브 멤버 경로 검증도 없으며, 추출 후 포함 여부 확인도 수행하지 않습니다.
결과적으로, 멤버에 ../ 순회 시퀀스나 절대 경로가 포함된 TAR 아카이브는 호출자가 fastcore에 추출을 요청한 디렉터리 외부에 파일을 쓸 수 있습니다.
untar_dir(fname, dest)가 모든 것을 dest 내로 제한할 것이라고 합리적으로 기대하는 호출자는 대신 프로세스가 쓸 수 있는 모든 위치에 임의 파일 쓰기를 허용하게 됩니다.
untar_dir()을 호출하는 프로세스의 권한으로 임의 파일 쓰기가 가능합니다.
무엇이 덮어써지는지에 따라 다음과 같은 결과가 발생할 수 있습니다:
개념 증명(PoC)은 완전한 쓰기 → 임포트 → 코드 실행 체인을 무해한 데모 디렉터리 내에서 처음부터 끝까지 시연합니다.
fastcore는 다음을 포함한 fast.ai 생태계 전반의 기반 의존성입니다:
fastainbdevghapi월 수천만 건의 다운로드가 발생합니다.
untar_dir()은 일반적인 "아카이브 다운로드 후 압축 해제" 워크플로우를 뒷받침하는 추출 기본 요소이며, 이는 fastai의 untar_data와 동일한 일반 패턴을 따릅니다.
내용이 완전히 신뢰되지 않는 아카이브를 untar_dir()에 전달하는 모든 코드 경로가 노출됩니다.
취약한 코드는 fastcore/xtras.py에 존재합니다:
def _unpack(fname, out):
import shutil
shutil.unpack_archive(str(fname), str(out)) # <-- no filter, no validation
ls = out.ls()
return ls[0] if len(ls) == 1 else out
def untar_dir(fname, dest, rename=False, overwrite=False, uid=-1, gid=-1):
"untar `file` into `dest` ..."
import tempfile, shutil
dest = Path(dest)
with tempfile.TemporaryDirectory() as d:
out = Path(d) / remove_suffix(Path(fname).stem, '.tar')
out.mkdir()
...
src = _unpack(fname, out) # extraction escapes `out` here
...
shutil.move(str(src), dest)
...
return dest
untar_dir()는 내부 임시 추출 디렉터리를 생성합니다:
<tempdir>/<random>/<archive-stem>/
그런 다음 _unpack()을 호출하며, 이는 아카이브를 직접 다음으로 전달합니다:
shutil.unpack_archive()
TAR 아카이브의 경우, 이는 궁극적으로 tarfile.extractall()을 호출합니다.
Python < 3.14에서 기본 추출 동작은 fully_trusted이며, 이는 순회 멤버가 허용될 수 있음을 의미합니다.
예를 들어, 다음과 같은 아카이브 멤버는:
../../../some/other/dir/file
추출 디렉터리를 기준으로 작성되므로 이를 벗어날 수 있습니다.
fastcore에서는 다음 중 어느 것도 수행하지 않습니다:
filter="data"를 전달하지 않습니다... 경로 구성 요소를 거부하지 않습니다.untar_dir()는 shutil.unpack_archive()를 안전하고 샌드박스화된 아카이브 추출기인 것처럼 취급합니다.
그렇지 않습니다.
Python 표준 라이브러리 문서는 신뢰할 수 없는 아카이브를 추출하면 요청된 대상 외부에 파일이 생성될 수 있다고 경고하며, TAR 아카이브에 대해 안전한 추출 필터링을 권장합니다.
fastcore는 적절한 추출 필터를 전달하지도 않고, 지원하는 Python 버전에 대해 동등한 포함 가드를 구현하지도 않습니다.
또한 untar_dir() 호출자에게 이 보안에 민감한 동작에 대해 경고하지 않습니다.
TAR 멤버는 임의의 경로 문자열을 포함할 수 있습니다.
영향받는 Python 버전에서 tarfile.extractall()은 기본적으로 .. 순회 시퀀스를 자동으로 무력화하지 않습니다.
따라서 fastcore의 임시 추출 디렉터리를 기준으로 순회 멤버를 작성하는 것만으로도 해당 디렉터리를 벗어나 프로세스가 쓸 수 있는 모든 위치에 쓸 수 있습니다.
신뢰할 수 있는 기본 요소는 다음과 같은 상대 순회입니다:
../../../target/file
이것이 개념 증명에서 사용된 기법입니다.
위험한 입력은 개발자가 선택한 대상 경로가 아니라 아카이브 내용입니다.
아카이브는 다음과 같은 외부 또는 반신뢰 위치에서 자주 획득됩니다:
따라서 신뢰할 수 없거나 반신뢰 소스에서 아카이브를 다운로드한 후 untar_dir()을 사용하여 처리하는 모든 서비스나 도구가 도달 가능할 수 있습니다.
PoC에는 이 전달 경로를 시연하기 위해 공격자가 제어하는 HTTP 엔드포인트에서 조작된 아카이브를 제공하는 변형도 포함되어 있습니다.
성공적인 악용을 위해서는 다음이 필요합니다:
애플리케이션이 내용이 공격자의 영향을 받는 아카이브(업로드, 다운로드 또는 기타 신뢰할 수 없는 아카이브)에 대해 fastcore.xtras.untar_dir()을 호출합니다.
런타임이 Python < 3.14를 사용하거나, 안전한 TAR 추출 필터가 강제되지 않는 다른 구성입니다.
임의 파일 쓰기에서 코드 실행으로의 에스컬레이션을 위해서는 프로세스가 나중에 순회로 도달 가능한 위치에서 파일을 임포트하거나 로드합니다. 예를 들어:
임의 파일 쓰기 및 구성/데이터 수정은 조건 1과 2만 필요합니다.
poc_fastcore_cna_demo.py는 실제 fastcore.xtras.untar_dir() API를 호출합니다.
이 시연은 의도적으로 무해합니다.
PoC가 생성하는 모든 파일은 다음을 사용하여 지정된 단일 데모 디렉터리 내에 남아 있습니다:
--demo-root
PoC는 실제 시스템 파일을 수정하지 않으며 클라우드 서비스나 자격 증명에 접근하지 않습니다.
환경 세부 정보와 _unpack() 및 untar_dir()의 취약한 소스 코드를 출력합니다.
다음을 포함하는 데모 레이아웃을 생성합니다:
service_app/plugins/
다음을 생성합니다:
attacker_supplied_upload.tar
의도된 추출 루트 외부를 가리키도록 설계된 아카이브 멤버(순회 멤버 및 다음 포함)를 포함합니다:
service_app/plugins/startup_hook.py
def auto_extract_uploaded_archive(received_archive):
return untar_dir(
received_archive,
intended_root,
overwrite=True
)
파일이 의도된 추출 디렉터리 외부에 작성되었는지 확인합니다.
아카이브로 작성된 다음 파일을 임포트하여 서비스 재로드를 시뮬레이션합니다:
startup_hook.py
무해한 시작 훅은 다음을 생성합니다:
SERVICE_RELOAD_MARKER
이는 완전한 체인을 시연합니다:
Attacker-controlled archive
↓
Path traversal during extraction
↓
Arbitrary file write
↓
Write into importable / auto-loaded location
↓
Application loads attacker-controlled file
↓
Code execution
영향받는 패키지를 설치합니다:
pip install fastcore
이 문제는 다음을 통해 확인되었습니다:
fastcore 2.2.30
시연은 다음 중 하나에 대해 실행할 수 있습니다:
fastcore 사본--source를 사용하여 선택한 로컬로 추출된 소스 트리모든 PoC 쓰기는 --demo-root를 통해 지정된 디렉터리 내에 남아 있습니다.
이전 PoC 출력을 정리합니다:
python poc_fastcore_cna_demo.py --demo-root ./poc_fastcore --clean
시연을 실행합니다:
python poc_fastcore_cna_demo.py \
--demo-root ./poc_fastcore \
--source latest \
--no-pause
축약된 출력 예시:
fastcore version: 2.2.30
Outside marker exists after extraction? True
Is outside marker inside intended extraction root? False
Relative traversal marker exists after extraction? True
Is relative traversal marker inside intended extraction root? False
Service plugin file exists after extraction? True
Service reload marker exists? True
POC WORKED: fastcore extracted attacker-controlled tar members outside the intended root.
지원되는 Python 버전에서는 다음과 같은 안전한 추출 필터를 사용하십시오:
filter="data"
shutil.unpack_archive() 또는 해당 tarfile 추출 작업과 함께 사용합니다.
추출 전에 모든 아카이브 멤버를 확인해야 합니다.
다음을 거부하십시오:
..를 포함하는 경로링크 대상도 추출 전에 확인하고 검증해야 합니다.
작성 전에 모든 대상 경로를 확인하고 의도된 추출 루트 아래에 남아 있는지 검증하십시오.
개념적으로:
resolved_member_path
↓
must remain inside
↓
resolved_extraction_root
확인된 대상이 추출 루트를 벗어나면 추출이 실패해야 합니다.
회귀 테스트는 최소한 다음을 포함해야 합니다:
../ traversal
absolute paths
Windows drive-letter paths
UNC paths
symbolic links
hard links
untar_dir()이 신뢰할 수 없는 아카이브를 안전하게 처리하도록 의도되었는지 명확히 문서화하십시오.
안전하지 않은 추출이 의도적으로 지원되는 경우에도 안전한 동작이 기본값이어야 합니다.
안전하지 않은 동작은 아카이브 내용을 조용히 신뢰하는 대신 명시적 옵트인이 필요해야 합니다.
패키지 수준 수정이 릴리스될 때까지:
untar_dir()에 직접 전달하지 마십시오.근본적인 기술적 결함은 아카이브 경로 순회로 인한 임의 파일 쓰기 취약점입니다.
그러나 최종 심각도는 배포 환경과 untar_dir()이 노출되는 방식에 따라 달라집니다.
대표적인 벡터는 다음과 같을 수 있습니다:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
결과:
9.8 — Critical
악용을 위해 개발자가 수동으로 아카이브를 다운로드하고 추출해야 하는 경우, 사용자 상호 작용과 공격 복잡성이 더 높을 수 있습니다.
따라서 결과 CVSS 점수는 실질적으로 낮아집니다.
문제를 평가할 때 두 가지 중요한 요소를 고려해야 합니다.
이것은 다음과 관련된 오래 알려진 안전하지 않은 TAR 추출 취약점 클래스의 인스턴스입니다:
CVE-2007-4559
최신 Python 릴리스는 더 안전한 아카이브 추출 동작을 도입했습니다.
Python 3.14는 안전한 data 추출 필터를 기본값으로 만듭니다.
따라서 주요 영향 환경은 Python < 3.14입니다.
그러나 이러한 런타임은 여전히 널리 배포되어 있습니다.
이 취약점은 호출자가 내용이 공격자에 의해 제어되거나 신뢰할 수 없는 아카이브를 untar_dir()에 제공할 때 악용 가능해집니다.
따라서 이 보고서는 아카이브의 내용을 신뢰할 수 없는 보안 경계로 취급합니다.
견고한 아카이브 추출 헬퍼는 아카이브가 어떻게 획득되었든 안전하게 실패해야 합니다.
아래 자리 표시자 날짜를 실제 공개 날짜로 교체하십시오.
YYYY-MM-DD — 유지 관리자에게 취약점 보고.YYYY-MM-DD — 공급업체 응답 / 확인 / 무응답.2.2.30)에서 여전히 미수정 확인; 추출 코드는 변경되지 않음.Rahul Karne이 발견하고 보고했습니다.
fastcore untar_dir() 문서
https://fastcore.fast.ai/xtras.html
fastcore xtras.py 소스
https://github.com/AnswerDotAI/fastcore/blob/main/fastcore/xtras.py
PyPI의 fastcore
https://pypi.org/project/fastcore/
Python shutil.unpack_archive() 문서
https://docs.python.org/3/library/shutil.html#shutil.unpack_archive
Python tarfile 추출 필터
https://docs.python.org/3/library/tarfile.html#extraction-filters
PEP 706 — tarfile.extractall용 필터
https://peps.python.org/pep-0706/
CWE-22 — 경로명의 제한된 디렉터리 제한 부적절
https://cwe.mitre.org/data/definitions/22.html
CVE-2007-4559 — 안전하지 않은 TAR 추출 취약점 클래스
https://nvd.nist.gov/vuln/detail/CVE-2007-4559
이 저장소는 조정된 공개 보안 발견을 문서화하고 무해하고 자체 포함된 개념 증명을 제공합니다.
PoC는 사용자가 지정한 --demo-root 디렉터리 내에만 쓰며 파괴적인 작업을 수행하지 않습니다.
시연에 포함된 모든 네트워크 기능은 선택적 로컬 시연으로 제한됩니다.
이 자료는 방어적 보안 연구 및 교육 목적으로 제공됩니다.
미디어 문의: [email protected]. 전체 PoC(공격자 서버, 순회 아카이브, 피해자 애플리케이션) 및 추가 기술 세부 사항은 요청 시 제공 가능합니다.