コンテンツにスキップ

実行時証拠による優先順位付けの成立性調査

  • 状態: 検証完了
  • 開始日: 2026年9月9日
  • 最終更新: 2026年9月13日

目的

実行時証拠を脆弱性の検出結果に十分な精度で紐づけ、優先順位付けの改善に使えるかを調査する

このページに初期計画を記録し、調査の進行に合わせて実験・結果・制約・判断を追記する

  • イメージ内の検出結果と実際の実行
    • スキャナはイメージ内の全パッケージを対象に脆弱性を報告するため、実行されないモジュールの脆弱性も含まれる
  • 既存の優先順位付け
    • CISA KEVとEPSSを使って検出結果に優先順位を付けている
    • これらは全環境共通の指標であり、脆弱なコンポーネントが利用者の環境で実際に動いているかは示さない
  • 環境固有の証拠
    • 脆弱なパッケージのバイナリがプロセスとして実行中か、サービスがポートで待ち受けているか、どの権限で動いているかを調べる
    • これらの証拠を使い、優先順位付けの根拠を説明し、判断の精度を高められるかを検証する

方針

  • 証拠は優先順位の引き上げにのみ使う
    • 実行を裏付ける肯定的な証拠があれば、検出結果の優先順位を「今すぐ対応」などへ引き上げられる
    • 証拠がないことを理由に優先順位を下げない
    • 短命なプロセス、再起動、権限不足による観測の欠落を安全の根拠にしない
  • 観測の分類
    • 観測をconfirmed(確認済み)、inferred(推定)、unknown(不明)、unobserved(未観測)に分類する
    • パッケージへ紐づけた実行ファイル・ロード済みOS共有ライブラリをconfirmedとし、サンプリングで捉えられない短命プロセスと言語パッケージは、イベント証拠で利用を直接紐づけられない限りunobservedとする
    • 待ち受けポートだけでインターネットから到達可能だと判断しない
  • 実行時観測機能はオプトイン
    • 実行時観測機能は明示的に有効化するとDockerホスト上で動作し、procfsとDocker APIのサンプリングで実行ファイル・ロード済み共有ライブラリを脆弱なパッケージへ紐づけ、待ち受けポート・実効権限を収集する
    • サンプリングとeBPFイベント観測は別オプトインとし、eBPFのカーネル要件を満たさないホストでもサンプリングを利用できる構成とする
    • 実行時観測機能が無効でも、追加権限が不要な標準のイメージスキャンを含め、既存の全機能が従来どおり動作することを条件とする
  • 最初の観測対象
    • 最初の段階はDocker Engineのみを対象にprocfsとDocker APIで状態をサンプリングして実行ファイルとロード済み共有ライブラリをOSパッケージへ紐づけ、ホストPID名前空間へのアクセスと他プロセスの/procを読むroot相当の権限を必要とする
    • eBPFイベント観測は実運用の「今すぐ対応」・「監視」相当の検出結果で確認率の有意な不足が計測され、カーネル・権限要件を許容する利用者がいる場合の後続段階とし、攻撃検知は扱わない
    • Kubernetes側の証拠収集は後続の段階で扱う

検証項目

  1. パッケージと実行プロセスの紐づけ精度
    • 限定された明確な範囲で、パッケージと実行時情報を正確に紐づけられるか
    • 「このプロセスの実行ファイルはこのOSパッケージに由来する」と判断した根拠を説明できるか
  2. 不明な情報の安全な扱い
    • 不明な情報や観測の欠落を安全に扱い、誤って低優先度と判断することを防げるか
  3. 運用上の負担
    • 必要な導入手順・権限・ホスト負荷が、対象利用者の許容範囲に収まるか
  4. KEV・EPSSに追加する価値
    • KEV・EPSSだけの場合に比べ、実行時証拠によって対応すべき検出結果を有用な形で絞り込めるか
  5. 実行時観測機能が無効な場合の動作
    • 実行時観測機能を無効にしても既存の全機能が完全に維持されるか

