https とは? http との使い分けは?
https とは、簡単に言うと http プロトコルを暗号化したものです。
http プロトコルはインターネット等の IP ネットワーク上にある Web サーバから html ファイル等のファイルをダウンロードしたり、サイトへログインする際の ID / パスワード情報を送ったりするのに使う通信プロトコルです。
ですが、ID / パスワードをそのまま送ってしまうと、万が一誰かに通信を傍受(パケットキャプチャ)されていたらパスワードが漏れ、そのサイトへ不正なログインをされてしまいます。
楽天等のショッピングサイトだったら勝手に買い物をされてしまう可能性もあります。
そのような事態を防ぐため、通常のショッピングサイトはほぼ 100%、https による暗号化を行っています。
最近は無料のデジタル証明書が増えてきており、ショッピングサイトでない普通のサイトも全て https による暗号化が為されており、むしろ http のサイトを探す方が難しくなってきています。
厳密には、暗号化以外にもサーバの認証を行っています。具体的には、『ブラウザに入力した URL』と『サーバの持つデジタル証明書のサブジェクトの別名 (代替名), 通称 SANs (サンズ)』が一致するか、を確認します。(昔は SANs ではなく CommonName (コモンネーム) という属性を見ていましたが、最近のブラウザは SANs に記載しないとサーバ認証に失敗するようになっています。)
さらにその証明書自体が信頼できるかどうかを PKI の仕組みで確認しますが、そのあたりはデジタル証明書を中心に記載した以下記事をご参照下さい。
このサーバ認証により、DNS キャッシュポイズニング攻撃等により、悪意あるサイトへ誘導されていないかを確認することができます。
認証に失敗するとどうなるかについては下記ページ等をご参照ください。
https のシーケンス図
http のシーケンス図と https のシーケンス図を比べてみます。
『TCP 3way ハンドシェイク』と『暗号化対象のhttp通信』の間に、TLS コネクション開始のためのハンドシェイク が入っています。
このハンドシェイクをもう少し詳しく見てみます。
まずは認証/暗号アルゴリズムのネゴシエーションを行います。Client Hello にてクライアント側が対応している認証/暗号アルゴリズムのリストを提示し、Server Hello によりその中でサーバ側が採択したものをクライアントへ提示します。
次に認証を行います。サーバからの Certificate にて『デジタル証明書の署名によるサーバの認証』が行われます。オプションで、クライアントへ『クライアント証明書の提示』を要求し、クライアントの認証を行うこともできます。
最後に Client/Server Key Exchange (TLS v1.3 以降は key_share Extension) により Diffie-Hellman アルゴリズムによる共通鍵交換を行います。
このハンドシェイク完了後に http の暗号化通信が可能となります。
公開鍵・秘密鍵については以下を参照下さい。
なお、2018 年 8 月に公開された TLS v1.3 の v1.2 からの変更点などについては以下を参照してください。
https 通信であっても盗み見される情報
https 通信であっても、(宛先 IP アドレスは当然のことながら、) 通信先に関して以下の情報を盗み見される可能性があります。
CONNECTメソッドのホスト情報
CONNECT とは、クライアントがプロキシ経由で https 通信をするときに使われる http メソッドです。一般的な http 通信においては GET メソッドが使われますが、https がプロキシ経由で通信する際、例えば https://www.yahoo.co.jp と通信するクライアントは、プロキシに対して "CONNECT www.yahoo.co.jp" というメソッドを平文で発行しますので、これを盗み見すれば宛先情報が分かります。
デジタル証明書のサブジェクト代替名/コモンネーム
https のセッション開始時 (暗号化通信が始まる前) の "Certificate" メッセージではサーバがデジタル証明書を提示しますが、そのデジタル証明書には サブジェクト代替名 (SANs) という URL のホスト情報が含まれています。これを盗み見することでやはり宛先情報が分かります。
この情報はよく UTM の URL フィルタでのサイトカテゴリ判別で使われたりします。
Client Hello の ServerName Extension
2011 年に公開された RFC 6066 においては "Server Name Indication (SNI)" という Extension が定義されており、TLSコネクション開始時の "Client Hello" メッセージの中に含めることができます。
この Extension には通信先サーバの URL 情報が載せられています。元々は https を使うバーチャルホストへの対応のため (HTTP GET の前に URL が分かっていないと、対応した証明書を提示できず TLS コネクションが開始できないため) に考えられましたが、中間の NW 機器 (主に UTM) 等が宛先を認識して制御する目的でもよく使われます。
この情報もデジタル証明書の SANs と同様、UTM の URL フィルタで使われており、最近では SANs は使わず SNI で宛先を識別するのが主流です。SANs ではワイルドカードの利用が可能であり、範囲が特定できない場合があるからです。
https のパケット構造、ヘッダ、フォーマット
https のフレームフォーマットは以下のようになります。
TLS 通信は『レコードヘッダ』と『ペイロード』に分かれています。
レコードヘッダの Version は『SSL 2.0 = 0x0200』,『SSL 3.0 = 0x0300』,『TLS 1.0 = 0x0301』,『TLS 1.1 = 0x0302』,『TLS 1.2 = 0x0303』,『TLS 1.3 = 0x0304』となっています。
Length には TLS ペイロードの長さ (MAC: Message Authentication Codeを含む) を示す値が入ります。
そして Content Type は『ペイロードにどのようなデータが入っているか』を示しています。
Content Type:20 = ChangeCipherSpec
ハンドシェイクプロトコルのサブプロトコル。暗号化通信の準備が整ったことを相手に知らせるメッセージです。
Content Type:21 = Alert
ハンドシェイクプロトコルのサブプロトコル。相手に何かしらの警告を通知するメッセージです。これはさらに Alert Type に分類されます。(次章参照)
Content Type:22 = Handshake
ハンドシェイクプロトコルのサブプロトコル。これはさらに Handshake Type に分類されます。(上図参照)
Content Type:23 = Application Data
http や smtp、ldap 等の上位プロトコルが暗号化されて通信されます。
Wireshark で Encrypted Alert および Unknown Record が表示されるケースについて
パケットキャプチャ時に Encrypted Alert と表示される場合があります。これは ”Content Type:21 = Alert” によるものです。
このパケットが出る理由はまちまちですが、TCP FIN の直前にある場合は大抵、TLS コネクションの終了を意味する『close_notify』だと思われます(暗号化されていて見えない)。
Alert と付くので少し気持ち悪いですが、正常終了でもこの『close_notify』が使われます。
TLS v1.2 を規格化している RFC 5246 の Section 7.2 では、以下の種類の Alert Type が定義されています。カッコの中の数字が Alert Type番号です。
handshake_failure(40), no_certificate_RESERVED(41), bad_certificate(42), unsupported_certificate(43), certificate_revoked(44), certificate_expired(45), certificate_unknown(46), illegal_parameter(47), unknown_ca(48), access_denied(49), decode_error(50), decrypt_error(51), export_restriction_RESERVED(60), protocol_version(70), insufficient_security(71), internal_error(80), user_canceled(90), no_renegotiation(100), unsupported_extension(110)
close_notify であれば「これ以上暗号化通信するものがないことを相手に伝える」という意味で、正常終了ですが、その他は名前が表す通りに何かしらの原因により異常終了するものです。
また、Ignored Unknown Record と表示される場合は、『定義されていない Content Type が使われている』という意味です。
例えば Windows のリモートデスクトップは TLS での暗号化を実装していますが、独自のカスタマイズをしているようで、パケットキャプチャで見てみると Content Type = 0x03 という RFC では定義されていない Record Protocol を使っています。
RFC 2246 (TLS v1.0) においては『理解できない Record Type は無視すべき』と書かれておりそれを受けての『Ignored Unknown Record』なのでしょう。ですがこれはクライアントとサーバが無視したということにはならず、Wireshark が RFC に従ってそのように解釈しただけです。
RDP の場合もそうですが、実際にはクライアントとサーバ間では解釈出来ているケースもあるでしょう(例えばWiresharkのバージョンが古いと、TLS の新バージョンで定義された Content Type (= Record Type) は理解できません。)
https の一般的な通信フロー
ここで、一般的な https 通信のフローとパケット構造を再確認します。
SSL/TLSのレイヤーは何層?
前述の通り、TLS コネクション開始のネゴシエーションは『TCP 3way ハンドシェイク』と『暗号化対象の http 通信』の間に存在しています。このことからも TLS のレイヤーは TCP 以上、http 以下であることが推察されます。
また、パケット構造を見ても、位置的に同様のことが言えます。
諸説あるようですが、nesuke 的には OSI 参照モデルのセッション層扱い、IPセットモデルだとアプリケーション層扱い(TLS 単体でトランスポート層の機能は無いので、暗号化を行うアプリケーションという位置付けになるはず)です。
コメント