こんにちは。
暗号化通信時の鍵情報が漏洩すると、通信の内容を復号化されてしまうことは知識として理解していますが、いざ実際に復号するには、どのようにすればいいのか調べてみました。
今回はクライアント ( Client ) 、ルータ ( Router ) 、サーバ ( Server ) の 3 ホストを仮想環境に用意して、順番に検証してみようと思います。
検証方法
以下の図のように、Router でキャプチャした暗号化されたパケットを、Server の秘密鍵、Client のセッションキーを用いて復号化することをゴールとします。
パケットキャプチャには tcpdump を、パケットの復号化には Wireshark を用います。
環境構築
各種ホストは VirtualBox 上に起動した AlmaLinux9 にて構築します。
Role | IP address | OS | Supplement |
Router | 192.168.33.11 | AlmaLinux 9 | – |
Client | 192.168.33.12 | AlmaLinux 9 | – |
Server | 192.168.33.13 | AlmaLinux 9 | vhosts: verienv.com |
Router
Router は iptables を用いて 192.168.33.0/24 ネットワークからのパケットをフォワードするように設定します。
systemctl stop firewalld systemctl disable firewalld dnf -y install iptables-services tcpdump iptables -t nat -A POSTROUTING -s 192.168.33.0/24 -j MASQUERADE iptables -A FORWARD -s 192.168.33.0/24 -j ACCEPT iptables -A FORWARD -d 192.168.33.0/24 -j ACCEPT iptables-save > /etc/sysconfig/iptables echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf sysctl -p
Client
Client では、元々のルーティングテーブルのエントリを削除し、先の Router をデフォルトゲートウェイとするエントリを追加します。
また、verienv.com の名前解決先が Server に向くように hosts ファイルにエントリを追加します。
dnf -y install net-tools route delete default route add default gw 192.168.33.11 route del -net 192.168.33.0 netmask 255.255.255.0 echo "192.168.33.13 verienv.com" >> /etc/hosts
Server
Server には特別な設定は必要なく、一般的な 443 を Listen する WEB サーバを構築します。
設定した証明書の秘密鍵は手元に落としておきます。
※ 本検証では verienv.com という FQDN のバーチャルホストを切り使用します。
※ ありふれた設定なので、本記事では割愛します。
検証
キャプチャ
Router にて以下コマンドを実行し、192.168.33.0/24 からのパケットをキャプチャして capture.pcap というファイルに出力します。
tcpdump -i eth1 -s 0 net 192.168.33.0/24 -w capture.pcap
Client にて以下コマンドを実行し、Server に対して JSON の POST リクエストを発行します。
※ SSLKEYLOGFILE 環境変数には、鍵情報 ( セッションキー ) のダンプ先となるファイルパスを指定しており、今回はカレントディレクトリの key.log というファイルに出力します。
SSLKEYLOGFILE=./key.log curl -k -X POST -H "Content-Type: application/json" -d '{"name": "snkk1210", "age": 100, "city": "New York"}' https://verienv.com
Router のフォアグラウンドで実行されている tcpdump を 「Ctrl + c」 で終了させ、Router の capture.pcap と Client の key.log を手元に落とします。
復号化
暗号化されたパケットの復号には Wireshark を使います。
一旦、手元に落とした capture.pcap を Wireshark で開いてみます。
この状態だとパケットは暗号化されたままで内容が分からないですね…。
以下の手順で Wireshark に先の鍵情報を登録します。
Edit > Preferences > Protocols > TLS > RSA keys list [Edit]
Key | Value |
IP address | 192.168.33.13 |
Port | 443 |
Protocol | http |
Key File | < Server の秘密鍵のパス > |
Password | – |
実は Perfect Forward Secrecy ( PFS ) が有効である場合や、暗号スイートに DHE を使っている場合、秘密鍵だけだと復号ができません。
同じく (Pre)-Master-Secret log filename に手元に落とした key.log ( セッションキー ) を指定します。
この状態でパケットの中身を覗いてみます。
新たに Decrypted TLS というタブが追加されており、こちらを選択することでリクエストの中身を確認することができました。
終わりに
今回、復号処理は全て Wireshark で行いましたが、この辺りを深く理解して独自に実装できるようになりたいものです。
もっと勉強しなくちゃですね。