
CVE-2026-74580(Linux vhost メタデータキャッシュのバグ)向けの、パッシブなインターネット全体のディスカバリー+責任ある開示ヘルパー — 既存のスキャンデータ(Sonar/Shodan/Censys)を照会し、露出をトリアージし、所有者への通知を下書きする(自動送信は決して行わない)。
CVE-2026-74580(「Vghost」)向けのペリメータチェックおよび責任ある開示支援ツールです。これは実際の Linux カーネル vhost メタデータキャッシュのバグ(CVE レコード、OSV エントリ)であり、公開された vhost/ハイパーバイザホスト上でローカル権限昇格/VM エスケープを可能にします。
主な用途: 自身のペリメータをチェックする。 自身の IP レンジ、CIDR、またはドメイン(import_list.py)を投入し(内部・外部を問わず)、vhost 関連の露出(libvirt/Proxmox/QEMU の管理ポート)についてトリアージしたうえで、自身のトラッカー向けの修復メモを取得します(run_pipeline.py --self、下記「自身のペリメータをチェックする」を参照)。自動ディスカバリや一括の連絡先検索は行いません。ホストはすでにあなたが所有しているからです。
副次的な機能: 公開スキャンデータによる第三者ディスカバリ。 本プロジェクトはインターネットを自らスキャンしません。オプションで、すでにスキャンを実施済みのデータセット/API(Rapid7 Open Data / Sonar、Shodan、Censys)を照会して他の露出ホストを見つけ、その所有者への開示通知の草案作成を支援できます。ここに時間を投資する前に知っておくべきこと: これに対する報奨金はありません(CSIRT は支払いませんし、「既知の CVE、未パッチのインスタンス」という報告は報奨金の対象になることはほとんどありません — 下記「影響」を参照)。これは無償の善意による通知作業であり、このリポジトリの実際の使われ方の大半は上記のペリメータチェックのケースであって、こちらではありません。
CVE-2026-74580 はカーネルレベルのローカルバグであり、Web/ネットワークに面したものではありません。そこからトリアージに関わるいくつかの点が導かれます:
以下のすべてが当てはまる場合にのみ適用可能:
vhost-net/vhost-scsi、通常は libvirt または Proxmox 経由)を使用している。VM のないベアメタルホスト、または vhost オフロードなしの素の virtio 上の VM は、パッチレベルに関係なくこのバグに露出しません。実際の深刻度を左右するのは、誰がすでに(または取得できる)コード実行を持っているかであり、ホストがインターネットに面しているかどうかではありません。 インターネットへの露出は、外部の攻撃者が標的を見つけたり、リモートで初期足場に到達したりする容易さに影響するだけで、誰かがその足場を得た後にバグが悪用可能かどうかは変わりません。内部専用のプライベートインフラは、本質的にリスクが低いわけではありません:
インターネット露出に関係なく、最も重要なもの:
インターネット露出が実際に重要となる場面(主要因ではなく副次的要因):
merge_and_triage.pyのスコアリングが探しているのはこれです。ただし、露出したポート自体は何も証明しません -- 攻撃者が制御する何かがローカルで実行できて初めて意味を持ちますが、パッシブスキャンデータではそれを示せません(このリポジトリが、所有していないホストに対してそれを確認しようとしない理由については、後述の「なぜパッシブのみなのか」を参照してください)。本当に重大度が低いもの:
WAFは役立つのか? このバグに直接は役立ちません -- WAFはHTTP(S)トラフィックを検査しますが、このバグはリクエストの解析ではなく、カーネルのvhostメタデータキャッシュの経路に存在します。脆弱性自体の露出経路には単純に含まれていません。
WAFが実際に重要となるのは、その一歩手前です。実世界で最も一般的な連鎖は、WebアプリのRCE → ゲスト内でのコード実行 → vhostエクスプロイト → ホストエスケープ → 他のすべてのテナントへの横展開です。WAF(またはその他のWebセキュリティ制御)は、攻撃者に初期の足場を与えるWebアプリのRCEを阻止でき、それによって攻撃者がこのバグの前提条件にそもそも到達することを防げます。つまり、vhostのバグ自体には無関係ですが、その前提条件への侵入経路として最も一般的なものの一つには関連しています。
リスクをエンドツーエンドで実際に低減するもの: カーネルへのパッチ適用、不要な箇所でのvhostオフロードの無効化、libvirt/Proxmoxの管理ポートをインターネットに公開しないこと、ゲスト内で動作するWebアプリ/サービスの堅牢化(初期RCEの可能性を減らす)、そしてテナント分離の堅牢化(seccomp、名前空間)により、あらゆる足場の取得を困難にすることです。
所有していない、または書面による許可を得ていないシステムに対して能動的なポートスキャンやSSHプロービングを行うことは、ほとんどの法域で不正アクセスに該当し(EUでは指令2013/40/EUの国内実施法に該当し、チェコ法では刑法§ 230に該当します)、またほとんどのホスト/クラウドで利用規約違反となります -- 善意であっても関係ありません。このリポジトリは、第三者のスキャナーが独自の許可のもとで既に収集し、公開または販売したデータへのアクセスを読み取るだけです。詳細はSCOPE.mdを参照してください。
特定の検出結果を検証したい場合(ホストが実際に脆弱なのか、単に「露出しているように見える」だけなのかを確認する場合)、それには所有者の許可が必要です -- まさにそれを求める開示テンプレートを参照してください。
src/sonar_query.py — Rapid7 Open Data / Sonar のスキャンファイルを解析し
(無料ダウンロード、アカウント不要)、vhost に関連するポート/バナーを抽出します。src/shodan_query.py / src/censys_query.py — 任意。同じシグネチャに対する
無料枠 API クエリ(Sonar の定期的なダンプより新しいデータを得るのに有用)。src/merge_and_triage.py — 結果をマージし、重複排除し、露出の可能性をスコアリングして
reports/candidates.csv を出力します。src/whois_contacts.py — 任意(下記参照)— 開示のルーティングのために、
候補ごとに abuse/security 連絡先を検索します(RDAP + security.txt の取得)。src/draft_notices.py — 候補ごとに templates/disclosure_email.md を埋めて
reports/notices/ に出力します。これはあなたがレビューし、手動で送信するためのものです。このパイプライン内の何も、自動的にメール送信や連絡を行うことはありません — 通知は 手動レビューと送信のために下書きされ、多数の組織に関する検出結果は、代わりに 各国の CSIRT を通すべきです(下記参照)。
上記のステップ 4〜5(連絡先検索、開示文の下書き)は、ホストの所有者を
すでに知らない 場合 — つまり見知らぬ相手への通知 — にのみ意味があります。代わりに
自分の IP レンジ/ドメイン(下記のオプション B)を入力して、公開スキャンデータが
自分の露出について何を示しているかを確認する場合は、所有者をすでに知っているので、
whois_contacts.py を完全にスキップし、draft_notices.py の代わりに
src/draft_remediation.py を使用してください — これは候補ごとに
templates/remediation_note.md を埋めて reports/remediation/ に出力します
(開示メールではなく、自分のトラッカー用のチケット。RDAP/
security.txt の検索は不要)。run_pipeline.py --self はこれを
自動で行います(下記の「任意: 週次で実行する」を参照)。
これはインターネットに面したホストだけでなく、内部ホストにも機能します。
import_list.py/merge_and_triage.py は --self モードでは対象ホストに
一切接続しません — DNS 解決(ドメイン/FQDN の場合)と CIDR 演算のみを行い、
すでに提供されたメタデータをスコアリングするだけです。したがって、プライベート IP
レンジ(10.x、172.16.x、192.168.x)、内部 FQDN、CNAME はすべて
機能します。ただし、これを実行する場所からそれらを解決/到達できる場合に限ります
(例: 社内ネットワークや VPN)— --self は SSRF 制限のある唯一のステップ
(whois_contacts.py)をすでにスキップします。連絡先を検索する第三者が
存在しないためです。Shodan/Censys/Sonar は明らかに内部ホストをカバーしません
(公開インターネットのみをインデックスしているため)。代わりに、自分の内部
インベントリをオプション B 経由で入力してください。
フラグが立ったホストをトリアージするだけでなく、確認する: 上記のすべては
パッシブなトリアージ(ポート/バナーのシグナル)です — 特定のホストのカーネルが
実際に未パッチかどうかは分かりません。そのためには、すでにアクセスが
許可されているホスト(SCOPE.md のシナリオ B に従う)で
src/vghost_scan.py を使用してください。これは uname -r と vhost カーネル
モジュールがロードされているかどうかを読み取り(エクスプロイト関連のものはなく、
ホストを変更するものもありません)、それを上記の修正済みバージョン表と
照合します。
python3 src/vghost_scan.py --local # the machine you're already on
python3 src/vghost_scan.py --ssh-host [email protected] --confirm-authorized # a host you control, via your own SSH access
実行ごとに明示的に指定された1つのホストのみをチェックします -- 一括/リスト入力、認証情報の推測、検出は行いません。--ssh-host は既存の SSH アクセス(キー/エージェント/設定)をそのまま使用し、認証情報の読み取り、プロンプト表示、保存は一切行いません。
すべての操作はリポジトリのルートから実行してください -- 各スクリプトはスクリプト自身からの相対パスではなく、カレントディレクトリからの相対パス(data/、reports/、templates/、config/)を使用します。
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
# Option A: free Rapid7 Sonar datasets (no key, large download)
python3 src/sonar_query.py --file sonar_tcp_16509.json.gz --port 16509 --port 16514 --port 8006
# Option B: your own list -- CSV with an "ip" and/or "domain" column (+ optional "port", other columns kept).
# The "ip" column may also hold a CIDR range (e.g. 203.0.113.0/24); it's expanded to
# individual addresses as passive-lookup candidates, capped by --max-hosts (default 65536).
python3 src/import_list.py --in hosts.csv
python3 src/import_list.py --in ranges.csv --max-hosts 4096
# Option C: Shodan free tier (set SHODAN_API_KEY env var)
python3 src/shodan_query.py --query 'product:QEMU' --query 'port:16509,16514'