【上級者向け】Shodan 高度な検索クエリ完全リファレンス|SSL/TLS解析・脅威インテリジェンス・OSINT自動化・SIEM連携まで

解析

前回の初級〜中級編でShodanの基本フィルターとポート別の調査手法を習得した方へ向けて、本記事では SSL/TLS証明書の深堀り解析、ASN・BGPルーティング情報の活用、Shodanデータを用いた脅威インテリジェンス構築、Facets/Aggregation APIによるデータ統計分析、CI/CDパイプラインへの統合、SIEMへのリアルタイム連携 まで、実務で差がつく高度なテクニックを体系的に解説します。

⚠️ 免責事項
本記事で紹介する手法はすべて、自分が管理・所有するシステムの診断またはセキュリティ研究・学習を目的としたものです。許可なく他者のシステムへアクセスする行為は不正アクセス禁止法等に抵触します。本記事の内容の悪用に関して筆者および当サイトは一切の責任を負いません。


1. SSL/TLS証明書フィルターの高度な活用

ShodanはHTTPS通信時のSSL/TLS証明書情報を構造化して保持しており、証明書の各フィールドを個別に検索できます。これは 証明書ベースのホスト追跡(Certificate Pivoting) と呼ばれるOSINT技術の基盤となります。

1-1. SSL証明書フィルターの全体像

フィルター対象フィールドクエリ例活用場面
ssl.cert.subject.cn:証明書のCommon Namessl.cert.subject.cn:"*.example.com"自社ワイルドカード証明書で保護されたホストを全列挙
ssl.cert.subject.o:証明書の組織名(O)ssl.cert.subject.o:"Example Corp"組織が発行・取得した証明書の全ホストを横断調査
ssl.cert.issuer.cn:発行者のCommon Namessl.cert.issuer.cn:"Let's Encrypt"特定の認証局が発行した証明書を持つホストを絞り込む
ssl.cert.subject.san:Subject Alternative Namessl.cert.subject.san:"internal.example.com"SANに内部ホスト名が含まれている証明書を発見する
ssl.cert.fingerprint:証明書のフィンガープリントssl.cert.fingerprint:"AA:BB:CC:..."同一証明書を使い回しているC2サーバーの追跡
ssl.cert.serial:証明書のシリアル番号ssl.cert.serial:"1234567890abcdef"証明書の一意識別子で同一インフラを追跡
ssl.cert.expired:証明書の有効期限切れssl.cert.expired:true country:JP自社の期限切れ証明書を一括発見する
ssl.cipher.name:使用暗号スイート名ssl.cipher.name:"RC4-SHA"廃止済みの弱い暗号を使っているホストの特定
ssl.version:TLSプロトコルバージョンssl.version:"SSLv2"SSL 2.0/3.0 や TLS 1.0など廃止バージョンの検出
ssl.jarm:JARMフィンガープリントssl.jarm:"29d29d..."C2フレームワーク(Cobalt Strike等)の指紋でサーバーを追跡

1-2. Certificate Pivoting の実践手順

攻撃者のC2インフラや、自社の想定外ホストを発見するために特に有効な技術です。手順は以下の通りです。

  1. 起点となるホストの証明書情報を取得する:既知の不審IPや自社ドメインのホストをShodanで調べ、証明書のCN・O・SANを確認する。
  2. 組織名または SAN でピボットする:同じ組織名・SANを持つ他のホストを横断的に検索する。
  3. フィンガープリントまたはシリアルで追跡する:同一の証明書が複数のIPで使われている場合、同一のインフラである可能性が高い。
# ステップ1:特定ドメインのSSL証明書を持つホストを全列挙
ssl.cert.subject.cn:"*.target-example.com"

# ステップ2:同じ組織名を持つホストにピボット
ssl.cert.subject.o:"Target Example Corporation"

# ステップ3:SANに内部ホスト名が漏れているケースを確認
ssl.cert.subject.san:"internal" ssl.cert.subject.o:"Target Example Corporation"

# JARMフィンガープリントでCobalt Strikeのデフォルト証明書を持つホストを追跡
ssl.jarm:"07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1"

📌 JARM とは
JARMはSalesforceが開発したTLSフィンガープリント手法で、サーバーのTLS実装の特性を元に一意のハッシュ値を生成します。Cobalt Strike・Metasploit・Empire など主要なC2フレームワークにはそれぞれ特徴的なJARMが存在し、攻撃インフラの特定に活用されています。


