日記スマートフォン用の表示で見るぼちぼち日記おそらくプロトコルネタを書いていることが多いんじゃないかと思います。発生することが問題になっていました。仕組みを取り入れました。Extensibility)という仕様をChromeに実装し、TLSサーバのバグで通らない拡張やフィールド値で問題が発生しないか試験を始めました。見慣れない値をCipherSuiteやTLS拡張に使っているのを見つけても驚かないよう気をつけて下さい。はじめに確か半年前も同じような事を言っていましたが、TLS1.3の仕様策定が大詰めを迎えています。大詰めの段階に来ているにも関わらず、最近のドラフト(draft-15/16)になって、これまでのTLS仕組みを大きく変えるような変更がいくつか導入されました。この大きな変更は、Netscape社のSSL3時代から20年近く、これまでずっと積み重なってきた技術負債をできるだけここで一掃したいという思いの現れです。一方で、ガチガチにミドルボックスで縛られた現状のインターネットと不完全な実装を持つ多数のTLSサーバの影響を考えるとそうそう一筋縄ではいきません。事情や経緯を知らない人がこの変更点を見るとなかなか理解しがたい仕様になっているでしょう。ついて取り上げたいと思います*1。Googleは、こんな苦労をもうしないよう、将来のTLSバージョンアップや機能拡張に備えるべくGREASEという仕様ドラフトを提出しました。Canaryで試験運用を始めました。これについても詳しく紹介します。Negotiation)は、TLSハンドシェイクの初期で行う非常に重要なステップです。不完全で、随分昔(2003年以前ぐらい)から問題が発生していることが知られています。日本語だと「バージョン不耐性」でしょうか?なんかよい訳が思い浮かびません。intoleranceが詳しく取り上げられました。Intoleranceにも詳しく解説されています。ここに敢えて私が付け加えるようなことはないのですが、後の説明がわかりやすくなるよう簡単に図にして解説してみます。Negotiationは、ClientHello/ServerHelloのハンドシェイクの最初のやり取りで行います。クライアントは自身がサポートしている最高のTLSバージョンをサーバに伝えます。サーバは、自身がサポートしているTLSバージョンからクライアントがサポートしているものを選んで返します。TLS1.2のクライアントとTLS1.2のサーバ間では簡単で、ClientHelloとServerHello供にTLS1.2のバージョンをやり取りして合意して完了です。クライアントとサーバ側のサポートが違う場合(サーバ側がTLS1.1までサポートしていない時)、サーバはClientHelloでTLS1.2を受信しますが、TLS1.2をサポートしていないので、ServerHelloでTLS1.1をクライアントに返します。クライアントはそれを受けて、クライアント・サーバ間でTLS1.1を合意します。実はこれをちゃんと実装していないサーバが多く存在していて問題になっています。Intolerance何がちゃんと実装されていないのでどういう問題が起きるのかは様々ですが、一例としてよく挙げられているのは、サーバが自身がサポートしていないTLSバージョンのClientHelloを受信すると接続を切断してしまうというという実装の問題です。Intoleranceの問題でClientHelloが切断されるとサーバにオファーするバージョンを下げてもう一回接続に行きます。これを繰り返してサーバがサポートしているバージョンまで合致すると、やっとハンドシェイクが進みます。最終的に接続できるから良いかと思うかもしれませんが、何回も初期接続を試みるのでTLS通信が確立するまで時間がかかります。なによりクライアントは本当にサーバが切断したのか判断つかないので、もし中間攻撃者によって意図的に切断されてダウングレードさせられているのかもしれません。脆弱性のあるTLSバージョンまでダウングレードさせられると問題です。TLS1.2が仕様化された後、このような状況がいくつか見られました。その結果、幾つかのブラウザベンダーは、TLS1.2の対応サーバがある程度普及するまでデフォルトでTLS1.2の通信をオフにしなければなりませんでした。TLS1.3はやっぱり通らないTLS1.3でも同じ状況が起こることが懸念されてました。Inc.で公開されています。ここでその図を引用させてもらいます。Intoleranceをチェックする試験を行っていました。TLS1.3では12%、TLS2.152では60%以上のサーバが接続を拒否しています。バージョンをTLS1.0に固定した試験に変更すると急激に下がりました。あると統計結果が出ています。layerのバージョンのtoleranceは大変厳しいのがわかります。layer自体はもう意味がなく、互換性のためだけに付けておく無駄な5バイトになっています。layerのバージョンはTLS1.0(0x0301)に固定されました。Alexaのトップ100万のサイトを調査しました。その結果、1.63%のサイトがTLS1.3のClientHelloを切断したということです。intoleranceの見積もりになります。この数字が大きいか小さいか、判断が別れるところです。その数パーセントの中に大規模なアクセスを受けているサイトがあれば、ユーザへの影響は大きいでしょう。TLS1.2までは問題なく動作していたということで、TLS1.3にしてまず真っ先に問題を疑われるのはクライアント側になります。していかないといけないかもしれません。できればそれは避けたいところです。Negotiationの仕組みを採用しました。Versionsを規定してそこにTLS1.3のクライアントがサポートするTLSバージョンのリストを記載します。VersionsのTLS拡張の方を見てTLSのバージョンを選びます。Versions拡張を知らないので、これまでのTLS1.2のClientHelloが来たと思って騙されて処理を継続します。intoleranceの影響を最小限にすることができます。までintoleranceが落ちるという結果がでました*2。これなら十分いけます。ClientHelloフィールドのうち半分が実際には不要で互換性維持のためだけに存在する固定値になってしまいました。あぁデザインがきれいじゃない。なんとも言えないもどかしさです。ClientHelloのフォーマットを維持してデータ形式上TLS1.xとの互換を保たないとTLS透過性はもっと悲惨なものになるでしょう。Negotiationを捨て去ることは、TLS1.3一回限りではなく今後TLS1.4以降でもずっと続く話になります。大きな決断をすることになりました。Versionsを使ったTLS1.3のハンドシェイクを見てみます。Versionsが実装されたので実際のパケットを見てみましょう。TLS1.3(0x0304)が使えるのは、最終的にTLS1.3の仕様化が完了した後からです。draft段階での相互接続試験においては、使用するバージョンは1オクテット目を0x7f、2オクテット目をドラフト番号にしたバージョン番号を使います。バージョン番号になります。LayerのバージョンはTLS1.0です。Versionは、TLS1.2。これで従来のTLS1.2までのサーバを騙します。Versions拡張は43番が割り当てられています。そこにクライアントがサポートするTLSバージョンのリストが5つ記載されます。後述するGREASEの値。一応記載順には意味を持たせないことになっています。LayerはTLS1.0で固定化したままです。Versionに記載してクライアントに返します。Negotiationの完了です。バグで錆びたTLSを滑らかにするGREASEこんな悲しいTLSの状況で頼みの綱はTLS拡張しかない。楽観視できない、TLS拡張の処理にもバグが固定化して錆びついてしまう。oiled.(これについて解決法は、どこか一つを繋げて十分に潤滑させておくことしかない)と書いています。Extensibility)https://datatracker.ietf.org/doc/draft-davidben-tls-grease/というドラフトを少し前に提出しました。日本語に訳すと「ランダムな拡張を生成して、拡張性を維持する」ということでしょうか。これは、2バイトの0x[0-f]a[0-f]aの16個データからランダムにいくつか抽出し、毎回ClientHelloのCipherSuiteやTLS拡張や値にこのランダム値を入れ込んでサーバに送ってしまおうという仕様です。versionsの値(TLS1.3のみ)の6領域を対象としています。本来はTLSサーバが知らない未定義の拡張やフィールド値を受信しても基本無視して処理するのがTLSの仕様で求められる挙動です。GREASEは、未定義値を毎回ランダムに送信することによって、TLSサーバのバグを早期に発見し、将来拡張で利用する時に問題が発生するのを未然に防ごうという狙いです。文字通りGREASEは、TLSの拡張やフィールド値の利用がバグ実装の固定化で錆びつかないようグリースを塗り続けるという比喩を表しています。Canaryに実装されているので、実際にパケットを見てみるとよくわかります。CanaryのTLS1.2のClientHelloを見てみましょう。CipherSuiteの先頭に0x3a3aの見慣れない値が入っています。これがGREASEです。いうring-LWE方式の格子暗号を組み合わせた鍵交換方式です。これはこれですごく面白いのですが、解説するとめちゃくちゃ長くなるので、いつかの機会に。続いてTLS拡張に入っているGREASEを見てみます。0バイト長の0x2a2aの拡張が頭に1バイト長の0x1a1aのタイプ値を持ったTLS拡張が追加されています。GREASE値が入っています。ALPNへのGREASEの実装はドラフトに記載されていますが、まだのようです。Versions拡張の先頭に0x1a1aのGREASEが入っているのがわかります。BoringSSLの実装では、これらのGREASE値をClientのRandomフィールドの頭の1バイトずつをシードにして生成しています(頭の4bit値)。よって、ClientRandomが変わると毎回値が変わることになります。GoogleはGREASEによってどの程度問題が発生しているのか統計を取って、今から将来のTLSのバージョンアップや機能拡張に備えている試験を始めたわけです。0x[0-f]a[0-f]aの見慣れないUnknownフィールドや値を見かけたとしても驚かないように。それはGoogleが、インターネット中のTLSサーバが錆びつかないようグリースを塗っている様子なんです。*1:この他にもCipherSuiteの構造も大きく変わっています。*2:Googleは、ChromeのTLS1.3の事前試験でTLS1.3で必須となっている署名アルゴリズム(RSA-PSS)のTLS拡張値でNSSのバグを踏んでハンドシェイクが失敗することを見つけました。0.017%にはこのNSSのバグの影響によるものがいくつか含まれているようです。10:12錆びついたTLSを滑らかに、GoogleによるGREASE試験Tweet広告を非表示にする関連記事2017-03-17書評:プロフェッショナルSSL/TLSごめんなさい、書いてたら長くなってしまいました。はてなブログの方に移りました。第2.0版」を読んで月別アーカイブはてなブログをはじめよう!jovi0608さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。