NodeJS - __proto__ & prototype Pollution
JavaScriptのオブジェクト
JavaScriptのオブジェクトは、プロパティとして知られるキーと値のペアのコレクションです。オブジェクトは、Object.create
を使用して、空のオブジェクトを生成するために引数としてnull
を使用して作成できます。このメソッドを使用すると、継承されたプロパティを持たないオブジェクトを作成できます。
JavaScriptにおける関数とクラス
JavaScriptでは、関数とクラスは密接に関連しており、関数はしばしばクラスのコンストラクタとして機能します。JavaScriptにはネイティブなクラスサポートがないにもかかわらず、コンストラクタはクラスの動作をエミュレートすることができます。
JavaScriptにおけるプロトタイプ
JavaScriptでは、実行時にプロトタイプ属性の変更、追加、または削除が可能です。この柔軟性により、クラスの機能を動的に拡張することができます。
toString
やvalueOf
などの関数は変更して動作を変更することができ、JavaScriptのプロトタイプシステムの適応性を示すことができます。
継承
プロトタイプベースのプログラミングでは、プロパティ/メソッドはクラスからオブジェクトに継承されます。これらのクラスは、他のクラスのインスタンスにプロパティ/メソッドを追加するか、空のオブジェクトにプロパティ/メソッドを追加することで作成されます。
他のオブジェクトのプロトタイプとして機能するオブジェクト(たとえばmyPersonObj
など)にプロパティが追加されると、継承するオブジェクトはこの新しいプロパティにアクセスできます。ただし、このプロパティは明示的に呼び出されない限り、自動的に表示されません。
__proto__の汚染
JavaScriptにおけるプロトタイプ汚染の探索
JavaScriptオブジェクトはキーと値のペアで定義され、JavaScriptオブジェクトプロトタイプから継承されます。これは、Objectプロトタイプを変更することで環境内のすべてのオブジェクトに影響を与える可能性があることを意味します。
別の例を使用して説明してみましょう:
アクセス可能なObjectプロトタイプは次の通りです:
以下は、JavaScriptのすべてのオブジェクトがこれらの新しいプロパティを継承するように、Objectプロトタイプにプロパティを追加することによって実現されます:
プロトタイプ汚染
__proto__
の使用が制限されているシナリオでは、関数のプロトタイプを変更することが代替手段となります:
これは、Vehicle
コンストラクタから作成されたオブジェクトにのみ影響を与え、beep
、hasWheels
、honk
、isElectric
プロパティを付与します。
JavaScriptオブジェクト全体に影響を与えるための2つの方法は次のとおりです:
Object.prototype
を直接汚染する:
よく使用される構造のコンストラクタのプロトタイプを汚染する:
After these operations, every JavaScript object can execute goodbye
and greet
methods.
他のオブジェクトを汚染する
クラスからObject.prototypeへ
特定のオブジェクトを汚染し、Object.prototype
に到達する必要があるシナリオでは、次のようなコードを使用してそれを検索できます。
配列要素の汚染
JSのオブジェクトの属性を汚染できるように、配列を汚染する権限がある場合、配列の値を汚染することもできます。アクセス可能なインデックスによって(値を上書きすることはできないため、書き込まれていないがどこかで使用されているインデックスを汚染する必要があります)。
Html要素の汚染
JSを使用してHTML要素を生成する際に、innerHTML
属性を上書きして任意のHTMLコードを書き込むことが可能です。この解説と例を参考にしました。
Examples
Basic Example
プロトタイプ汚染は、アプリケーション内の欠陥によってObject.prototype
のプロパティを上書きできるようにすることで発生します。これは、ほとんどのオブジェクトがObject.prototype
からプロパティを派生させるため、オブジェクトのプロパティを上書きできることを意味します。
最も簡単な例は、チェックされるオブジェクトの未定義の属性に値を追加することです。
もし属性 admin
が未定義の場合、PP を悪用して次のように True に設定することが可能です:
このメカニズムは、特定の入力を攻撃者が制御できる場合、プロパティを操作してアプリケーション内のすべてのオブジェクトのプロトタイプを変更できるようにすることに関わっています。この操作は通常、__proto__
プロパティを設定することを含みます。JavaScriptでは、これはオブジェクトのプロトタイプを直接変更することと同義です。
この攻撃を成功させるための条件は、特定の研究で概説されており、次のようになります:
再帰マージを実行する。
パスに基づいてプロパティを定義する。
オブジェクトをクローンする。
関数の上書き
Proto Pollution to RCE
pagePrototype Pollution to RCEその他のペイロード:
クライアントサイドのプロトタイプ汚染からXSSへ
pageClient Side Prototype PollutionCVE-2019–11358: jQuery $ .extendを介したプロトタイプ汚染攻撃
詳細については、この記事を参照してください jQueryでは、$ .extend
関数が適切に使用されない場合、ディープコピー機能が悪用されるとプロトタイプ汚染が発生する可能性があります。 この関数は、通常、オブジェクトのクローン作成やデフォルトオブジェクトからプロパティをマージするために使用されます。 ただし、誤って構成されると、新しいオブジェクトに意図されたプロパティが代わりにプロトタイプに割り当てられる可能性があります。 たとえば:
この脆弱性は、CVE-2019–11358として特定されており、ディープコピーが誤ってプロトタイプを変更し、isAdmin
などのプロパティが適切な存在確認なしにチェックされると、管理者アクセスなどの潜在的なセキュリティリスクが発生することを示しています。
CVE-2018–3721、CVE-2019–10744: lodashを介したプロトタイプ汚染攻撃
Lodashは同様のプロトタイプ汚染の脆弱性(CVE-2018–3721、CVE-2019–10744)に直面しました。これらの問題はバージョン4.17.11で解決されました。
他のCVEを含むチュートリアル
プロトタイプ汚染を検出するツール
Server-Side-Prototype-Pollution-Gadgets-Scanner: Webアプリケーションでのサーバーサイドプロトタイプ汚染の脆弱性を検出および分析するために設計されたBurp Suite拡張機能。このツールは、潜在的なプロトタイプ汚染の問題を特定するためにリクエストのスキャンプロセスを自動化します。Node.jsライブラリに特に焦点を当て、既知のガジェット(有害なアクションを実行するためのプロトタイプ汚染を活用する方法)を悪用します。
server-side-prototype-pollution: この拡張機能は、サーバーサイドのプロトタイプ汚染の脆弱性を特定します。サーバーサイドのプロトタイプ汚染で説明されている技術を使用します。
NodeJSにおけるASTプロトタイプ汚染
NodeJSは、テンプレートエンジンやTypeScriptなどの機能でJavaScriptの抽象構文木(AST)を広範に利用しています。このセクションでは、テンプレートエンジン、特にHandlebarsとPugに関連するプロトタイプ汚染に関連する脆弱性について探ります。
Handlebarsの脆弱性分析
Handlebarsテンプレートエンジンはプロトタイプ汚染攻撃の影響を受けます。この脆弱性は、javascript-compiler.js
ファイル内の特定の関数から発生します。たとえば、appendContent
関数は、pendingContent
が存在する場合にそれを連結し、pushSource
関数は、ソースを追加した後にpendingContent
をundefined
にリセットします。
攻撃プロセス
攻撃は、Handlebarsによって生成されたAST(抽象構文木)を活用し、次の手順に従います:
パーサーの操作: 最初に、パーサーは
NumberLiteral
ノードを介して値が数値であることを強制します。プロトタイプ汚染により、数値でない文字列を挿入できます。コンパイラーによる処理: コンパイラーはASTオブジェクトまたは文字列テンプレートを処理できます。
input.type
がProgram
と等しい場合、入力は事前に解析されたものとして扱われ、これを悪用できます。コードの挿入:
Object.prototype
を操作することで、任意のコードをテンプレート関数に挿入し、リモートコードの実行につながる可能性があります。
Handlebarsの脆弱性を悪用する例:
このコードは、攻撃者がHandlebarsテンプレートに任意のコードをインジェクトする方法を示しています。
外部参照: 'flat'ライブラリに関連するプロトタイプ汚染の問題が見つかりました。詳細はこちら: GitHubの問題。
外部参照: 'flat'ライブラリにおけるプロトタイプ汚染に関連する問題: Issue related to prototype pollution in the 'flat' library
Pythonでのプロトタイプ汚染の悪用の例:
Pugの脆弱性
Pug、別のテンプレートエンジンも、プロトタイプ汚染の類似リスクに直面しています。詳細な情報は、PugにおけるASTインジェクションの議論で入手できます。
Pugにおけるプロトタイプ汚染の例:
予防策
プロトタイプ汚染のリスクを減らすために、以下にリストされている戦略が採用されることがあります:
オブジェクトの不変性:
Object.prototype
にObject.freeze
を適用して不変にすることができます。入力の検証:JSON 入力は厳密にアプリケーションのスキーマに対して検証されるべきです。
安全なマージ関数:再帰的なマージ関数の危険な使用は避けるべきです。
プロトタイプのないオブジェクト:
Object.create(null)
を使用してプロトタイププロパティのないオブジェクトを作成することができます。Map の使用:
Object
の代わりに、キーと値のペアを格納するためにMap
を使用すべきです。ライブラリの更新:定期的にライブラリを更新してセキュリティパッチを取り込むことができます。
リンターと静的解析ツール:ESLint のような適切なプラグインを使用して、プロトタイプ汚染の脆弱性を検出および防止するためのツールを使用します。
コードレビュー:プロトタイプ汚染に関連する潜在的なリスクを特定し、是正するために徹底的なコードレビューを実装します。
セキュリティトレーニング:開発者にプロトタイプ汚染のリスクと安全なコードの書き方に関するベストプラクティスを教育します。
注意してライブラリを使用する:サードパーティのライブラリを使用する際は注意が必要です。特にオブジェクトを操作するライブラリのセキュリティポジションを評価し、コードをレビューします。
ランタイム保護:プロトタイプ汚染攻撃を検出および防止できるセキュリティに焦点を当てた npm パッケージの使用など、ランタイム保護メカニズムを採用します。
参考文献
Last updated