
CVE-2025-8088
면책 조항: 이 콘텐츠는 교육 및 연구 목적으로만 제공됩니다. 이 정보를 악의적인 활동에 사용하지 마십시오.
오늘은 CVE-2025-8088로 추적되는 흥미로운 경로 탐색 취약점을 심층 분석합니다. 이 취약점은 피해자가 특수하게 조작된 RAR 아카이브를 추출할 때 공격자가 임의의 파일을 피해자 시스템의 모든 위치에 쓸 수 있게 합니다. 이 특정 익스플로잇이 흥미로운 점은 사용자가 아카이브를 추출하는 위치에 관계없이 성공적인 페이로드 전달을 보장하기 위한 '샷건' 접근 방식입니다.
이 게시물은 제공된 Python PoC(Proof-of-Concept)에서 악성 .rar 파일을 제작하는 데 사용된 기술을 분석합니다.
이 PoC의 최종 목표는 고전적이면서도 효과적입니다: 지속성입니다. 경로 탐색 취약점을 악용하여 익스플로잇은 페이로드(payload.bat)를 Windows 시작 폴더(AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup)에 드롭하는 것을 목표로 합니다. 여기에 배치된 모든 실행 파일이나 스크립트는 사용자가 다음에 로그인할 때 자동으로 실행되어 공격자에게 지속적인 액세스 권한을 부여합니다.
Python 스크립트는 최종 exploit.rar를 구축하기 위한 다단계 프로세스를 자동화합니다. 그 논리를 살펴보겠습니다.
스크립트가 가장 먼저 하는 일은 구성 요소를 준비하는 것입니다:
payload.bat라는 간단한 배치 파일이 생성됩니다. 이것이 피해자의 시스템에 드롭하려는 악성 파일입니다.PAYLOAD = "@echo off\necho Payload executed!\npause\n"
file1.txt, file2.txt 등)을 생성합니다. 이 파일들은 두 가지 목적을 제공합니다: 아카이브를 합법적으로 보이게 하며, 더 중요한 것은 숨겨진 페이로드의 운반체 역할을 합니다.def create_files() -> Tuple[List[Path], Path]:
# ...
for i in range(NUM_DEPTHS):
decoy = Path(f"{DECOY_FILE_PREFIX}{i+1}.txt")
" X " * 200)로 구성된 긴 문자열이 정의됩니다. 이 자리 표시자는 아카이브의 메타데이터에 포함되었다가 나중에 악성 경로로 대체됩니다.이것은 기술의 핵심 부분입니다. 스크립트는 경로 탐색 경로로 파일 이름을 지정하는 대신 **대체 데이터 스트림(ADS)**이라는 NTFS 파일 시스템의 기능을 사용합니다. ADS를 사용하면 기존 파일 내에 데이터를 '숨길' 수 있습니다.
스크립트는 payload.bat를 각 미끼 파일에 ADS로 첨부합니다. 이 스트림의 이름이 자리 표시자가 사용되는 곳입니다. 본질적으로 파일 시스템에 다음과 같은 파일 경로를 생성합니다:
file1.txt:XXXXXXXXXXXXXXXXXXXX...
이제 payload.bat의 콘텐츠가 file1.txt 내부에 비밀리에 저장됩니다.
def attach_ads(decoy: Path, placeholder: str):
"""Attach payload to decoy as Alternate Data Stream"""
ads_path = f"{decoy}:{placeholder}"
with open(ads_path, "wb") as f:
f.write(Path("payload.bat").read_bytes())
다음으로 스크립트는 시스템에서 Rar.exe 명령줄 도구를 찾아 합법적인 기본 아카이브(base.rar)를 만드는 데 사용합니다. 이 아카이브에는 모든 미끼 파일이 포함되어 있으며, 이제 해당 파일은 대체 데이터 스트림에 페이로드를 비밀리에 담고 있습니다.
이 시점에서 base.rar는 완전히 유효하고 악의적이지 않은 아카이브입니다. WinRAR은 문제없이 추출할 수 있으며, 길고 이상한 ADS 이름을 가진 미끼 파일을 생성합니다.
def create_base_rar(rar_exe: str, decoys: List[Path]) -> Path:
# ...
subprocess.run(
f'"{rar_exe}" a -ep -os "{base_rar}" {files}',
# ...
)
여기서 익스플로잇이 영리하고 탄력적으로 변합니다. 공격자는 피해자가 아카이브를 어디에 추출할지 알 수 없습니다. C:\Users\victim\Downloads일까요? C:\? D:\Temp?
이러한 불확실성을 극복하기 위해 스크립트는 각각 다른 깊이를 가진 다양한 경로 탐색 문자열 목록을 생성합니다:
..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.bat..\..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.bat..\..\..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.bat아이디어는 여러 깊이를 제공함으로써 그중 적어도 하나가 추출 디렉터리에서 파일 시스템의 루트(예: C:\)로 다시 이동한 다음 대상 시작 폴더로 성공적으로 이동할 것이라는 점입니다.
def build_relative_paths() -> List[str]:
"""Generate paths with different traversal depths"""
paths = []
for depth in range(1, NUM_DEPTHS + 1):
paths.append(("..\\" * depth) + RELATIVE_DROP_PATH)
return paths
이것이 익스플로잇의 핵심입니다. 스크립트는 base.rar를 바이너리 모드로 열고 수술을 수행합니다.
아카이브의 내부 구조를 반복하면서 각 파일(file1.txt, file2.txt 등)의 헤더를 찾습니다. 각 헤더 내에서 자리 표시자 ADS 이름(:XXXXXXXXXXXXXXXXXXXX...)을 찾아 이전 단계에서 생성된 악성 경로 탐색 경로 중 하나로 바꿉니다.
file1.txt의 헤더는 ..\ 경로를 얻습니다.file2.txt의 헤더는 ..\..\ 경로를 얻습니다.def patch_rar(base_rar: Path, placeholder: str, relative_paths: List[str]) -> Path:
# ...
while pos + 4 <= len(data) and current_file_index < len(target_paths_utf8):
# ...
# Find the placeholder and replace it with the target path
c = patch_placeholder_in_header(hdr, placeholder_utf8, target_utf8)
# ...
단순히 헤더 데이터를 변경하면 아카이브가 손상됩니다. WinRAR은 CRC32 체크섬을 사용하여 각 헤더 블록의 무결성을 확인합니다. 체크섬이 헤더 콘텐츠와 일치하지 않으면 오류가 발생합니다.
PoC는 이를 예상합니다. 악성 경로로 헤더를 패치한 후 수정된 헤더 블록 전체에 대한 올바른 CRC32 체크섬을 다시 계산하고 새 체크섬을 파일에 다시 씁니다. 이렇게 하면 변조된 아카이브가 WinRAR에 완벽하게 유효한 것으로 보입니다.
def rebuild_all_header_crc(buf: bytearray) -> int:
"""Recalculate CRC checksums for all headers"""
# ...
while pos + 4 <= len(buf):
# ...
# Calculate CRC for the header region
region = buf[block_start + 4:header_end]
crc = zlib.crc32(region) & 0xFFFFFFFF
# Write the new CRC back into the buffer
struct.pack_into("<I", buf, block_start, crc)
# ...