2. ASN・BGP情報を活用したインフラ調査

2-1. ASNフィルターとその応用

AS(Autonomous System)番号を使うことで、特定のISP・クラウドプロバイダー・組織が管理するIPレンジ全体を一括調査できます。net: フィルターでCIDRを逐一指定するよりも広域かつ効率的な調査が可能です。

クエリ説明活用例
asn:AS15169特定ASN(Google)のホストを検索クラウドプロバイダー上の公開サービスを一括調査
asn:AS15169 port:22 "OpenSSH"特定ASN内のSSHホストを絞り込む自社クラウド環境のSSH開放状況を確認
org:"Amazon" port:3389 country:JPAWS上でRDPが開いている日本のホストクラウド移行後のRDP開放の見落とし確認
isp:"NTT Communications" port:23特定ISPでTelnetが開いているホスト顧客環境やレガシー機器の残存確認

💡 ASN番号の調べ方
自社・調査対象のASN番号は bgp.he.net(Hurricane Electric BGP Toolkit)や ipinfo.io で組織名から検索できます。大企業は複数のASNを持っている場合があるため、複数のASNを OR で繋いで調査するとより網羅的です。

2-2. Shodanのネットワーク調査とCIDRの自動展開

大規模な組織の全IPレンジを把握するには、BGP情報からCIDRブロックを取得してShodan CLIに渡す自動化スクリプトが有効です。

import shodan
import requests

API_KEY = "YOUR_API_KEY"
api = shodan.Shodan(API_KEY)

# bgp.he.netのAPIからASNのCIDRブロック一覧を取得(例:AS7679 NTT)
asn = "AS7679"
response = requests.get(f"https://bgp.he.net/AS{asn.replace('AS','')}#_prefixes")
# ※ 実際の運用ではwhoisやripestat APIを使用

# ASN全体をShodanで検索
results = api.search(f"asn:{asn} port:22 OR port:3389 OR port:23")
print(f"ASN {asn} の高リスクポート開放ホスト数: {results['total']}")

for match in results["matches"]:
    print(f"  {match['ip_str']}:{match['port']} | {match.get('org','')} | {match.get('product','')}")

3. Facets(統計集計)APIによるマクロ分析

Shodanの Facets API を使うと、検索結果を特定のフィールドで集計し、統計として取得できます。個々のホストを調べるのではなく、「全体の傾向を把握する」マクロ分析に最適です。

3-1. Facets APIの基本

import shodan
import json

API_KEY = "YOUR_API_KEY"
api = shodan.Shodan(API_KEY)

# 日本国内のHTTPSサービスをOSとバージョンで集計
result = api.search(
    "country:JP port:443",
    facets=[
        ("os", 10),         # OS上位10件
        ("product", 10),    # プロダクト上位10件
        ("version", 10),    # バージョン上位10件
        ("org", 10),        # 組織上位10件
    ]
)

print("=== OS分布 ===")
for item in result["facets"].get("os", []):
    print(f"  {item['value']:40s}: {item['count']:,}")

print("\n=== 製品分布 ===")
for item in result["facets"].get("product", []):
    print(f"  {item['value']:40s}: {item['count']:,}")

3-2. 経時変化の追跡:Shodan Trends との組み合わせ

Shodan Trends(trends.shodan.io)はFacets APIの時系列版で、特定のクエリに一致するホスト数の推移をグラフで確認できます。たとえば「Log4Shellパッチ適用後にCVE-2021-44228脆弱ホストがどれだけ減少したか」「特定の廃止プロトコルの使用率推移」などを可視化するのに活用できます。

分析テーマTrendsクエリ例把握できる情報
EOLプロトコルの残存推移ssl.version:"TLSv1" country:JPTLS 1.0廃止対応の進捗
脆弱バージョンの削減率product:"Apache httpd" version:"2.4.49"CVE-2021-41773パッチ適用状況の業界推移
Log4Shell残存ホスト数vuln:CVE-2021-44228対応が遅れているホストの推移
Telnet利用率の変化port:23 country:JPレガシープロトコル撲滅の進捗

4. 高度なOSINTクエリ:C2・マルウェアインフラの追跡

脅威インテリジェンス活動では、Shodanを使って攻撃者のC2(コマンド&コントロール)インフラや悪意のある活動に使われているサーバーを特定・追跡します。以下のクエリはいずれも 防御・調査目的でのみ 使用してください。

