見出し画像

#96 Prototype Pollution

 JavaScriptでよく取りあげられる脆弱性といえば、XSSですが、Prototype Pollutionも同様に問題を引き起こす可能性があります。JavaScriptは、オブジェクトをベースとした言語ですが、そのオブジェクトのもととなるプロトタイプを改変することで想定外の挙動を引き起こすことができてしまいます。
 少し実験してみましょう。


プロトタイプ汚染

 環境は、前回構築したXSSLabです。

プロパティの汚染

まずはシンプルにプロパティを汚染してみます。

var a = {
  test: "test1"
}

console.log(a.pollution);
Object.prototype.pollution = "h4x";
console.log(a.pollution);

上記のように、プロトタイプのプロパティを書き換えることで、aオブジェクトに影響を及ぼすことができます。


var a = {
  test: "test1"
}

console.log(a.test);
Object.prototype.test = "h4x";
console.log(a.test);

aオブジェクトで定義しているプロパティは、上書きできませんでした。オブジェクト→プロトタイプの順番でプロパティを検索しているのでしょうか。


メソッドの汚染

 もちろん、オブジェクトが持っているメソッドも汚染できます。

var a = {
  test: "test1"
}

Object.prototype.toString = function() {
  console.log("Hacked!");
}

a.toString();



__proto__による汚染

 汚染は、__proto__プロパティによっても可能です。別のオブジェクトの__proto__からプロトタイプを汚染して、ターゲットオブジェクトに影響を与えることができます。

var a = {
  test: "test1"
}

console.log(a.pollution);

var b = {
  prop: "prop",
}
b.__proto__.pollution = "h4x";

console.log(a.pollution);



JSON.parseによる汚染

 APIなどで受け取ったJSON文字列をパースする際に、プロトタイプが汚染される場合があります。例えば、下記のようにJSONに__proto__プロパティが含まれていると、オブジェクトにパースされると同時にプロトタイプが汚染されます。

{
  "prop1": "test1",
  "prop2": "test2",
  "__proto__": {
    "pollution": "h4x"
  }
}

影響

 さて、ここまでプロトタイプ汚染の挙動を確認してきましたが、実際に悪用された場合、どのような影響があるでしょうか?

 ブラウザでプロトタイプ汚染が発生する場合、影響はXSSと同程度だと思われます。実装にもよりますが、任意のJavaScriptを実行できるため、認証情報の窃取や別サイトへの誘導などの攻撃が考えられます。
 Node.jsなどサーバーサイドで発生した場合は、より深刻な影響を及ぼすかもしれません。典型的な例としては、下記のように認証をバイパスすることができます。

var user = {
}

Object.prototype.isAdmin = true;

if (user.isAdmin) {
  console.log("You are Admin");
} else {
  console.log("Not admin");
}


いずれにせよ、想定外の挙動になる可能性があるので注意が必要です。


対策

 対策を調べたところ、プロトタイプを変更できないように固定する方法や、Object.create(null)でプロトタイプのないオブジェクトを生成する方法などが紹介されていました。汚染が発生する可能性があるのは、ユーザー入力に__proto__などの特殊な文字列が含まれている場合が大半だと考えられるので、入力値チェックが有効です。


まとめ

 CTFでもときどき出題されるPrototype Pollutionですが、Web開発者でも知らない方は多いのではと思います。私も知りませんでした。気をつけていても思わずやってしまいそうですが、条件によっては大きな傷になってしまいます。今回はブラウザのみで実験しましたが、Node.jsの環境も作って理解を深めたいと思います!


EOF

この記事が気に入ったらサポートをしてみませんか?