コンテンツにスキップ

Reachability Analysisの概要

Aikidoのreachability analysisは、脆弱性がアプリケーションの文脈で実際に悪用可能かどうかを特定することに主眼を置いています。脆弱な依存関係やリスクのあるパターンを一律に重大とフラグ付けするのではなく、Aikidoはコードベース内のモジュール、関数、データフローのグラフを構築します。そして、次の重要な問いを立てます。実際のアプリケーションの動作から脆弱なコードへの実行パスは存在するか? そのようなパスが存在する場合にのみ、その検出結果は真にセキュリティ上の関連性があるとみなされます。

大まかに言うと、Aikidoは以下のような要素からなる抽象的なプログラムグラフを構築します。

  • **ノード(Nodes)**は、関数、メソッド、モジュール、ファイル、場合によってはより上位のコンポーネントを表します。
  • **エッジ(Edges)**は、関数呼び出し、import、依存関係の取り込み、変数やパラメータ間のデータフローなどの関係を表します。

脆弱性は、このグラフ内の特定のノードに紐づけられます(例えば、サードパーティライブラリ内の既知の脆弱な関数や、SQL実行ポイントのようなシンクなど)。次にAikidoは、エントリーポイント(HTTPハンドラ、CLIコマンド、バックグラウンドジョブなど)からこれらの脆弱なノードへのパスが存在するかどうかを計算します。現在のコードと設定の下でそのようなパスが存在しない場合、そのプロジェクトのリビジョンにおいて、その脆弱性はreachableではない(到達不可能)として扱われます。

このようにして、reachabilityは平坦なアラートのリストを、実際のプログラムの動作に確実に結び付けられた問題の構造化されたサブセットへと変換します。

Aikidoは、reachabilityについて互いに補完し合ういくつかの概念を用いています。これらは同じ基盤を共有しつつ、異なる抽象度のレベルで機能します。

種類 対象範囲 主な問い 典型的なシグナル
依存関係レベル(Dependency-level) SCA / パッケージの依存関係 「プロジェクトは脆弱なシンボルを呼び出すことがあるか?」 import、シンボル参照、依存関係マニフェスト
関数レベル(Function-level) SAST / テイント解析 「信頼できない入力が危険なシンクへ流れ得るか?」 ソース、サニタイザ、シンク、手続き間フロー
コンテキスト(実行時) ビルド・実行環境 「このコードは実際の実行時コンテキストで実行されるか?」 本番用と開発用の依存関係の違い、デッドコード、ビルド専用ツール

これらのカテゴリは互いに排他的ではありません。典型的なAikidoの検出結果は、まず依存関係レベルのreachabilityでフィルタリングされ、次に関数レベルのreachabilityで絞り込まれ、最後にプロジェクトのビルド・デプロイ方法の文脈で再解釈されます。

Aikidoはプロジェクトごとに、言語とフレームワークを考慮した軽量なグラフを構築します。

  • 構造的な関係: import、require、モジュール参照、継承、その他の静的な関係。
  • 呼び出しの関係: 関数呼び出し、メソッド呼び出し、イベントハンドラ。
  • データフローの関係: 変数、パラメータ、戻り値を通じた、汚染の可能性があるデータの伝播。

このグラフは意図的に近似的なものですが、「パスは存在するか?」という問いに効率的に答えるために必要な性質を保持するよう設計されています。

次に各スキャナーは、生の検出結果それぞれを、グラフ内の1つ以上のアンカーポイントにマッピングします。

  • SCAの場合、アンカーは通常、CVEやアドバイザリに関連付けられた脆弱なシンボル(特定の関数、クラス、メソッド、モジュール)です。
  • SASTの場合、アンカーは注目すべきコードの位置であり、多くの場合exec、SQLクエリ、ファイルシステムアクセス、デシリアライゼーションなどのセキュリティシンクです。
  • インフラスキャンの場合、アンカーポイントは実行時の実行環境に関与するイメージ、パッケージ、設定要素に対応することがあります。

一連のエントリーポイントとアンカーノードが与えられると、Aikidoは以下のような形式でreachabilityの問いを立てます。

「現在のビルドと設定の下で、いずれかのエントリーポイントからこのアンカーへの有効な実行パスが少なくとも1つ存在するか?」