4-1. 主要C2フレームワークの検出クエリ

C2フレームワーク検出クエリ検出の根拠備考
Cobalt Strikessl.jarm:"07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1"デフォルトのTLS実装によるJARMフィンガープリント最重要
Cobalt Strikeproduct:"Cobalt Strike Beacon" port:443 OR port:80Shodanがプロダクト識別したケース
Metasploitssl.jarm:"07d19d1ad21d21d07c42d43d000000543d1813b7de880abb6d7bca..." port:4444MetasploitのデフォルトリスナーのJARM
Sliver C2ssl.cert.subject.o:"Generic" ssl.cert.subject.cn:"multiplayer" port:443Sliverのデフォルト証明書プロファイル
Brute Ratel C4ssl.jarm:"3fd21b20d21d21d21c21b21b21b21b083cbd..." port:443BRCのデフォルトJARMパターン
Havoc C2"Havoc" port:443 ssl.cert.subject.cn:"Havoc"デフォルト証明書にHavocと記載
Deimos / PoshC2http.title:"IIS Windows Server" ssl.jarm:"..." port:443IIS偽装+特定JARM値の組み合わせ

🚨 注意:C2追跡クエリの倫理的使用
上記クエリで発見されるホストには、正規のペネトレーションテスト用サーバーが含まれる場合もあります。発見したIPへの接続・アクセス試行は一切行わず、情報収集のみに留めてください。悪意のあるC2と確認された場合は、ISP・CERT・法執行機関への通報など、適切なチャネルで対応することを推奨します。

4-2. フィッシングインフラ・悪用サービスの検出

# デフォルト証明書のままのGoPhishサーバー(フィッシングキット)
ssl.cert.subject.cn:"Gophish" port:3333

# EvilGinxプロキシの検出(ログインページ中間者攻撃)
http.title:"EvilGinx" port:443

# 自己署名証明書+高ポート(不審なHTTPS)
ssl.cert.issuer.cn:ssl.cert.subject.cn port:4443 OR port:8443 OR port:9443

# 新規取得ドメイン+Let's Encrypt+RDPという組み合わせ(典型的なフィッシング踏み台)
ssl.cert.issuer.cn:"Let's Encrypt" port:3389

5. 産業制御システム(ICS/SCADA)の高度な調査クエリ

重要インフラのセキュリティ調査において、ICS/SCADAプロトコルがインターネットに露出していないかを確認することは最重要項目の一つです。以下はセキュリティ研究目的での参照用です。

5-1. ICS/SCADAプロトコル別の検出クエリ

プロトコルポートクエリ対象システムリスク
Modbus502port:502 "Modbus"PLC・工場設備最高
DNP320000port:20000 "DNP3"電力・水道施設最高
BACnet47808port:47808 "BACnet"ビル管理システム
EtherNet/IP44818port:44818 "EtherNet/IP"Allen-Bradley PLC最高
IEC 60870-5-1042404port:2404 "IEC 60870"電力監視システム最高
MQTT1883port:1883 "MQTT" -userIoTゲートウェイ・センサー
OPC-UA4840port:4840 "OPC-UA"製造ライン・SCADA
Siemens S7102port:102 "Siemens S7"Siemens PLC(Stuxnet対象)最高

6. Shodan StreamingAPIによるリアルタイム監視

通常のShodan検索はインデックス済みデータへの検索ですが、Streaming API を使うとShodanのクローラーが新たに発見・更新したホスト情報をリアルタイムで受信できます。これにより、自社ネットワークへの変更をほぼリアルタイムで検知するシステムを構築できます。

6-1. Streaming APIの基本実装

import shodan
import json
import datetime

API_KEY = "YOUR_API_KEY"
api = shodan.Shodan(API_KEY)

# 自社のネットワーク範囲を監視するフィルター
MY_NETWORK = "203.0.113.0/24"

print(f"[{datetime.datetime.now()}] ストリーミング監視を開始します: {MY_NETWORK}")

