序章
本日、 Route Sixty-Sinkをリリースします。これは、自動化されたソースからシンクへの分析を使用して、防御者とセキュリティ研究者が任意の .NET アセンブリの脆弱性を迅速に特定できるようにするオープンソース ツールです。 Route Sixty-Sinkは、すでに数十の重大なセキュリティ問題を発見して悪用するために使用されており、その例については、このブログ投稿で説明します。
背景: ソースからシンクへの分析
アプリケーション バイナリまたはソース コード内の脆弱性を特定することは、多くの場合、長くて退屈なプロセスです。これを支援するために、ソースからシンクへの分析が使用されます。これは、目的の関数呼び出し (シンク) の引数として渡されるユーザー入力 (ソース) を識別しようとするデータ フロー分析の形式です。
ソースは、ユーザー入力がアプリケーションに入るエントリ ポイントであり、シンクは、ソースからのユーザー入力を使用して、アプリケーションによって実行されるアクションです。脆弱性の調査を行う場合、シンクは、ソースからの入力を使用して実行される危険な関数呼び出しと考えることができます。表 1 と 2 に、ソースとシンクの例をいくつか示します。
ソース
ソース |
シナリオ例 |
|
URL から GET パラメーターを解析する Web アプリケーション |
|
権限のないユーザーが編集可能なファイルからの入力を解析するコンソール アプリケーション |
|
ユーザー入力のある PUT 要求を受け入れる Web アプリケーション ルート |
シンク
ソース |
シナリオ例 |
|
アプリケーションは、コマンドを実行する新しいプロセスを生成します。これにより、コマンド インジェクションが可能になる可能性があります。 |
|
Web アプリケーションはファイルをディスクに保存します。これにより、Web シェルやその他の悪意のあるファイルのアップロードが可能になる可能性があります。 |
|
Web アプリケーションは、別の Web ページからファイルを取得します。 URI がユーザーによって制御される場合、SSRF が可能になる可能性があります。 |
シンクのリストを列挙し、アプリケーション内でそれらを識別し、それらをユーザー制御の入力にバックトラックすることにより、ソースからシンクへの分析は脆弱性を効果的に識別できます。簡単な例として、次のような API ルート ハンドラーを持つ .NET Web アプリケーションを想像してください。
using System.Diagnostics; using System.Web; public class HomeController : Controller { public IActionResult Index() { string arg = HttpUtility.ParseQueryString(myUri.Query).Get("q"); Process.Start("getHealth.exe", arg); return View(); } }
System.Diagnostics.Process.Start()
API 呼び出しが使用したいシンクであると仮定すると、次のようになります。
System.Diagnostics.Process.Start()
関数のコード ベースを検索します。-
q
クエリ パラメータを特定する - API コントローラーとルートを特定します (
/home?q=
) - シンクに渡されたユーザー指定の引数 (
q
) を分析し、それが脆弱性を引き起こすかどうかを判断します - コマンド インジェクションを取得するエクスプロイトを作成します (
GET /home?q=<CMD_INJECTION>
) 。
Route Sixty-Sink は何を解決しますか?
効果的ではありますが、ソースからシンクまでの適切な分析は、多くの場合、実行不可能な時間のかかる手動プロセスです。次の表は、手動の静的分析の主な 3 つの問題点を特定し、 Route Sixty-Sinkがそれらの解決にどのように役立つかを説明しています。
問題 |
手動分析 |
ルート 60 シンク |
複雑な入力 トレース |
特に MVC アーキテクチャが使用されている Web アプリケーションでは、アプリケーションの入力を識別するのが難しい場合があります。 |
Route Sixty-Sinkは、さまざまなルーティングおよび入力解析シナリオを処理し、プログラムでエンドポイントを識別することによってこのプロセスを自動化します |
アプリケーションサイズ |
大規模な C# アプリケーションでは、多くの場合、手動分析を使用して完全なコード カバレッジを取得することは不可能です。 |
Route Sixty-Sinkはこのプロセスを自動化し、ほとんどのプログラムを数秒で分析できるようにします |
ネストされたシンク |
インターフェイス、拡張クラス、または一連のネストされた関数呼び出し内に隠れているシンクを見逃す可能性があります |
Route Sixty-Sinkは、すべてのクラスとメソッド呼び出しのコール グラフを作成し、ネストされたシンクへの呼び出しフローを再帰的にトレースすることで、これらのシンクを識別します。 |
どのように機能しますか?
概要
Route Sixty-Sinkは、任意の .NET アセンブリを介したユーザー入力の流れを追跡し、それが危険な関数呼び出し (「シンク」) に引数として渡されるかどうかを判断します。
Route Sixty-Sinkは、2 つのメイン モジュールを使用してこれを行います。
- ASP.NET Core MVC および従来の ASP ページ Web アプリケーションで API ルートを列挙するRouteFinder 。
- SinkFinderは、エントリ ポイントを取り、すべてのクラスとメソッド呼び出しの呼び出しグラフを作成します。次に、シンクの文字列、メソッド呼び出し、およびクラス名を照会します。
ルートファインダー
RouteFinderは、Web アプリケーションによって公開された、特定されたすべてのルート エントリ ポイントをすばやく解析します。
入力
入力として、 RouteFinderは、コンパイルされた .NET Web アプリケーション アセンブリ、または Web アプリケーションを構成するアセンブリを含むディレクトリを受け取ります。 RouteFinderは、次のルーティングをサポートしています。
- ASPX、ASMX、ASHX、および ASCX ページ
- ASP.NET Core MVC ルーティング
- 属性ルーティング
- 従来のルーティング (基本的な既定の規則)
出力
RouteFinderは、アプリケーション内で識別されたすべての API エンドポイントについて、各アセンブリ、コントローラー、プレフィックス、ルート、アクション、および承認ポリシーを出力します。例を図 1 に示します。
シンクファインダー
エントリ ポイントを指定すると、 SinkFinderはアプリケーション内のメソッド呼び出しを再帰的にたどって、ユーザー定義の「シンク」リストを見つけます。これを行うには、次のアルゴリズムを使用します。
- 入力および依存関係の C# バイナリからクラスとメソッドを列挙し、コール グラフに格納します
- エントリポイントから始まる共通中間言語 (「CIL」) 命令を解析し、すべてのメソッド呼び出しを識別します
- シンクが見つかった場合は、ユーザーに通知します
- メソッド呼び出しごとに:
- コール グラフ内のメソッドを検索してアクセスする
- 手順 2 ~ 3 を繰り返します
入力
入力として、 SinkFinderはコンパイル済みの .NET アセンブリまたはアセンブリのディレクトリを受け取ります。また、必要に応じて、依存関係として使用する追加の .NET アセンブリまたはアセンブリのディレクトリを受け入れます。依存関係がコール グラフに読み込まれ、それらの関数が走査されてシンクが検索されます。
出力
シンクが見つかった場合、 SinkFinderは、シンクにつながるすべてのメソッド呼び出しの完全な呼び出しグラフを出力します。これにより、研究者は、シンク コールの原因となったデータ フローをすばやく特定できます。
図 2 は、シンクで終了する SinkFinder 呼び出しグラフの例を示しています。複数のネストされた関数呼び出しとサード パーティの依存関係を通じて、SinkFinder がどのようにシンクを識別できるかに注目してください。これは、従来の静的分析アプローチを使用して行うのは非常に困難です。
スタンドアロンSinkFinderを使用してアセンブリをクエリする
C# 実行可能ファイルがあり、ローカル権限昇格を可能にする危険な関数を呼び出すかどうかを判断したいとします。このプロセスは、 SinkFinderを使用すると非常に簡単になります。
まず、検索するシンクのリストを JSON 形式で指定します。 Route Sixty-Sink GitHub リポジトリのsinks.json
ファイルには、ほとんどのセキュリティ リサーチャーが最初に使用できる一般的なシンクのリストがあります。 SinkFinderを実行し、 bam !ローカル特権エスカレーションに関して、すでに 2 つの優れた手がかりを得ています。
Route Sixty-Sink : RouteFinderとSinkFinderの結合
RouteFinderとSinkFinderモジュールを組み合わせてRoute Sixty-Sinkを作成すると、真の魔法が起こります。Route Sixty-Sink は、API ルートからシンクまでのソースからシンクまでの包括的な分析を数秒で実行するツールであり、セキュリティ研究者がソース コードのレビューなどに費やす時間を短縮できます。脆弱性を発見する時間。
ケーススタディ: Route Sixty-Sink を使用して実際の脆弱性を見つける
約 6 か月前、アプリケーションのコンパイル済みアセンブリを提供してくれたクライアントのために、.NET MVC アーキテクチャを使用して大規模な Web アプリケーションをテストしました。私たちが発見した脆弱性と、 Route Sixty-Sinkがどのようにその脆弱性を特定するのに役立ったかについて詳しく説明する前に、少し背景情報が必要です。
Newtonsoft.Json での安全でない逆シリアル化
Newtonsoft.Json.JsonConvert Newtonsoft.Json.JsonConvert::DeserializeObject()
関数は、私たちがよく探しているシンクです (スターターのsinks.json
リストに含まれています)。この関数は、渡された JSON 文字列で指定されたプロパティを使用してオブジェクトをインスタンス化します。このプロセスはデシリアライゼーションと呼ばれ、安全に実行されない場合、任意のオブジェクトのインスタンス化につながる重大な脆弱性が導入され、リモートでコードが実行される可能性があります。Muñoz と Miroshは、安全でないデシリアライゼーションの脆弱性について優れた概要を提供しています。
Newtonsoft.Json.JsonConvert::DeserializeObject()
を使用したデフォルトの逆シリアル化は、指定された予想される型以外のオブジェクトをインスタンス化しないため、通常は安全です。ただし、Newtonsoft ライブラリでは、開発者は特別なNewtonsoft.Json.JsonSerializerSettings
オブジェクトをパラメータとして渡すことができ、任意のオブジェクトをインスタンス化できます。表 4は、安全でないNewtonsoft.Json.JsonSerializerSettings
オブジェクトがデシリアライゼーション呼び出しに渡されることを示しています。これにより、ユーザー入力が JSON 文字列内に収まった場合に脆弱性が発生します。
var deser = JsonConvert.DeserializeObject(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }); |
Route Sixty-Sink を使用した安全でないデシリアライゼーションの検出
これを念頭に置いて、 Newtonsoft.Json.JsonConvert::DeserializeObject()
への呼び出しを識別するために、下の図に示す正規表現クエリを作成しました。 Newtonsoft.Json.JsonSerializerSettings
オブジェクトをパラメーターとして受け入れました。
Newtonsoft.Json.JsonConvert::DeserializeObject.*JsonSerializerSettings |
カスタム正規表現を使用して、コンパイルされた MVC アプリケーションでRoute Sixty-Sinkを実行しました。図 5に示すように、 Route Sixty-Sinkは、作成した正規表現に一致する関数を呼び出す API エンドポイントをすばやく特定しました。
Route Sixty-Sinkは、コントローラー ( Discussions
) とアセンブリ ( BaseCommon.dll
) の両方を便利に識別し、コントローラー内のすべてのメソッドの呼び出しグラフを作成しました。そのうちの 1 つが最終的にシンクの実行につながりました。
次に、 BaseCommon.dll
を便利な .NET 逆コンパイラである DnSpy に取り込み、シンクを実行した特定のクラスとメソッドを見つけました。逆コンパイラの出力を図 6に示します。
示されているように、アプリケーションはPOST
要求からDiscussionContext
パラメーターを取得し、安全でない状態で逆シリアル化しました。次に、 ysoserial.netを使用して JSON ペイロードを生成し、デシリアライズすると、私たちが管理するサーバーに DNS 要求を発行することができました。最終的なエクスプロイトを図 7に示します。
しばらくすると、DNS サーバーへのコールバックを受信し、アプリケーション サーバーでコードを実行したことが証明されました。
貢献する
Route Sixty-Sinkをリリースするという決定は、セキュリティ コミュニティがその利益を享受し、その成長を継続できるようにするために行われました。次のセクションでは、 Route Sixty-Sinkの優先度が最も高い次のステップについて説明します。
Route Sixty-Sinkを使用してください。
Route Sixty-Sinkに対する私たちの最大の希望は、研究者と開発者がこのツールを使用して、その長所と短所を特定し、改善できるようにすることです。
sinks.jsonリストへの追加
Route Sixty-Sinkで提供されるのは、脆弱性を発見するために一般的に使用されている一般的な .NET シンクのリストを含むsinks.json
ファイルです。 Route Sixty-Sinkのシンク検出機能を改善するために、セキュリティ リサーチ コミュニティがこのファイルに引き続き追加することを願っています。
高度なソースからシンクへの分析
今後のリリースでは、 Route Sixty-Sinkに次の機能を追加したいと考えています。
- ソースとして使用するためのパラメータ解析
- 高度な汚染分析
- シンボリック実行
- ソースからシンクまでの深さ、中間検証、および/またはサニタイズ機能に基づく低/高忠実度評価
- IPC メカニズムからのデータ、ディスク上のデータ、ソケットなどを含む、非 Web ベースのユーザー制御入力の識別。
追加開発
コミュニティのコラボレーションと継続的な開発を促進するために、 Route Sixty-Sinkをモジュラー設計で設計しました。新しいタイプのソースを定義したい研究者は、それをRoute Sixty-Sinkに簡単に追加して、ソースからシンクへの自動分析を活用できます。
たとえば、すべての .NET 逆シリアル化ソースを識別するモジュールを実装できます。次に、モジュールをSinkFinderに接続して、興味深いガジェット チェーンをすばやく特定できます。
新しいモジュールのアイデアがある場合は、私たちに連絡するか、プル リクエストを送信してください。
結論
Route Sixty-Sinkを導入しました。これは、.NET バイナリ内で自動化されたソースからシンクへの分析を実行するオープン ソース ユーティリティです。私たちはすでにRoute Sixty-Sinkを使用して、オープンソースおよびプロプライエタリな Web アプリケーションの数十の問題を特定してきました。世界中のアプリケーション セキュリティの状態を改善するために、Route Sixty-Sink がさらに多くの問題を特定し続けることを願っています。読者には、このプロジェクトを使用して貢献することをお勧めします!
GitHub リポジトリ
GitHub リポジトリは、 https://github.com/mandiant/route-sixty-sinkにあります。
参照: https://www.mandiant.com/resources/blog/route-sixty-sink-launch
Comments