Readable Passwords at Rest — JavaScript Bug Hunt
Modelled on Facebook's 2019 disclosure: hundreds of millions of user passwords had been stored in readable form in internal systems, searchable by thousands…
- Language: JavaScript
- Layer: Database
- Difficulty: Medium
- Concepts: Security, Hashing
- Modelled on: Facebook · 2019
- Visible tests: the right password verifies; the stored record holds no readable password
- Reward: 50 XP for a complete fix
Briefing
Modelled on Facebook's 2019 disclosure: hundreds of millions of user passwords had been stored in readable form in internal systems, searchable by thousands of employees. The passwords had never been hashed on the path that wrote them.
accounts.js stores whatever it is handed and compares it directly.
Fix createAccount and verify so passwords are stored only as salted hashes.
Bug report
BUG-FB2019 · Priority: Critical · Reported by: security
createAccount(store, username, password) must write a record shaped { salt, hash } — with no field anywhere holding the password itself. verify(store, username, password) must return true only for the right password.
Observed: the stored record contains a password field in plain text, and verify compares strings directly.
Logs
[store] record kai = {"password":"hunter2"}
[audit] 2000 internal accounts could read the users tableThe code as shipped
src/accounts/accounts.js (editable)
var crypto = require("./crypto");
exports.createAccount = function (store, username, password) {
store[username] = { password: password };
return true;
};
exports.verify = function (store, username, password) {
var record = store[username];
if (!record) return false;
return record.password === password;
};
Read-only context: src/accounts/crypto.js.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.