以下の内容はhttps://cysec148.hatenablog.com/entry/2025/09/17/060451より取得しました。


JSONによるPrototype Pollution(プロトタイプ汚染)

Hello there, ('ω')ノ

🧨 攻撃に使われる悪意あるJSON

攻撃者が以下のようなJSONを送信したとします:

{
  "__proto__": {
    "evilProperty": "payload"
  }
}

例えば、WebSocketのメッセージやAJAXリクエストなどでサーバやフロントエンドに送信されることがあります。


🤖 JavaScriptでどうなる?

これを JSON.parse() でパースすると:

const objectFromJson = JSON.parse('{"__proto__": {"evilProperty": "payload"}}');

このとき objectFromJson の中身は:

{
  "__proto__": {
    "evilProperty": "payload"
  }
}

つまり、proto は文字列としてそのままプロパティになるということ。


💡 なにが面白いのか?比較してみよう

const literalObj = { __proto__: { evilProperty: 'payload' } };
const jsonObj = JSON.parse('{"__proto__": {"evilProperty": "payload"}}');

console.log(literalObj.hasOwnProperty('__proto__')); // false(プロトタイプを書き換えた)
console.log(jsonObj.hasOwnProperty('__proto__'));    // true(単なるキーとして扱われた)

この結果からわかること:

作り方 __proto__の扱い
オブジェクトリテラル {} 特別なキーとしてプロトタイプを変更
JSON.parse() 普通のプロパティとして扱われる

ここまでは安全そうに見えるかもしれません。


😱 問題は「その後のマージ処理」にある!

次のようにマージされると危険です:

merge(target, JSON.parse('{"__proto__": {"evilProperty": "payload"}}'));

この merge() 関数が以前紹介したような再帰的マージだった場合、次のような操作が実行されてしまいます:

target.__proto__.evilProperty = 'payload';

つまり、結局 Object.prototype.evilProperty = "payload" という形でプロトタイプが汚染されるのです。


💥 なぜ危険なのか?再確認

  • JSON.parse() 自体は安全に見える
  • しかし、その後の処理(マージ)が危険
  • 結果的に、全てのオブジェクトが evilProperty を継承してしまう

🧠 理解のポイント

ポイント 解説
JSON.parse() 入力に含まれる__proto__を単なる文字列キーとして扱う
問題点 それを merge() などでマージするとプロトタイプに代入されてしまう
被害 全オブジェクトに evilProperty が見えるようになる
攻撃対象 アプリやライブラリが参照する重要プロパティ(例:isAdmin)など

✅ 対策まとめ

  1. __proto__, constructor, prototype のような危険なキーをブラックリスト化
  2. サニタイズ処理を必ず実装する(入力前/マージ前)
  3. 安全なマージライブラリを使う(例:deepmergeなど)
  4. JSONから生成したオブジェクトはそのまま信頼しない

🔚 おわりに

JSON.parse() は一見安全に見えますが、その後の処理次第で重大なセキュリティリスクにつながります。特に、ユーザーから受け取ったデータを他のオブジェクトに「マージ」するようなコードには十分注意が必要です。

Best regards, (^^ゞ




以上の内容はhttps://cysec148.hatenablog.com/entry/2025/09/17/060451より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14