C2(Command & Control)サーバは、マルウェアに感染した端末を遠隔操作するための指令塔です。 攻撃者はその存在を隠すために HTTPS を多用しますが、SSL/TLS 通信には「指紋」が残ります。 本記事では、JA3/JA3S ハッシュ と JARM フィンガープリント を使った C2 サーバ追跡の仕組みを、初心者でも理解できるように解説します。
🔍 C2サーバとは何か?まず基礎から理解しよう
サイバー攻撃において、攻撃者は標的のコンピュータに侵入した後、そのマシンをリモートから操作し続ける必要があります。 そのために使われるのが C2(Command & Control)サーバ、日本語では「指令・制御サーバ」と呼ばれるインフラです。
感染端末(Bot)は定期的にC2サーバへ接続し、「次に何をすればよいか」という命令を受け取ります。 攻撃者はこのチャネルを通じて、ランサムウェアの実行・データの窃取・横断的侵害(ラテラルムーブメント)などを指示します。
💡 代表的なC2フレームワーク
・Cobalt Strike(2012年〜、ペンテスト用だが悪用多数)
・Metasploit Framework(オープンソース、汎用)
・Sliver(Go製、近年急増)
・Brute Ratel C4(2021年〜、AV回避特化)
・Havoc(2022年〜、オープンソース)
攻撃者はC2通信を正規トラフィックに偽装するため、HTTPS(TLS暗号化)を利用するケースが急増しています。 しかし暗号化されていても、TLS ハンドシェイクの段階で「どのクライアント/サーバソフトウェアが通信しているか」を示す痕跡が残ります。 それが本記事の核心である TLS フィンガープリント です。
🔐 TLS フィンガープリントとは?
HTTPS 通信が始まるとき、クライアントとサーバは TLS ハンドシェイク というやり取りを行い、 使用する暗号方式や証明書の情報を交換します。このハンドシェイクのパラメータの組み合わせは、 使用しているライブラリやフレームワークに依存するため、ほぼ一意な「指紋(フィンガープリント)」になります。
人間の指紋と同様に、このデジタル指紋を収集・照合することで、 「このサーバは Cobalt Strike を使っている」 といった識別が可能になります。
| パラメータ | 内容 |
|---|---|
| TLS バージョン | 1.0 / 1.2 / 1.3 など |
| Cipher Suites | 対応する暗号アルゴリズムのリスト |
| 拡張フィールド(Extensions) | SNI, ALPN, session ticket など |
| 楕円曲線(Elliptic Curves) | P-256, X25519 など |
| 圧縮方式 | null or Deflate など |
TLS Client Hello に含まれる主なパラメータ
🧬 JA3 / JA3S ハッシュ ── クライアント&サーバを「特定」する
JA3 とは
JA3 は 2017年に Salesforce の John Althouse、Jeff Atkinson、Josh Atkins が開発した、 TLS クライアントを識別するためのフィンガープリント手法です(名前の由来は3人のイニシャル)。
仕組みはシンプルです。TLS Client Hello パケットから以下の5つの値を抽出し、カンマ・ハイフンで結合した文字列を MD5 ハッシュ化 します。
- SSLVersion(TLS バージョン番号)
- Ciphers(暗号スイート番号リスト)
- Extensions(拡張番号リスト)
- EllipticCurves(楕円曲線番号リスト)
- EllipticCurvePointFormats(点形式番号リスト)
JA3 計算例(Cobalt Strike のデフォルト)
生文字列:771,49192-49191-49172-49171-57-56-51-50-53-47-10-5-255,0-11-10-35-22-23,23-24-25,0
JA3 ハッシュ:72a7c4bb6a5b2f5e15a61b3a23f05e49
この値は 使用するマルウェアのC2クライアント(Beacon)のコードを変更しない限り変わりません。 脅威インテリジェンスサービスが収集・公開しているJA3データベースと照合することで、 「このIPはCobalt Strikeらしい」という判断が可能になります。
JA3S とは
JA3S は同じチームが開発した、サーバ側のフィンガープリントです。 TLS Server Hello から SSLVersion・Ciphers・Extensions を抽出してMD5化します。 JA3(クライアント)と JA3S(サーバ)をペアで見ることで、 「誰が(どのマルウェアが)どのサーバ(どのC2フレームワーク)に接続しているか」という組み合わせ分析が可能になります。
JA3/JA3S の主要ツール
① Zeek(ネットワーク監視) + ja3 プラグイン
# Zeek インストール後、ja3 スクリプトを有効化
zeek -i eth0 /opt/zeek/share/zeek/site/ja3/ja3.zeek
# 出力例(ssl.log の一部)
# ts id.orig_h ja3 ja3s
# 1700000000 192.168.1.10 72a7c4bb6a5b2f5e15a61b3a23f05e49 (blank)
② tshark(Wiresharkのコマンドライン版)でpcapから抽出
# Client Hello の Cipher Suites を一覧表示
tshark -r capture.pcap \
-Y "tls.handshake.type == 1" \
-T fields \
-e ip.src -e tls.handshake.ciphersuite
③ Python ライブラリ ja3(pip install)
pip install pyja3
# pcap ファイルから JA3 ハッシュを一括抽出
python3 -m pyja3 -a capture.pcap
④ Suricata(IDS/IPS)
# suricata.yaml の tls ログに ja3 フィールドが自動記録される
# eve.json 例
{
"event_type": "tls",
"tls": {
"ja3": {"string": "...", "hash": "72a7c4bb6a5b2f5e15a61b3a23f05e49"},
"ja3s": {"string": "...", "hash": "b4ece4d5f13b3d3b5e7e1e3c4a7a2e1f"}
}
}
JA3 データベース・脅威インテリジェンス
- abuse.ch JA3 SSL Blacklist:悪意のあるJA3ハッシュのブラックリスト(無料)
- Salesforce ja3 GitHub:元祖JA3の実装とリスト
- VirusTotal:ファイル分析時にJA3情報を表示
- Shodan:インターネット上のサーバのJA3S情報を検索可能
🎯 JARM ── サーバを「能動的に」識別する
JARMとは何か
JARM(Just Another Reconnaissance Markup)は、2020年11月に Salesforce の研究チームが公開した、 TLS サーバを能動的に識別するためのフィンガープリント技術です。 JA3 がパッシブ(通信を傍受して記録)なのに対し、JARM はアクティブスキャン型です。
JARMは対象サーバに対して 10種類の特殊なTLS Client Hello を送信し、サーバがそれぞれにどう応答するかの パターンをハッシュ化して62文字の JARM フィンガープリントを生成します。 TLS ライブラリやそのバージョン・設定が同じであれば、同じJARMが生成されるため、 Cobalt Strike・Merlin・Covenant などのC2フレームワークを識別できます。
💡 JARMの62文字とは?
10回のプローブそれぞれの応答から 暗号スイート・ALPN・バージョン などを抽出し、 その組み合わせを SHA-256 でハッシュ化したものです。 前半32文字は応答パターンのシグネチャ、後半30文字はSHA-256ハッシュ由来の一意識別子です。
なぜJARMはC2追跡に有効なのか
多くのC2フレームワークは デフォルト設定のまま運用される ケースが非常に多いです。 実際、Salesforceの調査では、Cobalt Strike サーバの約 70% 以上がデフォルト証明書または デフォルトJARMを持つと報告されています(2020年当時)。
また、同一フレームワークから派生したC2サーバはIPアドレスや証明書が異なっていても 同一のJARMフィンガープリントを持ちます。 これにより「1つのC2を発見 → JARMで同種のC2をインターネット全体から列挙」という インフラマッピングが可能になります。
| C2 フレームワーク | 既知のJARM フィンガープリント(例) |
|---|---|
| Cobalt Strike 4.x | 07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1b |
| Metasploit Framework | 07d19d1ad21d21d07c42d43d000000aa99ce74e2c6d013c745aa52b5cc042d |
| Covenant | 2ad2ad0002ad2ad22c2ad2ad2ad2adce980c6a4a8d57f52d112c599d95b7a8 |
| Sliver | 3fd3fd15d3fd3fd21c3fd3fd3fd3fd9e5f3fd3fd3fd3fd44e3fd3fd3fd3fd |
| nginx(正規) | 27d40d40d29d40d1dc42d43d00041d4689ee210389f4f6b4b5b1b93f92252d |
※ フィンガープリントはバージョン・設定によって変化します。参考値です。
JARMの使い方 ── ツールとコマンド
① jarm(公式Pythonツール)
# インストール
git clone https://github.com/salesforce/jarm.git
cd jarm
pip3 install -r requirements.txt
# 単一ホストのスキャン
python3 jarm.py example.com
# 出力例
# Host: example.com | Port: 443
# JARM: 27d40d40d29d40d1dc42d43d00041d4689ee210389f4f6b4b5b1b93f92252d
# ポートを指定(C2は443以外も使う)
python3 jarm.py malicious-server.com -p 8443
# 複数ホストをファイルから一括処理
python3 jarm.py -i targets.txt -o results.csv
② nmap + JARM NSE スクリプト
# NSE スクリプトを使ったスキャン
nmap --script=tls-jarm -p 443 192.168.1.0/24
# 出力例
# PORT STATE SERVICE
# 443/tcp open https
# | tls-jarm:
# |_ 07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1b
③ zgrab2(大規模インターネットスキャン)
# CIDRブロックに対してJARMを取得
echo "203.0.113.0/24" | zgrab2 tls --jarm -o output.json
# jq でCobalt Strike のJARMだけフィルタ
cat output.json | jq 'select(.data.tls.result.jarm == "07d14d...")'
④ Shodan でのJARM検索(オンライン)
// Shodan 検索クエリ例
ssl.jarm:07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1b
// Cobalt Strike デフォルト証明書と組み合わせ
ssl.jarm:"07d14d..." ssl.cert.subject.cn:"Major Cobalt Strike"
🔎 SSL証明書ハッシュによるC2追跡
JARM や JA3 の他に、SSL証明書そのものを使ったC2追跡も非常に有効です。 多くの攻撃者は、C2サーバに自己署名証明書やデフォルト証明書を使います。 証明書の各フィールドや証明書全体のSHA-1/SHA-256ハッシュを追跡することで、 インフラを横断的に追跡できます。
証明書フィンガープリントの種類
- SHA-1 / SHA-256 フィンガープリント:証明書全体をハッシュ化した値。同一証明書ならIPが変わっても同値。
- Subject / Issuer の特徴:
CN=localhost、O=Internet Widgits Pty Ltdなどデフォルト文字列 - Subject Public Key Info(SPKI)ハッシュ:秘密鍵を使い回しているサーバを追跡
- 証明書シリアル番号:一意な値でキャンペーン内のサーバを紐付け
証明書ハッシュの取得方法
① openssl コマンド(最もシンプル)
# 対象サーバの証明書フィンガープリントを取得
echo | openssl s_client -connect target.com:443 2>/dev/null \
| openssl x509 -noout -fingerprint -sha256
# 出力例
# SHA256 Fingerprint=A1:B2:C3:D4:...:FF
# 証明書の詳細(Subject, Issuer, SAN など)
echo | openssl s_client -connect target.com:443 2>/dev/null \
| openssl x509 -noout -text
# SPKI ハッシュ(鍵の追跡に使用)
echo | openssl s_client -connect target.com:443 2>/dev/null \
| openssl x509 -noout -pubkey \
| openssl pkey -pubin -outform DER \
| sha256sum
② Censys / Shodan での証明書ハッシュ検索
// Censys(https://search.censys.io)
// SHA-256 ハッシュで全インターネットを検索
parsed.fingerprint_sha256: "a1b2c3d4e5f6..."
// Shodan
ssl.cert.fingerprint:"a1:b2:c3:..."
// Subject の特徴から追跡
ssl.cert.subject.cn:"Major Cobalt Strike"
ssl.cert.subject.o:"cobaltstrike"
③ Python + cryptography ライブラリ
import ssl, socket, hashlib
from cryptography import x509
from cryptography.hazmat.backends import default_backend
def get_cert_fingerprint(host, port=443):
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
with socket.create_connection((host, port), timeout=5) as sock:
with ctx.wrap_socket(sock, server_hostname=host) as ssock:
der = ssock.getpeercert(binary_form=True)
cert = x509.load_der_x509_certificate(der, default_backend())
sha256 = hashlib.sha256(der).hexdigest()
print(f"SHA-256: {sha256}")
print(f"Subject: {cert.subject}")
print(f"Issuer: {cert.issuer}")
print(f"Serial: {cert.serial_number}")
return sha256
get_cert_fingerprint("example.com")
Cobalt Strike デフォルト証明書の特徴
Cobalt Strike のデフォルト証明書(Malleable C2 未設定状態)には以下の特徴があり、 Shodan や Censys で容易に発見できます。
CN = Major Cobalt StrikeO = cobaltstrike- 有効期間:発行日から約 10年
- 自己署名(Issuer = Subject)
- SHA-1フィンガープリント:
6ece5ece4192683d2d84e25b0ba7e04f9cb7eb7c(旧版)
🔗 実践:複数手法を組み合わせたC2インフラ追跡フロー
実際のインシデントレスポンスや脅威インテリジェンス収集では、 JA3・JARM・証明書ハッシュを組み合わせることで、 1台のC2サーバ発見 → キャンペーン全体のインフラ特定という連鎖が可能です。
- パッシブDNS・ファイアウォールログから怪しいIPを発見
例:社内端末が深夜に不審な IP へ HTTPS 通信を繰り返している - JA3 でクライアント(マルウェア)のフィンガープリントを確認
tsharkやSuricataで JA3 ハッシュを抽出 → 脅威インテリジェンスと照合 - JARM でサーバ側のC2フレームワークを特定
python3 jarm.py 203.0.113.10を実行 → Cobalt Strike に一致 - 証明書ハッシュ・SPKIを取得してShodan/Censysで検索
同じ証明書または同じ鍵ペアを使う他のIPを発見 → 攻撃インフラを列挙 - IOC(侵害指標)としてブロックリストに追加
発見した全IPをファイアウォール・EDRに展開
⚠️ 注意:アクティブスキャンの倫理と法律
JARMのようなアクティブスキャンを自組織管理外のサーバに対して行うことは、 国によっては不正アクセス禁止法等に抵触する可能性があります。 Shodan・Censys などの既存のスキャンデータベースを活用し、 自組織ネットワーク以外への直接スキャンは慎重に行いましょう。
🛡️ 防御側の視点:JARMとJA3を組み込んだセキュリティ監視
攻撃を受ける側(ブルーチーム・SOC)として、これらのフィンガープリントを 日常的なネットワーク監視に組み込むことで、検知精度が大幅に向上します。
- Suricata / Zeek で全アウトバウンド TLS セッションのJA3を自動記録
- 既知の悪意あるJA3ハッシュ(abuse.ch等から取得)とのリアルタイム照合
- 新規IPへの接続でJARMを自動取得し、既知C2フィンガープリントと比較
- Elastic SIEM / Splunk にJA3フィールドを取り込み、異常なクライアントフィンガープリントのアラート設定
📚 まとめ
SSL/TLS は通信内容を暗号化しますが、そのハンドシェイクの「形」は隠せません。 JA3・JA3S・JARM・証明書ハッシュという4つの観点から、 攻撃者のインフラを暗号化越しに追跡することが可能です。
| 手法 | 何を識別するか | 主なツール | スキャン種別 |
|---|---|---|---|
| JA3 | TLSクライアント(マルウェア) | Zeek, Suricata, pyja3 | パッシブ |
| JA3S | TLSサーバ(C2) | Zeek, Suricata | パッシブ |
| JARM | TLSサーバのフレームワーク | jarm.py, nmap, zgrab2 | アクティブ |
| 証明書ハッシュ | 同一証明書を使うサーバ群 | openssl, Shodan, Censys | 両対応 |
TLS フィンガープリント手法の比較
初心者の方はまず Suricata を導入して JA3 ログを取り始める ことをお勧めします。 EVE JSON 形式で自動的にJA3ハッシュが記録されるため、追加開発なしに脅威検知に活用できます。 さらに一歩進んで JARM スキャンや Shodan での証明書追跡を組み合わせることで、 攻撃インフラ全体を可視化する「プロ級の」脅威ハンティングが実現できます。
📖 参考リソース
・Salesforce JA3 GitHub
・Salesforce JARM GitHub
・abuse.ch JA3 SSL Blacklist
・Censys Internet Search
・Shodan


コメント