try:
    # alertを作成してストリームを受信(有料プラン必要)
    for banner in api.stream.alert():
        ip   = banner.get("ip_str", "N/A")
        port = banner.get("port", "N/A")
        prod = banner.get("product", "N/A")
        org  = banner.get("org", "N/A")
        ts   = banner.get("timestamp", "N/A")

        # 高リスクポートの場合に即アラート
        HIGH_RISK_PORTS = {22, 23, 3389, 5900, 6379, 27017, 9200, 2375}
        if port in HIGH_RISK_PORTS:
            print(f"[ALERT] {ts} | {ip}:{port} | {prod} | {org}")

            # Slack Webhookへの通知(任意)
            # requests.post(SLACK_WEBHOOK, json={"text": f"Shodan Alert: {ip}:{port} ({prod})"})

except shodan.exception.APIError as e:
    print(f"APIエラー: {e}")

6-2. SplunkへのStreaming API連携

# Splunk HEC(HTTP Event Collector)へリアルタイム転送するスクリプト
import shodan, requests, json, datetime

API_KEY    = "YOUR_SHODAN_API_KEY"
SPLUNK_HEC = "https://splunk-server:8088/services/collector/event"
SPLUNK_TOK = "YOUR_HEC_TOKEN"

api = shodan.Shodan(API_KEY)

def send_to_splunk(banner):
    payload = {
        "time":       datetime.datetime.now().timestamp(),
        "sourcetype": "shodan:stream",
        "index":      "security",
        "event": {
            "ip":        banner.get("ip_str"),
            "port":      banner.get("port"),
            "product":   banner.get("product"),
            "version":   banner.get("version"),
            "org":       banner.get("org"),
            "country":   banner.get("location", {}).get("country_code"),
            "timestamp": banner.get("timestamp"),
            "vulns":     list(banner.get("vulns", {}).keys()),
        }
    }
    requests.post(
        SPLUNK_HEC,
        headers={"Authorization": f"Splunk {SPLUNK_TOK}"},
        data=json.dumps(payload),
        verify=False
    )

for banner in api.stream.alert():
    send_to_splunk(banner)
    print(f"Forwarded: {banner.get('ip_str')}:{banner.get('port')}")

7. CI/CDパイプラインへのShodan統合

インフラのデプロイ後に自動でShodanチェックを走らせることで、「デプロイ直後に不要なポートが開いていないか」を継続的に検証するセキュリティゲートを実装できます。

7-1. GitHub ActionsでのShodanチェック実装

# .github/workflows/shodan-check.yml

name: Shodan Security Check

on:
  push:
    branches: [ main ]
  schedule:
    - cron: '0 9 * * 1'   # 毎週月曜9時に定期実行

jobs:
  shodan-audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: pip install shodan requests

      - name: Run Shodan audit
        env:
          SHODAN_API_KEY: ${{ secrets.SHODAN_API_KEY }}
          TARGET_CIDR:    ${{ secrets.TARGET_CIDR }}
        run: python scripts/shodan_audit.py

      - name: Upload audit report
        uses: actions/upload-artifact@v3
        with:
          name: shodan-audit-report
          path: shodan_report.json
# scripts/shodan_audit.py
import shodan, json, os, sys

api = shodan.Shodan(os.environ["SHODAN_API_KEY"])
cidr = os.environ["TARGET_CIDR"]

FORBIDDEN_PORTS = {23, 5900, 2375, 6379, 27017, 9200}
findings = []

results = api.search(f"net:{cidr}")
for host in results["matches"]:
    port = host.get("port")
    if port in FORBIDDEN_PORTS:
        findings.append({
            "ip":      host.get("ip_str"),
            "port":    port,
            "product": host.get("product", ""),
            "severity": "CRITICAL"
        })

with open("shodan_report.json", "w") as f:
    json.dump(findings, f, indent=2)

if findings:
    print(f"[FAIL] {len(findings)} 件の禁止ポートが検出されました")
    for f in findings:
        print(f"  {f['ip']}:{f['port']} ({f['product']})")
    sys.exit(1)   # CI失敗として扱う
else:
    print("[PASS] 禁止ポートは検出されませんでした")

8. 高度な複合クエリ:実務シナリオ別チートシート

8-1. レッドチーム・脅威インテリジェンス用

