再現の手順
AngularJSのmerge()関数は、複数のオブジェクトを1つの新しいオブジェクトに結合するために使用されますが、このHigh-levelの脆弱性があります。このコマンドは、Object.prototype のプロパティを追加または変更するために使用できます。
Javascriptでは、マジック・プロパティである__proto__、コンストラクタ、プロトタイプを含め、オブジェクトのすべてのプロパティをマージすることができます。特にこのエクスプロイトでは、__proto__プロパティをマージすることで、Object.prototypeを変更し、脆弱性を公開することが可能です。Object.prototypeプロパティはすべてのJavascriptオブジェクトに継承されるため、攻撃者はコード実行に影響を与える自由度を広く持つことになります。Javascriptの例外をトリガーすることで、リモートでのコード実行やサービス拒否につながる可能性もあります。
詳細はGitHubで。
問題への対処
このエクスプロイトはバージョン1.7.9より前のすべてのバージョンのAngularJSに存在します。アップグレードできない場合、HeroDevsのNever-Ending Support for AngularJSのクライアントは、Angular 1.5と互換性のある固定バージョンのAngularJSにアクセスできます。 攻撃を受けやすい対象は以下の通りです:
- ウェブサーバー
- アプリケーションサーバー
- ウェブブラウザー
学習と予防
この種の攻撃を防ぐ方法はいくつかある:
- プロトタイプを凍結する。Object.freeze(Object.prototype)を使うのは、プログラムの柔軟性を著しく損なう思い切った行為だが、この種の攻撃を防ぐことができる。
- スキーマ検証を要求する。 JSON入力は、__proto__属性を含まないようにスキャン("サニタイズ")することができます。
- 安全でない再帰的マージ関数の使用は避ける。なぜなら、問題は再帰的マージ関数の性質にあるのではなく、再帰的であろうとなかろうと、merge()関数が危険な属性をやみくもにObject.prototypeにコピーしてしまうことにあるからです。
- プロトタイプを使わないオブジェクトを使う。プロトタイプを使用しないオブジェクトを作成するには、Object.create(null)やプロキシオブジェクト、カスタムクラスを検討してください。Object.prototypeを継承しないオブジェクトは、汚染の影響を受けません。
- 配列とmap()を使用する。オブジェクトとmerge()を使う代わりに、配列とmap()関数を使えば、プロトタイプ汚染の可能性を完全に回避できる。
結論
この脆弱性で説明されている修正は1.7.9に含まれており、Angular 1.5を使用しているHeroDevs AngularJSネバーエンディングサポートのクライアントもすぐに利用可能です。潜在的にコストのかかる攻撃を回避するためのサポートをご希望の場合は、今すぐHeroDevsにご連絡ください。
リソース
NIST BDSA-2019-10768エントリー
弊社がサポートするオープンソースソフトウェアに新たな脆弱性が修正された場合、いつでもアラートを受け取ることができます。