前回の初級〜中級編で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 Name | ssl.cert.subject.cn:"*.example.com" | 自社ワイルドカード証明書で保護されたホストを全列挙 |
ssl.cert.subject.o: | 証明書の組織名(O) | ssl.cert.subject.o:"Example Corp" | 組織が発行・取得した証明書の全ホストを横断調査 |
ssl.cert.issuer.cn: | 発行者のCommon Name | ssl.cert.issuer.cn:"Let's Encrypt" | 特定の認証局が発行した証明書を持つホストを絞り込む |
ssl.cert.subject.san: | Subject Alternative Name | ssl.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インフラや、自社の想定外ホストを発見するために特に有効な技術です。手順は以下の通りです。
- 起点となるホストの証明書情報を取得する:既知の不審IPや自社ドメインのホストをShodanで調べ、証明書のCN・O・SANを確認する。
- 組織名または SAN でピボットする:同じ組織名・SANを持つ他のホストを横断的に検索する。
- フィンガープリントまたはシリアルで追跡する:同一の証明書が複数の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:JP | AWS上で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:JP | TLS 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 Strike | ssl.jarm:"07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1" | デフォルトのTLS実装によるJARMフィンガープリント | 最重要 |
| Cobalt Strike | product:"Cobalt Strike Beacon" port:443 OR port:80 | Shodanがプロダクト識別したケース | |
| Metasploit | ssl.jarm:"07d19d1ad21d21d07c42d43d000000543d1813b7de880abb6d7bca..." port:4444 | MetasploitのデフォルトリスナーのJARM | |
| Sliver C2 | ssl.cert.subject.o:"Generic" ssl.cert.subject.cn:"multiplayer" port:443 | Sliverのデフォルト証明書プロファイル | |
| Brute Ratel C4 | ssl.jarm:"3fd21b20d21d21d21c21b21b21b21b083cbd..." port:443 | BRCのデフォルトJARMパターン | |
| Havoc C2 | "Havoc" port:443 ssl.cert.subject.cn:"Havoc" | デフォルト証明書にHavocと記載 | |
| Deimos / PoshC2 | http.title:"IIS Windows Server" ssl.jarm:"..." port:443 | IIS偽装+特定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プロトコル別の検出クエリ
| プロトコル | ポート | クエリ | 対象システム | リスク |
|---|---|---|---|---|
| Modbus | 502 | port:502 "Modbus" | PLC・工場設備 | 最高 |
| DNP3 | 20000 | port:20000 "DNP3" | 電力・水道施設 | 最高 |
| BACnet | 47808 | port:47808 "BACnet" | ビル管理システム | 高 |
| EtherNet/IP | 44818 | port:44818 "EtherNet/IP" | Allen-Bradley PLC | 最高 |
| IEC 60870-5-104 | 2404 | port:2404 "IEC 60870" | 電力監視システム | 最高 |
| MQTT | 1883 | port:1883 "MQTT" -user | IoTゲートウェイ・センサー | 高 |
| OPC-UA | 4840 | port:4840 "OPC-UA" | 製造ライン・SCADA | 高 |
| Siemens S7 | 102 | port: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:JP | RCEが可能な脆弱な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-XXXXX | CVE公開後即時 |
9. Shodan の限界と補完ツールの選択
| Shodanの限界 | 補完ツール | 補完できる情報 |
|---|---|---|
| スキャン頻度が低い(数週間単位) | Censys / 自前nmapスキャン | より新鮮なスキャン結果 |
| DNS・ドメイン情報が限定的 | SecurityTrails / RiskIQ PassiveTotal | パッシブDNS・ドメイン履歴 |
| IPレピュテーション情報なし | VirusTotal / AbuseIPDB / GreyNoise | 悪性IPかどうかの判定 |
| HTTP応答本文の詳細は限定的 | FOFA / ZoomEye | Webページ内容・特定フレームワーク検出 |
| マルウェアサンプルの紐付けなし | Malware Bazaar / ThreatFox | IoC・マルウェアハッシュと IP の関連付け |
| 脅威アクターの帰属なし | Recorded Future / Mandiant TI | APTグループとのインフラ関連付け |
まとめ: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


コメント