シナリオ複合クエリポイント
自己署名証明書の管理画面を横断検索ssl.cert.issuer.cn:ssl.cert.subject.cn http.title:"admin" country:JP自己署名+adminタイトルは管理コンソールの典型
デフォルト認証情報が残っている機器http.title:"Please login" "default password" country:JPデフォルトパスワードの記載があるログイン画面
Kibanaダッシュボードが認証なしで公開port:5601 product:"Kibana" country:JP -http.title:"Login"ログインページなしのKibanaは即データ漏えいリスク
Grafanaの認証なし公開port:3000 product:"Grafana" http.title:"Grafana" country:JP監視ダッシュボードが外部公開されているケース
Jupyter Notebookが認証なし公開port:8888 http.title:"Jupyter Notebook" -"login"RCE(任意コード実行)に直結する極めて危険な露出
Apache Hadoopのリソースマネージャー公開port:8088 http.title:"Hadoop" country:JPRCEが可能な脆弱なHadoop管理UIの露出
HashiCorp Vaultが認証なしで公開port:8200 product:"Vault" http.title:"Vault"秘密情報管理基盤が直接露出している最悪のケース
Kubernetes Dashboardの認証なしport:443 http.title:"Kubernetes Dashboard" -"login"コンテナ基盤全体が乗っ取られるリスク

8-2. ディフェンシブ・定期診断用クエリ

診断目的クエリ確認頻度
自社全体の最新露出サマリーnet:自社CIDR週次
期限切れSSL証明書の確認net:自社CIDR ssl.cert.expired:true月次
弱い暗号スイートの使用確認net:自社CIDR ssl.version:"TLSv1" OR ssl.version:"TLSv1.0"月次
新規に開放されたポートの検知net:自社CIDR after:2024-01-01週次
EOL OSの残存確認net:自社CIDR os:"Windows Server 2008" OR os:"Windows Server 2012"月次
新たなCVE対象ホストの確認net:自社CIDR vuln:CVE-2024-XXXXXCVE公開後即時

9. Shodan の限界と補完ツールの選択

Shodanの限界補完ツール補完できる情報
スキャン頻度が低い(数週間単位)Censys / 自前nmapスキャンより新鮮なスキャン結果
DNS・ドメイン情報が限定的SecurityTrails / RiskIQ PassiveTotalパッシブDNS・ドメイン履歴
IPレピュテーション情報なしVirusTotal / AbuseIPDB / GreyNoise悪性IPかどうかの判定
HTTP応答本文の詳細は限定的FOFA / ZoomEyeWebページ内容・特定フレームワーク検出
マルウェアサンプルの紐付けなしMalware Bazaar / ThreatFoxIoC・マルウェアハッシュと IP の関連付け
脅威アクターの帰属なしRecorded Future / Mandiant TIAPTグループとのインフラ関連付け

まとめ:Shodanを「攻撃面管理(ASM)」の基盤として設計する

本記事で解説した高度なテクニックを整理します。

  • SSL/TLS Certificate Pivoting:証明書のCN・O・SAN・フィンガープリント・JARMを起点に、同一インフラのホストを横断的に追跡する
  • ASN・BGP活用:ISPや組織単位でのマクロな露出調査を効率化し、CIDRの手動入力に頼らない検索を実現する
  • Facets APIによるマクロ分析:個別ホストの調査から、業界全体・自社全体の統計的傾向把握へと視野を広げる
  • C2インフラ追跡:JARMフィンガープリント・デフォルト証明書パターンを活用して攻撃者のインフラを特定・監視する
  • Streaming APIとSIEM連携:リアルタイムの変化検知とSplunk等への自動転送で、継続的な攻撃面監視を実現する
  • CI/CDへの統合:GitHub Actionsなどにセキュリティゲートを組み込み、インフラ変更のたびに自動でShodanチェックを走らせる

これらの手法を組み合わせることで、Shodanは単なる「検索エンジン」から Attack Surface Management(ASM:攻撃面管理)プラットフォーム の中核へと進化します。自社資産の継続的な可視化と、外部からの見え方の常時把握が、現代のセキュリティ運用における最重要課題の一つです。


参考リソース

  • Shodan Developer API ドキュメント:developer.shodan.io
  • JARM GitHub(Salesforce Engineering):github.com/salesforce/jarm
  • Censys(SSL証明書特化の補完ツール):censys.io
  • GreyNoise(Shodanと組み合わせるIPノイズフィルタリング):greynoise.io
  • RiskIQ / PassiveTotal(パッシブDNS・Certificate Pivoting)
  • MITRE ATT&CK T1596(Search Open Technical Databases):attack.mitre.org
  • Shodan Trends(時系列トレンド分析):trends.shodan.io

コメント