犬のプロフィールを作成できるWebアプリを公開しました。

ゴール
session.username=”admin”の状態にして/admin にアクセスするとフラグが得られる。
Adminは最初から存在しているがパスワードが不明
let users = {
admin: {
password: crypto.randomBytes(16).toString('hex'),
avatar: '🍭',
description: 'I am admin!'
}
};
getFilteredProfile()
const DEFAULT_PROFILE = { avatar: '🐶', description: 'bow wow!' };
function getFilteredProfile(username) {
const profile = users[username];
const filteredProfile = Object.entries(profile).filter(([k]) => {
return k in DEFAULT_PROFILE;
});
return Object.fromEntries(filteredProfile);
}
ユーザ名を与えてDEFAULT_PROFILEのキー(avatar/description)を返すように見える。
DEFAULT_PROFILEにpasswordを生やせると嬉しい。
/register
app.post('/register', async (req, res) => {
const { username, password, profile } = req.body;
if (users.hasOwnProperty(username)) { ... } // 既存チェック
users[username] ??= { password, ...DEFAULT_PROFILE };
for (const key in profile) {
users[username][key] = profile[key];
}
req.session.username = username;
return res.send({ 'message': 'ok' });
});
ここでPrototype Pollutionできる。
username="__proto__" を入れると
users["__proto__"] は Object.prototype を指す。
??=(Nullishのみ代入)は発生せず、profile に { "password": true } を設定すると
users["proto"]["password"] = true → Object.prototype.password = true となる。