5つすべてを継続の条件とし、満たせない場合は実行時証拠の機能を見送る

今回の対象外

  • 短命プロセスと言語パッケージのイベント観測

    • 短命プロセスと言語パッケージのイベント観測は初回範囲外とし、観測できなかった割合の計測結果に応じて後続段階で扱う
    • 攻撃検知と攻撃タイムラインは対象外
  • Kubernetesの証拠収集

    • Kubernetes側の証拠収集は、本調査でDocker Engineでの成立性を確認した後に着手する
    • 最初に既存の読み取り専用Kubernetes adapterから得られるcontainerPort・Serviceの宣言による待ち受けの見込みとsecurityContextによる実効権限の見込みを、実行時観測機能や追加権限なしのinferred証拠として扱う
    • 次にDocker向けの初期実装の後続として、Kubernetes利用者からの需要確認を条件に、オプトインのDaemonSet観測でconfirmed証拠を収集する
    • DaemonSet観測にもサンプリングと条件付きイベント観測の2段階および別オプトインを適用する

検証方法

  • 検証環境
    • 製品とは独立した検証用プログラム(ハーネス)を、1台のWSL2ホストで実行
    • Linux 6.6.114、Docker Engine 29.1.3、Trivy 0.71を使用し、HIGH/CRITICAL(以下「高重大度」)を中心に評価
  • 紐づけ1:プロセス → OSパッケージ → Trivyの検出結果(所有関係)
    • 脆弱なパッケージの利用を確かめるため、実行ファイルと読み込み済みライブラリをOSパッケージの所有情報と照合する
    • 利用を確認したパッケージを同じイメージのTrivy検出結果に紐づけ、不明な所有関係は推測で補わない
  • 紐づけ2:待ち受けポート → プロセス → 公開状態(ポート)
    • サービスの公開状態を確かめるため、待ち受けているプロセスとDockerのポート公開設定を照合する
    • 待ち受けているだけでは、インターネットから到達できるとは判断しない
  • 紐づけ3:プロセス → 実行ユーザーと特別な権限(権限)
    • どの権限で動いているかを確かめるため、プロセスごとに実行ユーザーと特別な権限の有無を調べる
  • 紐づけ結果のまとめ方と収集の検証
    • 別のプロセスの情報が混ざらないよう、同じプロセスを同じ観測時点で確認した情報だけを検出結果に付ける
    • 観測できなかった場合も失敗として記録する
  • 正解データ(採点用の「実際に使われたパッケージ」の一覧)
    • 紐づけの正しさを確かめるため、ハーネスとは別の方法で利用パッケージの一覧を作る
    • 自作イメージではプログラム自身の利用記録と照合し、記録対象の見逃しと誤った利用判定を調べる
    • 公式イメージでは常駐プロセスの利用ファイルを手作業で照合し、見逃しだけを調べる
    • 観測後に対象を選んだ確認は参考値とし、いずれの方法でも脆弱な処理そのものの実行は確認しない
  • テストケース
    • 対応範囲と見逃しを確かめるため、常駐サービス、異なるパッケージ形式、ファイルの削除・置換、短時間の実行・読み込みを試す
    • 12ケース・13種類のイメージで、修正後の再実行2回を含む36回の計測を実施
  • 権限とサンプリングの条件
    • 基準はrootで30秒ごとに300秒間観測する10サンプルとし、nginx・Redis・Distrolessで権限の4条件を比較
    • 短時間の利用を捉えられるか確かめるため、観測間隔・期間・開始タイミングを変えた7条件を比較
    • 運用負荷を確かめるため、ハーネスのCPU時間・ピークメモリとDockerデーモンのCPU時間を測定

具体的な権限名と手順はハーネスの READMEを参照

