JA3フィンガープリントとは?Bashでの実装・活用法を徹底解説

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

コメント

タイトルとURLをコピーしました