.mobiドメインにおけるWHOISを用いた不正サーバ証明書の取得事例

.mobi TLDにおいて、WHOISを利用して不正サーバ証明書発行を行う攻撃手法が明らかになり、話題となっている。

この実験者は、実際に 所有してない *.mobi ドメインの証明書発行が出来そうな事を確認している(不正発行の直前で実験を停止)。

簡単に流れを眺めたので、メモとして記録しておく。

詳細

詳細の記事はこちら
labs.watchtowr.com

箇条書きで流れを書くと

  • 前提
    • .mobi TLDwhoisをホストしていたドメインが "whois.dotmobiregistry.net" から "whois.nic.mobi" に移設した
    • "dotmobiregistry.net" を第三者が取得できる状態にあったため取得し、どのような通信が来てるか確認した
    • 大手CAからの通信があり、CAのドメイン所有検証にWHOISのConntactが使える事が判明する
  • 証明書発行手順
    • 実際に、whois.dotmobiregistry.netでwhoisサーバを起動し、必要な情報を入力しておく
    • CAに不正発行したい証明書(「google.mobi」や「microsoft.mobi」)のCSR提出する
    • 本来は、ドメイン検証のためにadmin@microsoft.mobiなどのメールアドレスが使用されるが、whoisのConntactに登録したメールアドレス(今回は記事執筆者の保有する whois@watchtowr.com) もドメイン検証に選択できることを確認


(参照記事からの引用)

ここまでで実験を中止。実際に不正発行までは行わなかったとのこと。

この実験により、所有してない*.mobiドメインの証明書を取得できるであろうことが示された。

CA/B側での議論

証明書発行に関する要件を定義する、CA/Browser ForumのBaseline Requirementsに変更を加える議論が出ている。
ドメイン検証にWHOISの情報を使わないようにする提案である。

github.com

github.com


ちょっと今後の動向も追っていきたい

Chromeで、サーバ証明書検証時にネットワークから取得した時刻を使う

Chrome Canaryで『Network Time for Certificate Verification』という機能を有効にできます。これは、サーバ証明書を検証する際に、PC端末の時刻ではなくネットワークから取得した時刻を使って検証するようにする機能です。

これまでの挙動

これまでの挙動としては、サーバ証明書時に時刻上の問題がある場合、『端末の時刻がズレている』というエラーが出ます。

どうやって端末の時刻がずれていると識別するかは、「Where the Wild Warnings Are: Root Causes of Chrome Certificate Errors」に掛かれています。Googleのサーバに接続し、時刻を取得します。このとき、Chromeにハードコードされた公開鍵を使用するため、時刻がズレてても正しくGoogleのサーバを信頼できます。( 該当ソースコードURL )

(論文にも掛かれていますが、証明書のエラー原因としてクライアントの時刻設定ミスがそれなりにあるようです。)

『Network Time for Certificate Verification』

chrome://flags/ より、機能を有効にできます。

有効にすると、端末の時刻がズレていても証明書エラーが出なくなります。
(初回の証明書エラー時に時刻をフェッチしに行くのか、初回だけエラーがでますが、その時刻はキャッシュされるようなのでほかサイトでも問題なく閲覧できるようです。)

ネットワークから取得した時刻で証明書エラーになった場合は、端末の時刻を利用するため、意図的に未来や将来の証明書を試す場合も問題なさそうです。

今後

今後、この機能がどう有効化されていくかは、今のところ情報はなさそうです。

プライベート用途に使える .internal ドメイン

2024年7月に、ICANNで .internal トップレベルドメイン(TLD) がプライベート用途として予約されたようです。

背景

長らくプライベート用途で利用できるトップレベルドメインについて議論されてきました。

現在、各組織が独自のTLDをプライベート用に利用しているケースがあります。しかし以下のような問題があります、

  • 新gTLDが登録された際に、衝突する可能性がある
  • Root DNSへ不要な問い合わせがある

実際、.home、.internal、.lan、.corp、.localdomain、.dlink、.zyxel-usg のような問い合わせがRoot DNSに来ていることが知られています。

そこで、.internal をプライベート用途として予約しようというのが、ICANNで議論されている『SAC113:SSAC私的利用TLDに関する勧告(SAC113)』です。

JPNICさんの記事が詳しいです。
blog.nic.ad.jp

.internal ドメインの予約

下記の、2024 年 7 月 29 日のICANN 理事会の記録を見ると
Approved Resolutions | Special Meeting of the ICANN Board | 29 July 2024