結果(2026年9月12日)

  • 確認できたこと

    • 確認対象の常駐プロセスでは、実行ファイルとOS共有ライブラリの所有パッケージを解決できた
    • 所有者不明のファイルを推測で紐づけた件数は0で、削除・置換の3対象も現在の同名ファイルと取り違えなかった
    • プロセスごとの実行権限とポートの公開設定を区別でき、ホストネットワークの公開状態は不明とした
    • 次表は主計測の1台での結果に限り、Dockerへのアクセス権は別途用意した
    観測側の権限条件 パッケージの利用確認 待ち受けプロセスの特定 実行権限の確認
    root 基準 取得できた 取得できた
    rootなしで最小の権限2つ rootと同じ rootと同じ rootと同じ
    rootなしで権限1つ rootと同じ できず、公開状態は不明 取得できた
    rootなしで権限なし 全サンプルで観測失敗 不明 不明
    • 主計測の1コンテナ・300秒では、ハーネスのCPU時間は0.09〜0.41秒、ピークメモリは6.5〜20 MB
    • DockerデーモンのCPU増分は0.16〜0.21秒で、Redisのみ1.13秒となった原因は未調査
    • 観測タイミングの最大遅延は37 msで、遅延の累積なし
    • できなかったこと
    • 事前に定めた正解データは対象ケースの高重大度パッケージの4.0〜5.6%に限られ、精度全体は未判定
    • 利用記録との照合で誤った利用判定は0件だったが、確認対象は各ケース1〜2パッケージのみ
    • Python拡張やGo依存関係などの言語パッケージは紐づけられず、静的Goの実行ファイルもOSパッケージの所有情報からは紐づけられなかった
    • 約0.1秒実行して5秒待機するcurlとgitは安定して捉えられず、次表は実行回数に対する捕捉率ではなく捉えたサンプル数
    観測間隔 観測期間 開始タイミングのずれ サンプル数 curlを捉えた数 gitを捉えた数
    10秒 300秒 0秒 30 1 0
    30秒 300秒 0秒 10 0 0
    60秒 300秒 0秒 5 0 0
    10秒 100秒 0秒 10 0 0
    60秒 600秒 0秒 10 1 0
    30秒 300秒 3秒 10 0 0
    30秒 300秒 7秒 10 1 0
    • 捕捉は観測タイミングに左右され、この計測から一般的な見逃し率は推定できない
    • 7秒ごとに読み込みと解放を繰り返すSQLiteは、7条件すべてで捉えられた
    • ケース別の結果
    • 分数は基準条件での「利用証拠を紐づけた検出結果数 / 対象の検出結果数」
    • 「今すぐ対応」「監視」は高重大度のみを集計し、N/Aは該当する検出結果なしを表す
    イメージ・ケース 高重大度 今すぐ対応 監視 全重大度
    nginx Debian 9/153 1/2 2/20 66/616
    Redis Alpine 0/0 N/A N/A 0/0
    nginxホストネットワーク 9/153 1/2 2/20 66/616
    PostgreSQL 5/113 N/A 1/10 71/409
    Python + cryptography 0/54 N/A 0/2 22/180
    Distroless動的C 0/0 N/A N/A 18/29
    Debian静的Go 0/56 N/A 0/2 0/222
    Distroless静的Go 0/0 N/A N/A 0/0
    ファイルの削除・置換 0/59 N/A 0/3 18/232
    短命なcurl/git 0/99 N/A 0/9 23/410
    SQLiteの一時的ロード 3/59 N/A 1/3 28/232
    nginx-unprivileged Alpine 16/34 2/2 2/4 42/109
    nginxの特別な権限を変更 9/153 1/2 2/20 66/616
    • nginx Debianではlibssl3の「監視」2件の順位が上がり、未観測の検出結果は順位を維持
    • 本番環境での標本
    • 別のUbuntuホストの4コンテナを、rootで30秒ごとに300秒間、1回計測
    • AppArmor有効の環境で全コンテナの観測に10/10回成功し、rootなしの条件は未検証
    コンテナの種類 高重大度の確認済み / 対象 高重大度の内訳:言語 / OS 監視の確認済み / 対象 全重大度の確認済み / 対象
    静的Goバイナリ 0/36 23 / 13 N/A 0/107
    JDK同梱のJVM 0/17 15 / 2 0/3 16/246
    Node.jsサービス1 0/21 19 / 2 0/3 0/48
    Node.jsサービス2 0/29 27 / 2 0/2 0/67
    • 高重大度103件はすべて未確認で、内訳は言語パッケージ84件と未観測のOSパッケージ19件
    • 「監視」8件も未確認で、内訳は言語パッケージ6件とOSパッケージ2件
    • 「今すぐ対応」は0件のため評価できず、この1ホスト・1回の結果を実運用全体には一般化できない
    • 4コンテナでハーネスのCPU時間は0.44秒、ピークメモリは16.8 MB、DockerデーモンのCPU増分は0.59秒
    • 実機で見つかったハーネスの不備
    • 権限不足の誤分類、ファイルの所有関係の誤判定、優先度未分類の検出結果が集計から漏れる不備を修正
    • 一部の検出結果が製品の通知などから欠落する別課題は未修正
    • ファイルの入れ替わりを見分ける追加の判定と、静的Goケースで追加観測が役立つ範囲の判定は未検証