アルゴリズム的には、これは言語のセマンティクスと設定情報によって制約されたグラフのreachability(順方向または逆方向の走査)に帰着します。データフロー解析では、reachability関係はテイント情報によって拡張されます。パスは、信頼できないデータがサニタイゼーションによって完全に無害化されることなく通過できる場合にのみ、セキュリティ上の関連性があるとみなされます。

4. トリアージおよび優先順位付けとの統合

Section titled “4. トリアージおよび優先順位付けとの統合”

Reachabilityは、より上位のトリアージが行われるに適用されます。

  • 到達可能なパスがない検出結果は、除外されるか大幅に格下げされます。
  • 明確で説明可能なパスがある検出結果は保持され、後続の段階(リスクスコアリング、ビジネスインパクト分析など)に渡されます。
  • 開発者は、具体的なパス(コールスタックとデータフロー)を確認し、その問題がどのように悪用可能になるかを理解できます。

このパイプラインにより、ほとんどの「オオカミ少年」的な検出結果は、単に深刻度の調整によって隠されるのではなく、構造レベルでフィルタリングされます。

検出結果とワークフローへの影響

Section titled “検出結果とワークフローへの影響”

Reachability analysisは、チームがAikidoをどのように利用するかに関して、いくつかの実践的な効果をもたらします。

  1. ノイズの削減

    従来型のツールが生成する多くのアラートは、存在はしているが決して呼び出されない依存関係や、事実上デッドなコードパスに起因します。実証可能な実行パスを持たない問題を排除することで、Aikidoは誤検知や重複するチケットを大幅に削減します。

  2. より意味のある深刻度

    深刻度はもはやCVEやルール単体の性質ではなく、CVEプロジェクトでの使われ方を組み合わせた性質になります。ホットパス上に深く組み込まれた中程度の深刻度のライブラリの問題は、本番環境で決して実行されない開発専用ツールの高深刻度の問題よりも緊急性が高い場合があります。

  3. 開発者に寄り添った説明

    具体的なパス(「リクエストハンドラ → サービス → ライブラリ関数 → 脆弱なシンボル」)を示すことで、セキュリティの検出結果を認識可能なプログラムの動作として捉え直すことができます。これにより開発者の認知的負荷が下がり、修正作業をより的確かつ効率的に行えるようになります。

  4. 時間経過に対する安定したシグナル

    Reachabilityはコードや依存関係の変化に応じて再計算されるため、課題のバックログは実際のアーキテクチャの変化を反映します。デッドな依存関係が削除されたりコードがリファクタリングされたりすると、以前は到達可能だった検出結果が到達不可能に変わることもあれば、その逆もあり、動的でアーキテクチャを考慮したリスクの見方を提供します。

Aikidoのreachabilityエンジンは、「保守的なunder-approximation(過小近似)」として構築されており、高い確信度をもって判断できる場合にのみコードを到達不可能とマークします。リフレクション、動的import、メタプログラミング、複雑なビルドステップといった動的な言語機能は、コールグラフの一部を不明瞭または不可視にすることがあります。このような曖昧なケースでは、Aikidoは慎重を期し、潜在的に関連性のある問題を抑制するのではなく、そのまま維持するか、深刻度を下げるかのいずれかを選択します。

このトレードオフは、次の2つの目標のバランスを取るものです。

  • 実行時に確実に到達不可能である問題をフィルタリングすることでノイズを削減する。
  • Reachabilityを確実に判定できない場合に、誤った安心感を与えないようにする。

Aikidoにおけるreachability analysisは、ソースコード、依存関係、インフラにまたがる、関数呼び出し、データフロー、コンポーネント間の相互作用を追跡することで、アプリケーションの各部分がどのようにつながっているかをマッピングします。脆弱性は、アプリケーションのエントリーポイントから脆弱な動作までの明確で実行可能なパスがある場合にのみ、実際のリスクとして扱われます。この考え方をすべてのスキャナーに組み込み、トリアージと緊密に統合することで、Aikidoは大量でノイズの多い生のアラートの流れを、攻撃者が実際にシステムを悪用し得る方法をより正確に反映した、少数で信頼性の高い検出結果の集合へと変換します。