Wiresharkで古いSSL(TLS)をフィルタで見つける
ブラウザを提供している各社がTLS1.0,1.1を無効化処理して久しいですが、TLSはインターネットを閲覧する場合以外でも使っていることがあります。
例えばSMTP over SSL/TLS(メール送受信)やSSL-VPN(VPN)などでも使われます。
ところが、各ブラウザでは古いTLS無効化が実行されましたが、メールやVPNといったソフトウェアはまだ対応していないことがあります。
世の中の流れとしていずれは無効化されることがほぼ確実ですが、いざ組織内でそれらの古いTLSを使っているのかどうか、と言われるとなかなか調査するのが難しかったりします。
そこで今回はパケットキャプチャソフトとして有名なWiresharkを利用して、古いSSL(TLS)通信の有無を見つける方法を解説します。
※Wiresharkの基本的な使い方はここでは説明しません。また、ネットワークスペシャリストレベルの前提知識があるものとしてパケットの細かいことも説明しませんのであしからず。。。
SSL/TLSのバージョン推移
古いバージョンを見つける前に、SSL/TLSのバージョン推移を振り返っておきましょう。
バージョン | 概要 | 見つかった主な脆弱性 | バージョンの判別方法(Client/Server Hello) | 対応する16進数 |
SSL1.0/2.0 | 1995年頃にNetscapeが提唱。脆弱性があるので今は使われていない。 | ハッシュ衝突等 | SSLヘッダバージョン | 0x0200 ※1 |
SSL3.0 | SSL2.0の改良版。主要ブラウザでは既定で無効。 | POODLE等 | SSLヘッダバージョン | 0x0200 |
TLS1.0 | SSL3.0のPOODLE解決版。主要ブラウザでは既定で無効。 | 暗号、認証技術の脆弱性、BEAST等 | TLSヘッダバージョン | 0x0301 |
TLS1.1 | TLS1.0のBEAST解決版。主要ブラウザでは既定で無効。 | 暗号、認証技術の脆弱性等 | TLSヘッダバージョン | 0x0302 |
TLS1.2 | TLS1.0/1.1の脆弱性解決版。2022年2月現在において主流のバージョン。 | TLSペイロードバージョン | 0x0303 | |
TLS1.3 | HTTP/3(QUIC)との親和性を重視したもの。まだ主流ではないが徐々に対応が進んでいる。 | TLSペイロードのsupported version | 0x0304 |
SSL/TLSのバージョンはどこに書いてあるのか
IPパケットはパケットヘッダを確認すればIPv4かIPv6を判別できますが、SSL/TLSは少し特殊な判断が必要となります。
上記の表にある通り、バージョンによってフィルタする方法や場所が異なります。
例えば、TLS1.3のヘッダとペイロードバージョンには何が書いてあるかというと、実はTLS1.0とかTLS1.2を示す0x301や0x303が書かれていることがあります(少なくともここにTLS1.3を示す0x304は記載されません)。
ではどこに書いてあるかというと、ペイロードにあるExtensions属性のSupported Versionsに記載されています。
この通信はTLS1.0/1.1の無効化された最新版のChromium Edgeで発生したものですが、このようにSupported Versionsの中にTLS1.2/1.3に対応していることが示されています。
TLS1.3対応のサーバーはExtensionsのSupported Versionを確認してからTLS1.3のServer Helloを応答します。
一方、TLS1.3非対応でTLS1.2対応のサーバーはペイロードのバージョン(TLS1.2)を確認してTLS1.2のServer Helloを応答します。
TLS1.3もTLS1.2も非対応でTLS1.0/1.1対応のサーバーはヘッダのバージョン(TLS1.0)を確認してからTLS1.0のServer Helloを応答します(ただしこの場合、TLS1.0/1.1を受け付けないブラウザであればコネクションは失敗します)。
このように後方互換性を確保するためにヘッダ、ペイロード、Extensionsにそれぞれバージョン識別のデータが含まれています。
そのため、すこしややこしいですがSSL/TLSパケットのバージョンを識別するには識別したいバージョンに合わせて対応が必要です。
キャプチャフィルタを構成する
今回の目的は古いバージョンのTLS(特に今後無効化が進むであろうTLS1.0/1.1)を見つけるためにキャプチャを行います。
そのため、キャプチャデータが膨大になってしまわないよう条件の厳しめなキャプチャフィルタを構成します。
どのようなフィルタにすべきかはキャプチャする場所や組織内の通信環境によって変わってきますので柔軟に解釈してください。
今回はSMTPS/STARTTLS/HTTPSに限定してキャプチャします。ポート番号を指定していますが、SSL-VPNやその他ポート番号が固定ではない通信も検出する場合はTCPフィルタだけにしましょう。
場合によっては膨大なキャプチャデータになる可能性があるので、リングバッファやtsharkを利用することも視野に入れてください。
tcp port 443 || tcp port 465 || tcp port 587
ディスプレイフィルタを構成する
キャプチャフィルタを構成したらディスプレイフィルタを構成してさらに絞り込みます。
今回はTLSクライアントからサーバーへ送信するClient Hello(TLS通信の最初に送信されるパケット)を観測します。
Client HelloはHandshake Type == 1なので、この条件を必ず付けておきます。サーバーの応答であるServer Helloも観測したい場合はHandshake Type == 2も条件として追加してください。
※なぜClient Helloかというと、TLS1.0/1.1は既に対応を終了しているサーバーの場合Server Helloを応答しないことがあるためです。応答がない場合、パケットの観測は出来ないので検出漏れとなります。
TLS1.0/1.1の場合
TLS1.0/1.1の特徴はヘッダバージョンとペイロードバージョンのどちらも1.0(0x0301)か1.1(0x0302)であることでフィルタします。
ヘッダバージョンだけでフィルタすると、下記画像のようなTLS1.2やTLS1.3も含まれてしまいます。
TLS1.0だけをフィルタする場合
tls.record.version == 0x0301 && tls.handshake.version == 0x0301 && tls.handshake.type == 1
TLS1.1だけをフィルタする場合
tls.record.version == 0x0302 && tls.handshake.version == 0x0302 && tls.handshake.type == 1
TLS1.0/1.1の両方をフィルタする場合
((tls.record.version == 0x0301 && tls.handshake.version == 0x0301) || (tls.record.version == 0x0302 && tls.handshake.version == 0x0302)) && tls.handshake.type == 1
TLS1.2/1.3の場合
2022年2月現在ではTLS1.2/1.3が有効になっているクライアントがほとんどのため、送出しているClient HelloがTLS1.2なのかTLS1.3なのかは判別できません。
TLS1.3はヘッダバージョンとしてはTLS1.2と全く同じように動作しますし、ExtensionsのSupported VersionにはTLS1.2/1.3両方対応していることを示すデータが格納されているので違いはありません。
ですので、サーバーの応答であるServer Hello(handshake type == 2)を観測して判断することになります。
TLS1.3のServer HelloはExtensionsのSupported VersionがTLS1.3を示す0x0304だけ格納されているので、これを条件にフィルタします。
TLS1.2だけをフィルタする場合
TLS1.2にはExtensionsにSupported Versionが含まれないことを逆に利用してフィルタします。
tls.handshake.version == 0x0303 && not tls.handshake.extensions.supported_version && tls.handshake.type == 2
TLS1.3だけをフィルタする場合
tls.handshake.extensions.supported_version == 0x0304 && tls.handshake.type == 2
TLS1.2/1.3の両方をフィルタする場合
Supported Versionの条件を省けばTLS1.2/1.3の両方を得られます。
tls.handshake.version == 0x0303 && tls.handshake.type == 2
アプリケーションデータでフィルタする
大前提として、TLSハンドシェイクに成功してアプリケーションデータの通信が発生している場合は、フィルタがもっと簡単になります。
TLSハンドシェイクではClient HelloやServer Helloのように複数のバージョンが含まれていたり、Extensionsがあったりと大変でした。
ところがハンドシェイクに成功した後に発生するアプリケーションデータはとてもシンプルにヘッダにバージョンがしっかり書いてあるので、そこだけを条件にフィルタすればOKです。
※何度も言いますがハンドシェイクに成功してデータ通信が発生している場合に使える方法です。古いTLS1.0/1.1のようにハンドシェイクに失敗している可能性のあるバージョンの検出には不向きです。
TLS1.0~TLS1.2のアプリケーションデータをフィルタする
下記の0xXXXXに対応する16進数をいれるだけです。TLS1.0なら0301、TLS1.1なら0302、TLS1.2なら0303です。
tls.record.version == 0xXXXX && tls.record.content_type == 23
TLS1.3のアプリケーションデータをフィルタする
TLS1.3はTLS1.2のcontent_typeに相当する部分がopaque_typeに置き換わります。
なお、record.versionは相変わらずTLS1.2(0x0303)ですので紛らわしいですが注意しましょう。
tls.record.version == 0x0303 && tls.record.opaque_type == 23
※opaque_typeはTLS1.3にしかないので、前半のversion == 0x0303条件式は無くてもよいですが、ここでは明示しました。
まとめ
- TLSのバージョンでフィルタするにはフィルタしたいバージョンによってかなり違う
- TLS1.0/1.1のフィルタはほぼやり方が同じ
- TLS1.2/1.3のフィルタはほぼやり方が同じだけど少し難しい