はじめに:世界中のセキュリティ担当者を悩ませる「NVD問題」
脆弱性スキャナーやIT資産管理システムを自作・運用したことがある人なら、一度は米国立標準技術研究所(NIST)のNVD(National Vulnerability Database)APIのお世話になったことがあるはずです。
しかし、近年NVDをめぐる状況は急速に厳しさを増しています。
- 厳しいAPIレートリミット: リクエスト制限により、LAN内の数百台のソフトウェアを検査しようとするとすぐにエラー(HTTP 429)で止まる
- 分析・採番の遅延問題: 新規CVEが公表されてからNVDでCVSS値や影響範囲(CPE)が付与されるまでにタイムラグが発生する
- 閉域網(オンプレミス)で動かない: セキュリティポリシー上、LAN内から外部Web APIへの常時アクセスを禁止されている環境が多い
「スキャンのたびに外部のNVD APIを叩く」という設計は、もはや実運用の現場では限界を迎えています。
本記事では、NVD単体への依存を脱却し、CISA KEV(悪用確認済みリスト)、FIRST EPSS(悪用予測率)、国内JVN、OSベンダー公式OVAL などを統合してローカル環境(SQLite)でミリ秒単位で突合する設計を紹介します。
1. 活用すべき「多層的脆弱性インテリジェンス」の役割分担
NVDだけに頼るのではなく、目的に応じて以下のフィードを使い分けるのが現在のセキュリティ運用の最適解です。
| ソース名 | 提供組織 | 主な役割・メリット |
|---|---|---|
| CISA KEV Catalog | 米CISA |
最優先修復フラグ(最重要)。 CVSS値に関わらず「野生で実際にサイバー攻撃に使われている脆弱性」を即座にクリティカル認定する。 |
| FIRST EPSS | FIRST.org |
悪用予測スコアリング(0.0〜1.0)。 「今後30日以内に攻撃コードが出回る確率」を算出し、膨大なパッチの中から本当に危険なものを絞り込む。 |
| OSベンダー公式OVAL | Canonical / RedHat |
誤検知(False Positive)の撲滅。 Linuxのバックポートパッチ(バージョン番号が見かけ上古くても修正済み)を正確に判定する。 |
| JVN iPedia | IPA / JPCERT |
経営層・管理者向けの日本語レポート生成。 英語のCVE説明文ではなく、公的な日本語解説テキストを付与する。 |
2. CISA KEV と EPSS をローカルSQLiteにキャッシュする実装
最も効果が高いのが、「CISA KEV(悪用済みリスト)」の一括ダウンロードとローカルキャッシュ化です。
CISA KEVは公式でJSONフィード(約1,000件強)を丸ごと配布しているため、1回取得してSQLiteに入れておけば、外部通信ゼロで判定できます。
💻 コア実装・設定スニペット(抜粋)
# (要点抜粋)
import sqlite3
import requests
import json
KEV_URL = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
def sync_cisa_kev_to_sqlite(db_path: str = "cve_cache.db"):
"""
CISA KEV (悪用確認済み脆弱性カタログ) を取得し、ローカルSQLiteに格納する
"""
print("[+] Downloading CISA KEV feed...")
res = requests.get(KEV_URL, timeout=30)
res.raise_for_status()
data = res.json()
conn = sqlite3.connect(db_path)
cur = conn.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS cisa_kev (
cve_id TEXT PRIMARY KEY,
vendor_project TEXT,
product TEXT,
vulnerability_name TEXT,
date_added TEXT,
short_description TEXT,
action_required TEXT
)
""")
for vuln in data.get("vulnerabilities", []):
cur.execute("""
INSERT OR REPLACE INTO cisa_kev
(cve_id, vendor_project, product, vulnerability_name, date_added, short_description, action_required)
VALUES (?, ?, ?, ?, ?, ?, ?)
""", (
vuln.get("cveID"),
vuln.get("vendorProject"),
vuln.get("product"),
vuln.get("vulnerabilityName"),
vuln.get("dateAdded"),
vuln.get("shortDescription"),
vuln.get("requiredAction")
))
conn.commit()
conn.close()
print(f"[+] Synced {len(data.get('vulnerabilities', []))} CISA KEV records.")
3. スキャン時にミリ秒で「危険度ランク」を判定する
端末から抽出したパッケージ名やCVE IDに対し、外部APIを叩かずにローカルDBだけで即座に優先度判定を下します。
4. Linuxのバックポートパッチ誤検知をゼロにするOVAL連携
Linux(UbuntuやRHEL)では、アップストリームの最新バージョンに上げなくても、OSベンダーがセキュリティ修正だけを古いバージョンに適用する「バックポート(Backport)」が頻繁に行われます。
単に パッケージのバージョン番号 < 脆弱性バージョン で判定すると、「パッチ適用済みなのに未適用と怒られる」という誤検知(False Positive)が大量発生します。
各ベンダーが配布している OVAL(Open Vulnerability and Assessment Language)XMLフィード をローカルに取り込んでおくことで、正確なパッケージリビジョン(例: 1.2.3-1ubuntu0.1)に基づいた誤検知ゼロの監査が可能になります。
まとめ:外部API依存を捨てて「自前のインテリジェンス」を持とう
脆弱性管理の品質とスピードは、**「どれだけ手元に整理されたデータを持っているか」**で決まります。
- NVDのレートリミットに振り回されるのをやめる
- CISA KEVとEPSSを取り入れ、「現実に悪用されているもの」に最優先で注力する
- ローカルSQLiteにインデックスを張り、LAN内の閉域網でも一瞬で診断を完結させる
このアーキテクチャに切り替えるだけで、診断ツールの信頼性と実行速度は10倍以上に向上します。LAN内システムの脆弱性管理に頭を抱えている方は、ぜひローカルフィード設計を試してみてください!
📚 さらに詳しいアーキテクチャ設計・パラメータ表・トラブルシューティング
最後までお読みいただきありがとうございます!
本記事が少しでも「役に立った」「あとで試したい」と感じていただけましたら、ぜひQiitaの 「いいね(♡)」 と 「ストック」、および アカウントのフォロー をいただけると今後の検証・執筆の大きな励みになります!
また、本記事のさらに踏み込んだ 「深層アーキテクチャ解説」「主要パラメータの技術的根拠」「現場アンチパターン・トラブルシューティング対応表」 は、以下のGitHub技術リファレンスにて公開しています。
👉 【第10弾 詳細技術リファレンス (QIITA_ARTICLE_DETAIL_10.md)】
⭐ 全14層・200パターンの自立型インフラ&オンプレAIリファレンス集(おじさんの武器庫)を順次公開中です。ぜひGitHubリポジトリへの Star (★) と X (@OjisanTechnical) のフォローもお願いいたします!
👉 GitHub リポジトリ: ojisantech/ojisan-arsenal
💡 【検証環境・個人研究(PoC)に関する注記】
本記事は、筆者個人の自宅検証環境(ホームラボ/仮想環境)において、公開情報およびOSS(オープンソースソフトウェア)を用いて独自に構築・検証した個人研究(PoC)の記録です。特定の企業・団体の実環境や業務上の非公開情報とは一切関係ありません。