Secure Steady
プロトタイプ汚染 - Prototype Pollution の使い方・オプション・サンプル

プロトタイプ汚染 - Prototype Pollution

JavaScript のプロトタイプチェーンを悪用し、オブジェクトのプロパティを改ざんする攻撃。npm パッケージ経由で発生しやすい。

概念図

Prototype Pollution diagram

攻撃シナリオ

ディープマージ関数を悪用した Prototype Pollution

bash
// 脆弱なディープマージ関数
function merge(target, source) {
  for (const key in source) {
    if (typeof source[key] === "object") {
      target[key] = merge(target[key] || {}, source[key]);
    } else {
      target[key] = source[key];
    }
  }
  return target;
}

// 攻撃ペイロード
merge({}, JSON.parse('{"__proto__":{"isAdmin":true}}'));

// すべてのオブジェクトに isAdmin=true が追加される
console.log({}.isAdmin); // true

URL パラメータ経由の攻撃と安全なオブジェクト生成

bash
// URL パラメータ経由の攻撃
// ?__proto__[isAdmin]=true
// qs ライブラリの古いバージョンなどで発生

// 安全な実装(Object.create(null) を使う)
const safeObj = Object.create(null);
safeObj.key = "value";
// → プロトタイプチェーンを持たないため汚染されない

攻撃の仕組み

JavaScript のオブジェクトは __proto__ プロパティを通じてプロトタイプチェーンにアクセスできる。

オブジェクトのマージやクローン処理で __proto__ キーを適切にフィルタリングしていない場合、Object.prototype にプロパティを追加できてしまう。

汚染されたプロパティはアプリケーション内の全オブジェクトに影響するため、以下のような深刻な被害につながる:

  • 認証バイパス(isAdmin プロパティの注入)
  • XSS の発生(テンプレートエンジンの動作を改ざん)
  • DoS(アプリケーションのクラッシュ)
  • リモートコード実行(サーバーサイド Node.js 環境で)

対策

  • __proto__ キーのフィルタリング: マージ・クローン処理で __proto__, constructor, prototype を除外する
  • Object.create(null) の使用: プロトタイプチェーンを持たないオブジェクトを利用する
  • Map の使用: キーバリューストアには Object の代わりに Map を使う
  • Object.freeze: Object.freeze(Object.prototype) でプロトタイプを凍結する(互換性に注意)
  • 依存パッケージの更新: lodash の merge、jQuery の extend 等は過去に脆弱性が報告されており、最新版に更新する

関連トピック