kdnakt blog

hello there.

ゆるTLSアドベントカレンダー 4日目:TLS拡張

この記事は ゆるTLS Advent Calendar 2021 の4日目の記事です。

 

3日目は2021年に見つかったALPACA攻撃を取り上げた。

kdnakt.hatenablog.com

 

ALPACA攻撃はSNIやALPNといったTLS拡張で対策が可能だが、TLS拡張とはそもそも何か、というお話。

 

 

[TLS拡張の歴史*1]

1999年にRFC2246で定められたTLS1.0のClientHelloメッセージ(ブラウザなどのクライアントがTLSハンドシェイクの流れで最初に送るメッセージ)は以下のような構造になっている。

enum { null(0), (255) } CompressionMethod;

struct {
   ProtocolVersion client_version; // プロトコルのバージョン
   Random random; // 乱数
   SessionID session_id; // セッションID
   CipherSuite cipher_suites<2..2^16-1>; // 利用可能な暗号スイート
   CompressionMethod compression_methods<1..2^8-1>; // 圧縮方式
} ClientHello;

 

しかし、RFC2246の35ページをよく読むと、以下のように書かれている。

Forward compatibility note:
       In the interests of forward compatibility, it is permitted for a
       client hello message to include extra data after the compression
       methods. This data must be included in the handshake hashes, but
       must otherwise be ignored. This is the only handshake message for
       which this is legal; for all other messages, the amount of data
       in the message must match the description of the message
       precisely.

 

意訳すると次のような感じ。

ClientHelloメッセージのみ、互換性のために圧縮方式の後に追加のデータを含めてもよい。ただし、このデータもハンドシェイクの完全性検証の対象とする。他のハンドシェイクメッセージについては規定通りとする。

 

この曖昧な仕組みが整備され、2003年にRFC3546TLS拡張としてまとめられた。2006年にRFC4346でTLS1.1が定められた際には、RFC3546は参照されるのみだったが、2008年にRFC5246でTLS1.2が定められた際に、TLSプロトコルの仕様として取り込まれた。

 

TLS1.2でのClientHelloメッセージは以下のようにTLS拡張に関する部分が追加されている。

enum { null(0), (255) } CompressionMethod;

struct {
    ProtocolVersion client_version; // プロトコルバージョン
    Random random; // 乱数
    SessionID session_id; // セッションID
    CipherSuite cipher_suites<2..2^16-2>; // 暗号スイート
    CompressionMethod compression_methods<1..2^8-1>; //圧縮方式
    select (extensions_present) { // TLS拡張
        case false:
            struct {};
        case true:
            Extension extensions<0..2^16-1>;
    };
} ClientHello;

 

また、TLS1.0ではこの仕組みはClientHelloメッセージのみに存在していたが、TLS拡張ではServerHelloメッセージにも追加されている。

 

[TLS拡張の仕組み]

ClientHelloおよびServerHelloメッセージに追加された拡張の中身は以下のようになっている。

struct {
    ExtensionType extension_type; // 拡張種別
    opaque extension_data<0..2^16-1>; // 拡張データ
} Extension;

 

拡張種別としては、RFC3546では以下の6種類が定められている。

enum {
    server_name(0), // SNI拡張はこれ
    max_fragment_length(1),
    client_certificate_url(2),
    trusted_ca_keys(3),
    truncated_hmac(4),
    status_request(5),
    (65535)
} ExtensionType;

 

これ以外にも、TLS1.2で定められたsignature_algorithms(13)や、個別のRFCで定められたrenegotiation_info(65281)RFC5746、2010年)やheartbeat(15)RFC6520、2012年*2)がある。

 

ClientHelloまたはServerHelloメッセージは暗号化されていないため、Wiresharkなどのツールでパケットをキャプチャすると、TLS拡張を確認できる。

f:id:kidani_a:20211204233527p:plain

 

[ALPN拡張]

ALPACA攻撃の対策として挙げられているALPN(Application-Layer Protocol Negotiation)拡張は、2014年にRFC7301で定められた。

datatracker.ietf.org

 

拡張種別は16となっている。

拡張データには、以下のProtocolNameListが含まれる。

opaque ProtocolName<1..2^8-1>;
struct {
    ProtocolName protocol_name_list<2..2^16-1>
} ProtocolNameList;

 

上の画像の例では、h3(HTTP/3、HTTP-over-QUIC)がネゴシエーションされているのがわかる。

このように、ALPN拡張を利用すると、TLSハンドシェイクを行なっている間に、アプリケーションプロトコルに関するネゴシエーションができる。従って、HTTPを使うはずの接続でALPACA攻撃を受けてFTPが使われた場合には、これをクライアント側が検知して接続を中断すべし、とされている(ALPACA Attack)。

 

[まとめ]

  • TLS1.0での曖昧な仕様がTLS拡張となりTLS1.2に統合された
  • TLS拡張は暗号化されていないのでパケットキャプチャで確認できる
  • ALPN拡張を適切に使うとALPACA攻撃の防御に利用できる

*1:参考:『プロフェッショナルSSL/TLS』175ページ。『プロフェッショナルSSL/TLS』読書メモ

*2:heartbeat拡張は2014年4月にOpenSSLでの実装上の脆弱性がみつかり、Heartbleedと名づけられた。参考:『プロフェッショナルSSL/TLS』160ページ。『プロフェッショナルSSL/TLS』読書メモ