".internal" をプライベート用途として恒久的に予約することが決まったようです。

IETF側の動き

上記のICANN側での決定を踏まえて、IETF側にも『A Top-level Domain for Private Use』というDraftがICANNの方から提出されています。

内容については、 .internal をプライベート用途に予約する旨書かれています。

追記: 本記事に頂いたコメント

補足を頂きましたのでここに追記しておきます。ありがとうございます。

信頼しているCAをネゴシエーションする TLS Trust Anchor Negotiation のメモ

IETFTLS WGでは、Googleの方らによって提案されている『TLS Trust Anchor Negotiation』という仕組みが議論されています。

これは、クライアントとサーバ側で共に信頼できるCA(トラストアンカー)をネゴシエーションし、複数あるサーバ証明書から適切なものを提供できるようにする仕組みです。

(引用: IETF 120 スライド PDF より)

具体的な提案仕様よりも、explainer を読むのが分かりやすい。自分用に軽く目を通しておく
https://github.com/davidben/tls-trust-expressions/blob/main/explainer.md

目次

背景

現状、クライアントがどのCAを信頼しているか伝えず、サーバ側は全てのクライアントに信頼されているだろうCAのサーバ証明書を利用します。

本議論の中では、それを『単一証明書デプロイモデル』と読んでいます。単一証明書デプロイモデルでは次のような

  • 新しいCAを利用しようとしても、全てのクライアントに信頼されている必要がある。更新されていないクライアントがいると利用できない。キーローテーションも同様
  • クライアント側が新しいセキュリティ要件を課したとして、古いクライアントが居るとそれに答えられない

この課題を解決するために、『複数証明書デプロイモデル』として、サーバ側がクライアントに合わせて証明書を出し分けられるようにするのが、『TLS Trust Anchor Negotiation』の議論である。

目標

TLS Trust Anchor Negotiationの目標は、Webで使用されるHTTPSにおいて『複数証明書デプロイモデル』を有効にすることです。次の項目を目指します。

  • 可用性と競合することなく、ユーザのセキュリティニーズを満たせるように進化できる
  • サーバ側では複数のサーバ証明書を設定でき、接続ごとに適切な証明書を自動的に送信できる
  • サーバの運用者の手動作業を可能な限り少なくし、ACMEが利用できる
  • TLSハンドシェイクに追加されるトラフィックを最小限に抑える

また、耐量子計算機暗号 (PQC) 証明書への移行などもユースケースに含まれている

実現案

既存の実現案として RFC 8446 TLS1.3には、certificate_authorities拡張を使う方法があります。certificate_authorities拡張を使うことで、サポートしているCAを示すことが出来ます。

しかし、certificate_authorities拡張は1CAあたり100バイト程度消費し、100CAを扱う昨今のクライアントでは、送信するデータ量が大きくなってしまいます。

そこで、Googleの方らによって次の2つの提案仕様が出されています

