0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

なぜ脆弱性診断ツールは「手打ちパッチ」で誤検知を連発するのか? BashとSQLiteで過剰アラートをゼロにする超軽量プローブを作った話【個人検証PoC】

0
Last updated at Posted at 2026-10-11

💡 【検証環境・個人研究(PoC)に関する注記】
本記事は、筆者個人の自宅検証環境(ホームラボ/仮想環境)において、公開情報およびOSS(オープンソースソフトウェア)を用いて独自に構築・検証した個人研究(PoC)の記録です。特定の企業・団体の実環境や業務上の非公開情報とは一切関係ありません。

はじめに:セキュリティ診断の現場で起きている「手打ちパッチ地獄」

インフラエンジニアや情シス、あるいはMSP(運用監視)の現場で、定期的にOpenVASやNessusなどの脆弱性スキャナーを回している方は多いと思います。

そして、スキャン結果のレポートを見て、一度はこう叫んだ経験があるはずです。

「このOpenSSHの脆弱性、先週バックポートパッチ当てて修正済みだよ!! なんでまだCriticalで上がってくるんだよ!!」

外部からのブラックボックススキャンや一般的なエージェントレススキャナーの多くは、バナー情報(例: OpenSSH 8.9p1)のバージョン番号だけを見てCVEデータベースと突合します。
しかし、Linuxディストリビューション(UbuntuやRHEL等)の運用では、メジャーバージョンを上げずにパッチだけを手動やディストリ配布でバックポート適用する(手打ちパッチ) のが日常茶飯事です。

その結果:

  • 「実際には塞がれているのに、脆弱性スキャナーは危険だと大騒ぎする」
  • 毎回、エクセル報告書に「※手動適用済みのため対象外」と除外理由を手打ちする不毛な作業が発生
  • 現場は疲弊し、本当に危険なゼロデイ攻撃や設定不備を見落とす「アラート麻痺」に陥る

この不条理を現場から根絶するために、「Bashの標準機能とSQLiteだけで、適用済みパッチの引き算を行い、誤検知をゼロにする超軽量プローブ」 を自作しました。


設計思想:現場が本当に求めている3大要件

ツールを作るにあたり、以下の3つの制約を自分に課しました。

  1. 外部依存ゼロ(Pythonすら不要・Bash標準機能のみ):
    監視対象やエッジゲートウェイには、勝手にPythonライブラリや重いJavaランタイムを入れる権限がないことが多い。Bash標準の /dev/tcp ソケット機能だけで動かす。
  2. 高速・省メモリ(0.5秒・数MBで完了):
    重いDBやデーモンを常駐させず、数秒以内で判定を終わらせる。
  3. 「適用済みパッチ」の確実な引き算(手打ち台帳):
    現場のエンジニアが「このホストのこのCVEは修正済み」と記録した情報を、ローカルDB(SQLite)で即座に引き算する。

アーキテクチャ図・処理フロー・要点コード抜粋 (cve_lookup_db.sh)

アーキテクチャ詳細、処理フロー図、中核ロジックのコード抜粋(PoC)、およびパラメータ解説・トラブルシューティング手順は、GitHubリポジトリ(詳細技術リファレンス)にて管理・随時アップデートしています。
設計の全体像や要点スニペットの確認は以下のリンクをご参照ください。

👉 GitHubで詳細技術リファレンス・処理フローを見る (QIITA_ARTICLE_DETAIL_1.md)


実装のキモ:Bashでここまでできる!

1. Python不要!/dev/tcp による高速エージェントレスポート検査

LinuxのBashには、標準で /dev/tcp/ホスト/ポート という仮想デバイスを使ったTCPソケット通信機能が備わっています。これを使えば、nc や nmap すらインストールされていない最小構成の環境でもポート疎通が可能です。

2. SQLite WALモードによる「手動パッチ台帳」の引き算

パッチ適用履歴を管理するテーブルをSQLiteで超軽量に保持します。WAL(Write-Ahead Logging)モードを有効にすることで、並行アクセス時もロック競合を起こさずにミリ秒単位で突合できます。

診断実行時、検知されたCVEリストから applied_patches に登録されているレコードを SQLの SELECT 1 FROM applied_patches WHERE ip=? AND patch_id=? で引き算します。これだけで、現場が苦しんでいた「すでにパッチを当てたCVEのアラート」が画面から一瞬で消え去ります。


実際の動作ログ:実行時間0.3秒・過剰検知ゼロ

実際に現場の社内サーバー(Ubuntu 24.04)に対してプローブを実行した結果がこちらです。

1. 初回実行(パッチ未記録時)

# (Source: https://github.com/ojisantech/)
./cve_lookup_db.sh 192.168.1.200

実行ログ:

[TARGET] 192.168.1.200 (高速エージェントレスプローブ開始)
[PROBE] ポート 22,80 開放確認
[WARN] 以下の重要CVEが検出されました:
  - CVE-2024-6387 (OpenSSH regreSSHion (RCE) [CRITICAL])
==================================================
🚨 要対応の脆弱性: 1件 (至急パッチ適用または台帳登録を行ってください)
==================================================

2. パッチ適用を台帳に記録

# (Source: https://github.com/ojisantech/)
# 現場で apt update を実施した事実を台帳に1行記録
./cve_lookup_db.sh --record 192.168.1.200 CVE-2024-6387 "apt update && OpenSSH更新適用済み"

実行ログ:

[SUCCESS] 192.168.1.200 の CVE-2024-6387 を適用済み台帳に記録しました。

3. 再診断(引き算が作動)

# (Source: https://github.com/ojisantech/)
./cve_lookup_db.sh 192.168.1.200

実行ログ:

[TARGET] 192.168.1.200 (高速エージェントレスプローブ開始)
[PROBE] ポート 22,80 開放確認
[INFO] CVE-2024-6387 は適用済み(手動台帳確認)のため除外されました。
==================================================
✅ 危険な未対応脆弱性: 0件 (過剰検知ゼロ・安全)
==================================================

おわりに:セキュリティ運用は「現場の納得感」がすべて

どれほど多機能で高価な商用スキャナーであっても、「現場が直したはずのパッチを無視してアラートを出し続けるツール」は、最終的に誰にも見られなくなります。

セキュリティを形骸化させないためには、

  • 「本当に今、危険なものだけを通知する」
  • 「現場のエンジニアの作業実績(パッチ適用)を正当に評価して引き算する」

という泥臭い運用設計が不可欠だと痛感しています。

本記事で解説したアーキテクチャ図、処理フロー、要点コード抜粋やパラメータ設計、トラブルシューティング対応表は、GitHubリポジトリ(詳細技術リファレンス)にて公開しています。

👉 【第1弾 詳細技術リファレンス】

(※ 本リポジトリでは運用上の安全性を考慮し、完成品スクリプトの丸ごと公開ではなく、アーキテクチャ図・処理フロー・要点コード抜粋(PoC)を中心に順次追加・連載していく方針です。実環境への適用にあたっては、各環境のセキュリティポリシーや要件に合わせて十分な検証・設計を行ってください)

「うちの環境でも手打ちパッチ誤検知に悩んでいる」「エージェントレスで資産管理台帳と連動させたい」というインフラ担当者や情シスの方がいらっしゃいましたら、ぜひ参考にしてみてください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?