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


JavaScriptのプロトタイプ継承の仕組み

Hello there, ('ω')ノ

🔁 危険な関数

まず、以下の関数は「2つのオブジェクトをマージ(結合)する処理」です:

function merge(target, source) {
  for (let key in source) {
    if (typeof source[key] === 'object') {
      if (!target[key]) target[key] = {};
      merge(target[key], source[key]);
    } else {
      target[key] = source[key];
    }
  }
}

ここでは target に対して source を上書きしていきます。 再帰的に処理するため、source の中にオブジェクトがあれば深い階層までコピーされます。


🧪 ユーザー入力の例

この関数に次のような悪意のあるユーザー入力が渡されたとします:

{
  "__proto__": {
    "isAdmin": true
  }
}

これをJavaScriptで渡すと:

merge({}, JSON.parse('{"__proto__": {"isAdmin": true}}'));

⚠ なにが起こるのか?

JavaScriptでは、すべてのオブジェクトはObject.prototypeを継承しています。

そして __proto__ というプロパティを使うと、そのオブジェクトの「親」を書き換えることができるのです。

ここがポイント!

merge(){ "__proto__": { "isAdmin": true } } をマージすると、target.__proto__ = { isAdmin: true } のように振る舞います。

つまり、最終的には Object.prototype.isAdmin = true と同じ状態になるのです。


🧨 その結果どうなる?

たとえば、以下のような空のオブジェクトを作っても:

let user = {};
console.log(user.isAdmin); // true が表示される!

userオブジェクトにはisAdminプロパティは存在しません。 でも、プロトタイプが汚染されているので、継承によって isAdmin が存在しているように見えるのです。


💡 図解で理解(イメージ)

[Object.prototype] ← { isAdmin: true } ← 書き換えられた親
         ↑
      [user] ← 本来は何も持っていないオブジェクト

このように、「全てのオブジェクトの親」が書き換えられるため、新しく作ったどんなオブジェクトにも isAdmin: true が見えてしまうわけです。


✅ まとめ

項目 内容
__proto__ オブジェクトの親(プロトタイプ)を指定する特別なプロパティ
なぜ危険? 書き換えると全オブジェクトに影響する
merge()で発生する理由 再帰的にコピーする際、キーをフィルタしていないため __proto__ が素通りしてしまう
結果 Object.prototypeが汚染され、全てのオブジェクトに偽のプロパティが追加されたように見える

Best regards, (^^ゞ




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

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