Prototype Pollution
外部からJavaScriptのオブジェクトのプロトタイプを汚染する攻撃
オブジェクトのプロパティアクセスに影響を与えることができる
プロトタイプとは?
JavaScriptにおける継承を実現する機構のこと
オブジェクト指向言語で言えば親クラスのようなもの
詳しくはMDNを読んでください
Object のプロトタイプ https://developer.mozilla.org/ja/docs/Learn/JavaScript/Objects/Object_prototypes
継承とプロトタイプチェーン https://developer.mozilla.org/ja/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
重要なこと
オブジェクトのプロトタイプは、obj.__proto__で取得できる
標準で非推奨の機能なので、将来削除される可能性がある
JavaScriptのプロパティアクセスは、プロトタイプに対して該当するプロパティがあるかどうか再帰的に調べて、あればその値を、無ければundefinedを返すようになっている
A -> B -> CというプロトタイプチェーンがあるときにA.fooにアクセスした場合
Aにfooというプロパティがあれば、それを返す
Aにfooというプロパティが無ければ、AのプロトタイプのBにfooというプロパティがあるか調べる
Bにfooがあればそれを、無ければBのプロトタイプのCを調べ...
基本的にオブジェクトはすべてObject.prototypeを継承している
NumberもStringもArrayもFunctionもObject.prototypeをプロトタイプチェーンに持つ
JavaScriptのプロパティアクセスはドットでも添字でもアクセスできる
a["b"]["c"]とa.b.cは等価
a["__proto__"]でプロトタイプにアクセスできる
Prototype Pollutionとは?
プロトタイプのプロパティに対して悪意のある書き込みを行い、そのオブジェクトをプロトタイプに持つ全てのオブジェクトのプロパティアクセスに対して影響を与える攻撃
obj[A][B] = Cのような処理があり、攻撃者がA,B,Cを操作できるとき典型的なPrototype Pollutionの脆弱性が生まれる
code:poc.js
const obj = {}; // プロトタイプチェーンは obj => Object.prototype => null
// 攻撃者がObject.prototype.pollutedに書き込みを行う
obj"__proto__""polluted" = "pwned";
// 別のオブジェクトを作成する
const obj2 = {}; // プロトタイプチェーンは obj2 => Object.prototype => null
// obj"__proto__" === obj2"__proto__" なので obj2.__proto__.polluted も"pwned"になる
console.log(obj2.polluted); // => pwned
上書きできるのは元のオブジェクトで定義されていないプロパティだけ
code:poc.js
const obj = {hoge: "original"}; // {hoge: "original"} => Object.prototype => null
obj"__proto__""hoge" = "pwned";
// objにhogeプロパティが存在するため、プロトタイプにさかのぼらずにobj.hogeを出力する
console.log(obj.hoge) // => "original";
定義されてないプロパティを上書きするだけで脆弱性になるの?
危険なオプションを有効にしたり、外部からの書き込みが想定されていない部分に書き込んだりすることで攻撃につなげたりできる
CVE-2019-7609 https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/
KibanaのPrototype PollutionによるRemote Code Execution
対策
Object.prototype.hasOwnPropertyを用いて上書きするプロパティが自分で定義したものか確認する
obj = {a: 1}のとき
Object.prototype.hasOwnProperty.call(obj, "a") === true
Object.prototype.hasOwnProperty.call(obj, "toString") === false (objで定義したものではないので)
これを使ってobj[A] = Bの前にAをチェックする
{}ではなくObject.create(null)を利用する
Object.create(null)とするとプロトタイプを持たない(プロトタイプがnullの)オブジェクトを作成できる
プロトタイプを持たないので、Object.prototypeなどを汚染できない
オブジェクトの代わりにnew Map()を使えないか考える
Map https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Map
攻撃テクニック
obj.__proto__以外にもobj.constructor.prototypeでプロトタイプにアクセスできる
__proto__を弾くだけでは不十分
Gadgetを探す
一般に適用できるテクニックはないので、問題ごとにGadgetを探す必要があることが多い
既存のCVEや既知のgadgetを使うときもある
ソースコードやライブラリを調べてPrototype Pollutionで悪用できそうな未定義のプロパティを探す
if (A.B) { ~ }や、if (A[B]) { ~ } // Bは操作可能が狙い目
過去の例
Asian Cyber Security Challange 2021 - Cowsay as a Service
https://nanimokangaeteinai.hateblo.jp/entry/2021/09/20/053533#Web-370-Cowsay-as-a-Service-33-solves
child_process.spawnSyncのoptions.shellを汚染して任意コード実行
CakeCTF 2022 - Panda Memo
https://nanimokangaeteinai.hateblo.jp/entry/2022/09/09/235615#web-289-Panda-Memo-9-solves
テンプレートエンジンmustacheのキャッシュの汚染
MapleCTF 2022 - Viene Library
https://jamvie.net/posts/2022/09/maplectf-2022-vies-challenges/#viene-library-11-solves
node-fetchのX-HTTP-Method-Overrideを汚染してMethodを上書き
Balsn CTF 2022 - 2linenodejs https://gist.github.com/ginoah/e723a1babffae01ffa5149121776648c
requireの内部を汚染してRemote Code Execution
AST Injection https://blog.p6.is/AST-Injection/
テンプレートエンジンのASTを汚染してRemote Code Executionにつなげる手法
client-side-prototype-pollution https://github.com/BlackFan/client-side-prototype-pollution
参加者ごとにインスタンスが提供されたり、毎回インスタンスが破棄される問題はPrototype Pollution (?)
Prototype Pollutionは性質上環境を永続的に汚染するので、複数の参加者がひとつのサーバーを共有する問題を壊れないように作るのは難しい
そのためPrototype Pollutionの問題はインスタンスは破棄されたり分けられたりすることが多いので、その形式ならPrototype Pollutionだろうというジンクス
もう古いかも
資料
client-side-prototype-pollution https://github.com/BlackFan/client-side-prototype-pollution
クライアントサイドで発見されたPrototype Pollutionと悪用できる汚染先
Node.jsにおけるプロトタイプ汚染攻撃とは何か https://jovi0608.hatenablog.com/entry/2018/10/19/083725
プロトタイプ汚染周りの提案と primordials.js https://zenn.dev/petamoriken/articles/2f6511742d7907
CTFのWebセキュリティにおけるJavaScript,nodejsまとめ(Prototype pollution, 難読化)
https://blog.hamayanhamayan.com/entry/2021/12/18/132420
【1分見て】実例から学ぶprototype pollution【kurenaif勉強日記】 https://www.youtube.com/watch?v=qP8ihBctMeY
New ways to alert: prototype pollution http://archive.volgactf.ru/volgactf_2021/slides/VolgaCTF_2021_Stupin_Bobrov.pdf
Prototype pollutionの攻撃手法に関する発表のスライド