( 前者の仕様の議論を経て、後者の仕様が提出されていますが、現在は合わせて議論されている段階です

簡単に紹介します
(それぞれACMEの拡張も行ってたりしますが、細かいところは割愛

Trust Expressions

WebブラウザやOSによって管理される信頼するCAリスト(ルートプログラム)に、名前とバージョンを付けトラストストアマニフェストとします。クライアントはそのマニフェストを参照し、trust_expressionsとして送信することで信頼するCAのリストをサーバに伝えます。

enum { trust_expressions(TBD), (2^16-1) } ExtensionType;

struct {
    TrustStore trust_store;
    uint24 excluded_labels<0..2^16-1>;
} TrustExpression;

TrustExpression TrustExpressionList<1..2^16-1>;
Trust Anchor Identifiers

CAを5バイトで表現できるようにtrust anchor identifiersという識別子を導入しています。これを用いて、ハンドシェク中、クライアントはtrust_anchors拡張でサポートするCAのリストをサーバに通知できるようにします。

また、サーバも HTTPS/SVCB DNS レコード を用いて自身がサポートしているCAのリストを提示することで、クライアントが送信するデータ量を最小限に抑えることが出来ます。

example.net.  7200  IN SVCB 3 server.example.net. (
    tls-trust-anchors=32473.1,32473.2.1,32473.2.2 )

TCP上でQUICを喋る『QUIC on Streams』について復習しておく

TCP(+TLS)上でQUICおよびHTTP/3の通信を行うことを可能にする『QUIC on Streams』という仕様がFastlyのOku Kazuho氏らによって提案されている。

今年3月に行われたのIETF119で提案されている。

仕様は、TCP/TLS上でQUIC通信を行う『QUIC on Streams』と、それを使ってHTTP/3通信を行う『HTTP/3 on Streams』に分かれている。

今週IETF120があるので、キャッチアップしておく。

モチベーション

この提案の背景にあるのは、WebTransportといったHTTP上で動作する新しいプロトコルを設計する際に HTTP/3版とHTTP/2版の両方を設計・メンテナンスを行っているところにあります。


(引用: IETF119スライドPDFより)

なぜ新しいプロトコルでもHTTP/2版を設計するかと言うと、QUICのフォールバック先が必要だからです。

QUICはUDPで動作しており、一部のネットワークでは(そのネットワーク管理者が意図してか、意図せずか)QUICが通らないネットワークがあることが知られています。そのためHTTP/3は、疎通できないケースにおいては、TCPを使うHTTP/2にフォールバックするということが行われています。そのため、WebTransportのような新しいプロトコルも、フォールバック先としてHTTP/2版プロトコルを設計する必要があります。

もちろんHTTP/2とHTTP/3ではストリームやフレームの機能に違いがあるため、それぞれそれなりの仕様になっています。WebTransportのそれぞれの仕様は次の通り。

そこで、QUICそのものをTCP/TLS上で動作させることで、複数スタック用にプロトコル設計しなくても良くなります。それが、『QUIC on Streams』のモチベーションになります。


(引用: IETF119スライドPDFより)

『QUIC on Streams』の仕組み

『QUIC on Streams』はTLS over TCPのようなトランスポート上でQUICのフレームを送受信する仕組みを定義します。

下層のトランスポート

TLS over TCPが想定されていますが、使用上はそれだけに限定されているわけではなく、次の機能をもつトランスポートを想定しています。

  • 双方向のバイトストリーム通信
  • 信頼性 (再送などによる、データの配送保証)
  • 輻輳制御
  • 気密性と完全性
ストリームの送受信

『QUIC on Streams』では、トランスポート上で直接ストリームが送受信されます。QUICパケットヘッダは存在しません。

なお、送受信できるのは次のフレームに限定されます。

  • PADDING
  • RESET_STREAM
  • STOP_SENDING
  • STREAM
  • MAX_DATA
  • MAX_STREAM_DATA
  • MAX_STREAMS
  • DATA_BLOCKED
  • STREAM_DATA_BLOCKED
  • STREAMS_BLOCKED
  • CONNECTION_CLOSE

再送制御は下層トランスポートで行われるため、ACKフレームは送受信できません。また、コネクションマイグレーションも『QUIC on Streams』ではサポートされません。

一方で、次のフレームが追加で定義されています

  • QS_TRANSPORT_PARAMETERS: トランスポートパラメータを交換するフレーム
  • QS_PING: PINGの送受信
『QUIC on Streams』のその他
  • 一部トランスポートパラメータは使用禁止
  • 既存の拡張仕様がQUIC on Streams上で使えるかは、明示的に許可される必要がある
    • ただし、DATAGRAMは送信可能(下層のトランスポート特性により、信頼性が保証される)
  • QUICのバージョンネゴシエーションの仕組みはない

(UDP利用に起因するリフレクションがないとすれば、通信開始時のPADDINGの制約って緩和出来るんだろうか...?)

HTTP/3 on Streams

HTTP/3 on Streams』の仕様は非常に短いです。

TLS Encrypted Client Hello用のSSLKEYLOGFILE拡張の提案仕様

TLS Encrypted Client Hello用のSSLKEYLOGFILE拡張として『SSLKEYLOGFILE Extension for ECH』という提案仕様が提出されています。

背景

提案仕様の説明の前に、簡単にSSLKEYLOGFILEとECHについて補足します。

SSLKEYLOGFILEについて

TLS通信を復号するためには鍵の情報が必要です。トラブルシュートやデバッグのために、多くのTLS実装では"SSLKEYLOGFILE形式"でシークレットをログとして出力できます。例えば、OpenSSLやChromeブラウザなどがオプションを指定することでSSLKEYLOGFILEファイルを出力します。

具体的にはこのように各種シークレットが16進数で表記されます。

# SSL/TLS secrets log file, generated by OpenSSL
SERVER_HANDSHAKE_TRAFFIC_SECRET 24878b76381f03203d3c4772bf51c49c5786c7adcf7d8fdd644460d5deafd6d5 b48d1fdc6b10b6f4765456e8407649b25971f3384e63461bdacab59c2488cacb8bb7dcde0aa1e2c6ede9390b568624f4
EXPORTER_SECRET 24878b76381f03203d3c4772bf51c49c5786c7adcf7d8fdd644460d5deafd6d5 b56d696bd2fc3ef533dea35a6f907586cbbd7d049fd027d9964d3b924435ea157bfc955a55ef1d6ea7d5012ea906dee3
SERVER_TRAFFIC_SECRET_0 24878b76381f03203d3c4772bf51c49c5786c7adcf7d8fdd644460d5deafd6d5 4676aa104c6ac82822f4450c5a8d3990f70b64005bed05e50a9586e4cd2a6c0187fec0220a83ed21e69eb61fd9e9cfaf
CLIENT_HANDSHAKE_TRAFFIC_SECRET 24878b76381f03203d3c4772bf51c49c5786c7adcf7d8fdd644460d5deafd6d5 6ef4d40e4103a2aa00c985a5287314048fdaddd781f7ee90a2b98513efef6fde04a00950721660ba9e5afb184fbafc70
CLIENT_TRAFFIC_SECRET_0 24878b76381f03203d3c4772bf51c49c5786c7adcf7d8fdd644460d5deafd6d5 8408e4b76dfcb3850eea590c8be1a0fb42a5c63f85246b1b6b16661241670f19c0a511b3d683d5bafc650e89efc04890

また、WireSharkにSSLKEYLOGFILEを食わせることで、キャプチャした該当通信を復号することもできます。

SSLKEYLOGFILEは、現在『The SSLKEYLOGFILE Format for TLS』として標準化が進められています。

Encrypted Client Hello

TLSハンドシェイク中にクライアントから送信されるClientHelloは、暗号化されません。特にSNI拡張は通信先のドメインが記載されるため、通信の観測者に情報を与えてしまいます。

そこで、ClientHelloの暗号化『TLS Encrypted Client Hello』という仕様が提案されています。詳しい仕組みについては詳しい解説が幾つか公開されておりますので、そちらに譲ります。

blog.cloudflare.com

SSLKEYLOGFILE Extension for Encrypted Client Hello

SSLKEYLOGFILE Extension for ECH』では、SSLKEYLOGFILEに以下の情報を記載可能に拡張する。

  • ECH_SECRET: ECHで使われる、HPKE キー スケジュールで生成されるシークレット
  • ECH_CONFIG: ECH拡張に使用されたECHConfigの値 (16進数表記)

これらの情報によりEncrypted Client Helloが復号できるようになる。

DNSでTLSハンドシェイクの鍵交換を改善する、TLS Key Share Predictionについて

IETFGoogleの方々から提案されている『TLS Key Share Prediction』という提案仕様が、WG Adoptionされています。

これは、DNS HTTPS レコードを用いることでTLSハンドシェイクを改善することを目的とした提案仕様です。

TLSハンドシェイクのKey Shareについて

まず、Key Shareについて簡単に補足する

TLSハンドシェイクのClientHelloでは、鍵交換でサポートするnamed groups(名前付きグループ)をSupported groups拡張で送信します。合わせて、鍵交換に必要なパラメータをKey share拡張で送信します。Key Share拡張にはnamed groups事に必要なパラメータを送信します(サポートする全てのnamed groups分送る事は必須ではない)。

Chromeの例:

Key Share拡張には下記のようなトレードオフがあります。

  • 複数のnamed groupsのKeyShareEntryを送ると、その分 データ量が増える
  • 送ったKeyShareEntryにサーバが対応してないかった場合、HelloRetryRequestによって1RTT余計に時間がかかる。

そこでこのトレードオフを改善するために『TLS Key Share Prediction』が役に立ちます。

TLS Key Share Prediction

TLS Key Share Prediction』では、DNS HTTPSレコードにサーバが対応しているSupported groupsをユーザに通知することによって、クライアントはClientHelloで送信する必要があるKey Shareを知ることができます。

これにより、Key Share拡張におけるトレードオフは緩和され、必要なKeyShareEntryのみを送信することが出来るようになります。

(もしなんらかの理由により、HTTPSレコードと齟齬があったとしてもHelloRetryRequestを挟みますが、通信自体は問題なく継続できます)

HTTPSレコードのtls-supported-groupsパラメータ

この仕様では、HTTPSレコードにtls-supported-groupsを新しく定義し、そこにSupported groupsの値を書けるようにします