Igual pero Distinto
Bypass de auth por coerción de tipos
// OBJETIVO
Entrá como admin sin conocer la contraseña, aprovechando cómo JavaScript coacciona tipos en comparaciones flojas.
// ZONA DE ATAQUE
Corre en un iframe de origen opaco: no puede leer este sitio ni tu progreso. Cuando logres el exploit, la flag aparece dentro de la app — copiala y verificala.
// CONSULTÁ
Pistas
Código vulnerable
El handler compara con igualdad floja y confía en el tipo del body:
app.post('/api/login', (req, res) => {
const { user, remember } = req.body;
const account = db.find(user); // admin tiene rememberToken = 0
// "recordarme": si el token coincide, saltea la contraseña
if (account && remember == account.rememberToken) {
return res.json({ ok: true, flag: FLAG });
}
// ...verificación normal de contraseña
});
Como el body es JSON, remember puede llegar como false, 0, [] o "", y
== los coacciona: false == 0, [] == 0 y "" == 0 son todos true. Mandando
{"user":"admin","remember":false} la comparación pasa sin conocer nada.
Remediación
Compará con === y validá el tipo antes de comparar:
- if (account && remember == account.rememberToken) {
+ if (
+ account &&
+ typeof remember === 'string' &&
+ remember.length > 0 &&
+ remember === account.rememberToken
+ ) {
return res.json({ ok: true, flag: FLAG });
}
Por qué funciona: === no coacciona, así que false, 0 o [] dejan de ser
iguales a un token string. Exigir typeof === 'string' y longitud mínima cierra el
resto de los valores raros que un cliente puede inyectar por JSON.