JA3フィンガープリントとは?基本概念をわかりやすく解説
「JA3」という言葉を初めて聞いた方も多いかもしれません。JA3とは、TLS(Transport Layer Security)通信のClient Helloパケットから生成されるフィンガープリント(指紋)のことです。2017年にSalesforceのセキュリティチーム(John Althouse、Jeff Atkinson、Josh Atkins)によって開発されました。名前の「JA3」は、3人の頭文字に由来しています。
TLS通信が始まる際、クライアント(ブラウザやアプリ)はサーバーに対して「Client Hello」というメッセージを送ります。このClient Helloには、以下のような情報が含まれています。
- TLSバージョン
- 暗号スイート(Cipher Suites)の一覧
- 拡張機能(Extensions)の一覧
- 楕円曲線(Elliptic Curves)の情報
- 楕円曲線ポイントフォーマット
JA3は、これらの情報を特定の順序で結合し、MD5ハッシュ値として32文字の文字列に変換したものです。同じクライアントソフトウェアであれば、基本的に同じJA3ハッシュが生成されます。これにより、通信元のソフトウェアを識別できるのです。
例えば、Google Chrome 120とFirefox 121では異なるJA3ハッシュが生成されます。また、マルウェアが使用するTLSライブラリも固有のJA3ハッシュを持つため、悪意のある通信の検知にも活用されています。
なお、サーバー側の応答である「Server Hello」から生成されるフィンガープリントはJA3Sと呼ばれます。JA3とJA3Sを組み合わせることで、より精度の高い通信の識別が可能になります。
なぜBashでJA3を扱うのか?実務でのメリットと活用シーン
JA3フィンガープリントの取得・分析には、PythonやGoで書かれた専用ツールも存在します。しかし、Bash(シェルスクリプト)で扱うメリットは数多くあります。
軽量で即座に実行できる
Bashスクリプトは追加のランタイム環境を必要としません。サーバーにSSH接続した直後から、すぐにJA3関連の操作を実行できます。緊急のセキュリティ調査では、この即応性が非常に重要です。
パイプラインとの親和性が高い
Bashの最大の強みは、コマンドをパイプで連結できることです。tcpdumpでキャプチャしたデータを、awkやsedで加工し、JA3ハッシュの算出まで一気に処理できます。
CI/CDやcronとの連携が容易
JA3ハッシュの定期的な監視やアラート発報を、cronジョブやCI/CDパイプラインに組み込むことが簡単にできます。Pythonスクリプトを別途管理する必要がありません。
主な活用シーン
- セキュリティ監視:ネットワーク上の不審なTLS通信をJA3ハッシュで検知
- Bot対策:Webサーバーへのアクセスが正規ブラウザかBotかを判別
- フォレンジック調査:インシデント発生時にpcapファイルからJA3を抽出・分析
- 脅威インテリジェンス:既知のマルウェアのJA3ハッシュとの照合
- アセット管理:社内ネットワーク上のクライアントソフトウェアの棚卸し
特に、少人数のセキュリティチームやインフラエンジニアにとって、Bashで手軽にJA3分析ができることは大きな武器になります。
BashでJA3ハッシュを取得する具体的な方法
ここからは、実際にBashを使ってJA3フィンガープリントを取得する方法を、ステップバイステップで解説します。
前提となるツールのインストール
JA3をBashで扱うには、以下のツールが必要です。
- tshark:Wiresharkのコマンドライン版。パケットキャプチャと解析に使用
- openssl:MD5ハッシュの計算に使用
- awk / sed:テキスト処理に使用
Ubuntu/Debianの場合、以下のコマンドでインストールできます。
sudo apt update && sudo apt install -y tshark openssl
CentOS/RHELの場合は以下の通りです。
sudo yum install -y wireshark openssl
ステップ1:TLS通信のキャプチャ
まず、tcpdumpまたはtsharkでTLS通信をキャプチャします。
sudo tcpdump -i eth0 -w /tmp/capture.pcap 'tcp port 443' -c 1000
このコマンドは、eth0インターフェースのポート443(HTTPS)の通信を最大1000パケットまでキャプチャし、pcapファイルに保存します。
ステップ2:tsharkでClient Helloを抽出
キャプチャしたpcapファイルから、Client Helloメッセージの情報を抽出します。
tshark -r /tmp/capture.pcap -Y 'tls.handshake.type == 1' -T fields -e tls.handshake.version -e tls.handshake.ciphersuite -e tls.handshake.extension.type -e tls.handshake.extensions_supported_group -e tls.handshake.extensions_ec_point_format
このコマンドでは、TLSハンドシェイクタイプ1(Client Hello)をフィルタリングし、JA3の算出に必要な5つのフィールドを抽出しています。
ステップ3:JA3文字列の生成とハッシュ化
抽出したフィールドを結合してJA3文字列を作り、MD5ハッシュを算出します。以下は、この一連の処理を行うBashスクリプトの例です。
#!/bin/bash
PCAP_FILE="$1"
tshark -r "$PCAP_FILE" -Y 'tls.handshake.type == 1' -T fields
-e tls.handshake.version
-e tls.handshake.ciphersuite
-e tls.handshake.extension.type
-e tls.handshake.extensions_supported_group
-e tls.handshake.extensions_ec_point_format
2>/dev/null | while IFS=$'t' read -r version ciphers extensions curves formats; do
# カンマ区切りに変換
ciphers=$(echo "$ciphers" | tr ',' '-' | sed 's/-/,/g')
extensions=$(echo "$extensions" | tr ',' '-' | sed 's/-/,/g')
curves=$(echo "$curves" | tr ',' '-' | sed 's/-/,/g')
formats=$(echo "$formats" | tr ',' '-' | sed 's/-/,/g')
# JA3文字列を生成
ja3_string="${version},${ciphers},${extensions},${curves},${formats}"
# MD5ハッシュを計算
ja3_hash=$(echo -n "$ja3_string" | openssl md5 | awk '{print $2}')
echo "JA3 String: $ja3_string"
echo "JA3 Hash: $ja3_hash"
echo "---"
done
このスクリプトをja3_extract.shとして保存し、以下のように実行します。
chmod +x ja3_extract.sh
./ja3_extract.sh /tmp/capture.pcap
出力例は以下のようになります。
JA3 String: 771,4866-4867-4865-49196-49200-159-52393-52392-52394-49195-49199-158-49188-49192-107-49187-49191-103-49162-49172-57-49161-49171-51-157-156-61-60-53-47-255,0-11-10-35-22-23-13-43-45-51-21,29-23-30-25-24,0-1-2
JA3 Hash: e7d705a3286e19ea42f587b344ee6865
GREASE値の除外について
注意すべき重要なポイントがあります。Google Chromeなどのブラウザは、GREASE(Generate Random Extensions And Sustain Extensibility)と呼ばれるランダム値をClient Helloに含めます。JA3の正確な算出には、これらのGREASE値を除外する必要があります。
GREASE値は、0x0a0a、0x1a1a、0x2a2a…のようなパターンを持ちます。Bashスクリプトでは、sedやgrepを使ってフィルタリングできます。
# GREASE値を除外する関数
remove_grease() {
echo "$1" | sed 's/b[0-9a-f]a[0-9a-f]ab//g' | sed 's/,,/,/g' | sed 's/^,//;s/,$//'
}
実践的なBashスクリプト:リアルタイムJA3監視ツールの構築
ここでは、より実践的なリアルタイムJA3監視スクリプトを構築します。このスクリプトは、ネットワーク上のTLS通信をリアルタイムで監視し、既知の悪意あるJA3ハッシュを検知した場合にアラートを発報します。
ブラックリストファイルの作成
まず、既知のマルウェアのJA3ハッシュをリスト化したファイルを作成します。
# ja3_blacklist.txt
# 既知のマルウェアJA3ハッシュ(例)
e7d705a3286e19ea42f587b344ee6865 # Emotet variant
6734f37431670b3ab4292b8f60f29984 # Trickbot
72a589da586844d7f0818ce684948eea # Cobalt Strike
a0e9f5d64349fb13191bc781f81f42e1 # Metasploit
リアルタイム監視スクリプト
#!/bin/bash
# ja3_monitor.sh - リアルタイムJA3監視スクリプト
INTERFACE="eth0"
BLACKLIST="./ja3_blacklist.txt"
LOG_FILE="/var/log/ja3_alerts.log"
# ブラックリストを読み込み
declare -A MALICIOUS_JA3
while IFS=' ' read -r hash comment; do
[[ "$hash" =~ ^#.*$ ]] && continue
[[ -z "$hash" ]] && continue
MALICIOUS_JA3["$hash"]="$comment"
done < "$BLACKLIST"
echo "[*] JA3監視を開始します(インターフェース: $INTERFACE)"
echo "[*] ブラックリスト登録数: ${#MALICIOUS_JA3[@]}"
# tsharkでリアルタイムキャプチャ
sudo tshark -i "$INTERFACE" -Y 'tls.handshake.type == 1' -T fields
-e ip.src -e ip.dst -e tcp.dstport
-e tls.handshake.ja3
2>/dev/null | while IFS=$'t' read -r src_ip dst_ip dst_port ja3_hash; do
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
if [[ -n "${MALICIOUS_JA3[$ja3_hash]}" ]]; then
alert="[ALERT] $timestamp | 悪意あるJA3検知 | SRC=$src_ip DST=$dst_ip:$dst_port | JA3=$ja3_hash | ${MALICIOUS_JA3[$ja3_hash]}"
echo "$alert" | tee -a "$LOG_FILE"
# Slackやメールへの通知もここに追加可能
else
echo "[INFO] $timestamp | SRC=$src_ip DST=$dst_ip:$dst_port | JA3=$ja3_hash"
fi
done
このスクリプトは、tsharkの-e tls.handshake.ja3フィールドを活用しています。tsharkの比較的新しいバージョン(3.x以降)では、JA3ハッシュを直接算出するプラグインが利用可能です。
cron連携による定期レポート生成
以下のスクリプトをcronに登録することで、毎日のJA3統計レポートを自動生成できます。
#!/bin/bash
# ja3_daily_report.sh
YESTERDAY=$(date -d 'yesterday' '+%Y-%m-%d')
LOG_FILE="/var/log/ja3_alerts.log"
REPORT_DIR="/var/reports/ja3"
mkdir -p "$REPORT_DIR"
# 昨日のアラート件数を集計
alert_count=$(grep "$YESTERDAY" "$LOG_FILE" | grep '[ALERT]' | wc -l)
unique_ja3=$(grep "$YESTERDAY" "$LOG_FILE" | awk -F'JA3=' '{print $2}' | awk '{print $1}' | sort -u | wc -l)
top_sources=$(grep "$YESTERDAY" "$LOG_FILE" | grep '[ALERT]' | grep -oP 'SRC=K[^ ]+' | sort | uniq -c | sort -rn | head -10)
cat > "$REPORT_DIR/report_$YESTERDAY.txt" <<EOF
===== JA3日次レポート ($YESTERDAY) =====
アラート総数: $alert_count
ユニークJA3ハッシュ数: $unique_ja3
--- アラート上位送信元 ---
$top_sources
EOF
echo "レポートを生成しました: $REPORT_DIR/report_$YESTERDAY.txt"
crontabに以下を登録します。
0 6 * * * /opt/scripts/ja3_daily_report.sh
JA3ハッシュのデータベース照合と脅威インテリジェンス連携
JA3ハッシュの真の力は、脅威インテリジェンスデータベースとの照合によって発揮されます。BashスクリプトからAPIを叩いて、検出したJA3ハッシュの危険度を自動判定する方法を解説します。
公開データベースの活用
JA3ハッシュの照合に利用できる主要なデータベースは以下の通りです。
| データベース名 | 特徴 | API提供 | 費用 |
|---|---|---|---|
| ja3er.com | JA3ハッシュの大規模データベース | あり | 無料 |
| Abuse.ch (SSLBL) | 悪意あるSSL証明書・JA3のブラックリスト | あり | 無料 |
| GreyNoise | インターネットスキャナーのJA3情報 | あり | 一部有料 |
| Shodan | JA3によるデバイス検索が可能 | あり | 有料 |
Bashからja3er.comのAPIを叩く例
#!/bin/bash
# ja3_lookup.sh - JA3ハッシュをAPIで照合
JA3_HASH="$1"
if [[ -z "$JA3_HASH" ]]; then
echo "使い方: $0 <JA3ハッシュ>"
exit 1
fi
# ja3er.comで検索
echo "[*] ja3er.com で照合中..."
result=$(curl -s "https://ja3er.com/search/$JA3_HASH")
if echo "$result" | grep -q '"User-Agent"'; then
echo "[+] 一致するレコードが見つかりました:"
echo "$result" | python3 -m json.tool 2>/dev/null || echo "$result"
else
echo "[-] データベースに一致するレコードはありません"
fi
# Abuse.ch SSLBLで検索
echo ""
echo "[*] Abuse.ch SSLBL で照合中..."
sslbl_result=$(curl -s 'https://sslbl.abuse.ch/blacklist/ja3_fingerprints.csv' | grep "$JA3_HASH")
if [[ -n "$sslbl_result" ]]; then
echo "[!] 警告: このJA3ハッシュはAbuse.chのブラックリストに登録されています"
echo "$sslbl_result"
else
echo "[+] Abuse.chのブラックリストには登録されていません"
fi
実行例は以下の通りです。
./ja3_lookup.sh e7d705a3286e19ea42f587b344ee6865
バッチ処理による大量ハッシュの照合
pcapファイルから抽出した大量のJA3ハッシュを一括で照合するスクリプトも、Bashなら簡単に作成できます。
#!/bin/bash
# ja3_batch_lookup.sh
INPUT_FILE="$1" # 1行1ハッシュのファイル<br

コメント