判断(2026年9月13日)

  • eBPFによる実行時証拠の観測調査へ進む
    • 今回の本番標本では高重大度の優先順位付けを改善できず、短命プロセスと言語パッケージの利用確認を調査する
    • eBPFによるイベント観測の着手条件は未判定のまま調査を先行し、証拠がないことを理由に優先順位を下げない原則を維持する
  • 設計の手がかり
    • 静的Goは、Trivyが検出したバイナリと実行中のファイルを照合する方法を検討する
    • JVMは開いたままのファイル、Node.jsはファイルを開いた時点の記録から利用を確かめる方法を検討する
  • 未確定事項
    • 利用者が許容する動作環境と権限、言語パッケージへの紐づけ方法、実運用全体での効果は未確認

次の作業

  • イベント観測と対応付けの検証
    • 短時間の利用を捉えるため、実行やファイル読み込みが起きた時点の記録とパッケージへの紐づけを検証する
  • 権限・精度・負荷の評価
    • 導入可能な条件を確かめるため、利用者の許容範囲と環境ごとの必要権限を確認する
    • 実用性を確かめるため、複数ホスト・複数日での精度と優先順位への効果、規模が大きい場合や初回観測時の負荷を測る
  • 共通の証拠モデルと既存機能の維持
    • DockerとKubernetesで共通に扱えるよう、観測結果と根拠の表し方を定める
    • 製品組み込み時に、観測失敗で順位が下がらないことと無効時の互換性を含め、成立性の5条件を再評価する

更新履歴

2026年9月13日

  • サンプリング方式の検証結果を記録
    • 検証方法、結果、必要権限、負荷、本番標本、修正した不備と残る制約を追加
  • eBPFによるイベント観測の調査方針を決定
    • 着手条件は未判定のまま、短命プロセスと言語パッケージの利用確認の調査を先行する

2026年9月10日

  • Kubernetesの位置づけを決定
    • 初回調査はDocker Engineに限定し、観測の分類と証拠の型はDocker・Kubernetes両方の識別子に対応する形で定義する
    • KubernetesはDockerでの成立確認後に実行時観測機能を使わない推定証拠からオプトインのDaemonSet観測へ進む構成とし、DaemonSet観測には利用者の需要確認も必須とする
  • eBPFの扱いを決定
    • 最初の段階はロード済み共有ライブラリを含むprocfsとDocker APIの状態のサンプリングとし、ホストPID名前空間へのアクセスとroot相当の権限を必要とする
    • eBPFイベント証拠は確認率不足の計測とカーネル・権限要件を許容する利用者の存在を条件とする後続段階として別オプトインにし、攻撃検知は対象外とする

2026年9月9日

  • 調査開始
    • 動機、設計スタンス、成立性を検証する5つの問い、対象外の範囲、初期検証計画を記録
    • 実験と結果の記録はこれから

この記事は、KestreLynxの開発記録です。KestreLynxについて