WebサイトのCookieの受け入れ方針を伝える『Cookie-Preference』ヘッダ

IETFに「The Cookie-Preference HTTP Header Field」という提案仕様が提出されています。

Webサイトを閲覧していると、Cookieについて受け入れる/拒否するのボタンを選択させられる機会もあるかとおもいます。それに対して、HTTPリクエストで、WebサイトにCookieの受け入れ方針を伝えられるようにする提案です。

Cookie-Preference: essential

Cookie-Preference: all; level="high"

Cookie-Preference: ask; granularity="category"

Cookie-Preferenceヘッダの値は次の値が定義されています

  • all: すべてのクッキーを受け入れる
  • essential: 必要不可欠なクッキー(セッション、認証、セキュリティなど)のみを受け入れる
  • none: すべてのクッキーを拒否する
  • ask: 必須ではないクッキーを設定する前に、明示的または詳細な同意を求める

その他にも、ユースケースとしてlevelやgranularityをパラメータとして例示していますが、仕様中では厳密な定義を与えてはおりません。

おまけ (その他の類似機能)

古くは、DNTヘッダー (Do not track)や、Sec-GPC(Global Privacy Control)ヘッダというものもあるが Cookieの受け入れ条件を指定出来ないというのが主な違いになります

Webクローラーが付加するWeb-Bot-Authの署名を検証してみる

GoogleのクローラーBotがWeb-Bot-Authの仕様を実験実装してたりします。
developers.google.com

Web-Bot-Authでは、Botはリクエストに署名を付けHTTPリクエストを送信してきます。こうすることで、User-Agentだけに頼るのではなく、署名検証を通してそのBotが正規のものか確認できます。これにより、AIの学習をしたりするBotを適切に認証したり、はたまたBotの学習行為に対して課金したりできます。

実際に試す

私の個人サイトへ、Google Botが署名付きでリクエストを送ってきてくれれば良いものの、、、まだ付加してこなさそうです。
アクセスログを見ると、ahrefs.com というBotがWeb-Bot-Auth署名付きのリクエストを送ってきたので、署名検証をしてみます。

署名検証に必要なパラメータ

署名の検証に必要な情報は大体次のとおりです。
基本的なパラメータは『RFC 9421 - HTTP Message Signatures』に則ったパラメータがHTTPリクエストにのかってきます。
(下記jsonは便宜上、json形式で表現しただけで。仕様で定義されているフォーマットでは有りません)

{
  "received_at_unix": 1781486729,
  "authority": "asnokaze.com",
  "headers": {
    "signature": "sig=:+wkpd7nQVTXX2qrvPUiDm2ZXU5Uzdgi759hZgzZmgViGue+zgxa12+ysInY1IBEIjqFUpgG8YzJ8FekBZ6JGAw==:",
    "signature-input": "sig=(\"@authority\" \"signature-agent\");created=1781486729;keyid=\"e3vpiy0B6M1Wdxnizw3dqRSgpqS6SXM2qiQ6HtUwZ5g\";alg=\"ed25519\";expires=1781490329;nonce=\"NcuWdzP41zzBqJr0SAr4RJQQZaKt72aCN8rk_Ee7z_vgaeD-4l7G0PMisYEZnRftOxmoNoFnM-fiJzNaea2ZLg\";tag=\"web-bot-auth\"",
    "signature-agent": "\"https://ahrefs.com\""
  }
}
検証

主な流れは次の通り

  • signature-agentを読み取り、https://ahrefs.com/.well-known/http-message-signatures-directory にアクセスし、keyidに対応する公開鍵を取得する
  • 取得した公開鍵と、各種パラメータ(暗号アルゴリズム, nonce, tag)より、署名値を検証する (署名の範囲は authorityヘッダとsignature-agentヘッダ)
  • 時刻が expires を越えてないことを確認する

これにより、アクセスしたBotがahrefsの正規のBotであることが確認できる

おまけ: 実験コード

上記のような、署名検証に必要な情報をまとめたjsonで、Web-Bot-Authの署名検証をする実験コード
https://gist.github.com/flano-yuki/de66a66fbb64340658393960a566090d

iOSで実装されている、期限切れDNSキャッシュを活用する Optimistic DNS について

Appleの方から『Optimistic DNS』という提案仕様がIETFに提出されています。
www.ietf.org


Optimistic DNS の概要

Optimistic DNSは、クライアント側で動作するスタブリゾルバ機構です。

その動作は、期限切れのキャッシュされたレコードをアプリケーションに即座に返しつつ、同時に新しいネットワーククエリを発行してレコードを更新することで、TTL の期限切れによる名前解決遅延を解消します。

サーバと動作するのではなく、アプリケーションからAPIを叩く形で動作する前提で仕様は書かれているようです。

提案仕様の図にある通り、期限が切れていてもアプリケーションは以前のキャッシュを利用します。その後にDNS解決を行いそのキャッシュを更新します。これにより、アプリケーションの待ち時間が低減できます。( その後freshなデータを受信しだい、アプリケーションに通知されます。)

(なお、仕様上はアプリケーションがOptimistic DNSを利用するかはオプトイン方式として書かれては居ます)

このような仕様であれば、サーバ運用者も比較的短いTTLでDNSを運用できオペレーションがしやすくなるとも謳っています。

実装

2018年頃のmacOS 10.14 / iOS 12からすでにこの機能が実装されています。今回提出された提案仕様は、その実装を反映したもののようです。
アプリケーションとAPIを介してやりとりするようです。

github.com

運用およびセキュリティ上の注意点

慣例に基づき提案仕様では『Operational Considerations』『Security Considerations』の項目があります。

Optimistic DNSでは古いデータを利用してしまう可能性があり、運用およびセキュリティ上の考慮事項があります。

IPアドレスの再利用

DNSレコードの有効期限が切れると、そのレコードに含まれていたIPアドレスは、別のホストで再利用されている可能性があります。

HTTPS接続の場合、TLS証明書の検証によってこの不一致が検出され、データが誤った相手に送信されるのを防ぎます。暗号化されていないプロトコルの場合、意図しないサーバーに接続してしまうリスクがあります

ポイズニングの増幅

攻撃者がキャッシュエントリを改ざんすることに成功した場合、オプティミスティックDNSは改ざんされたレコードの有効期間を元のTTLを超えて延長する可能性があります。

Chromeのキャッシュ利用効率を改善する Cache sharing for extremely-pervasive resources

Chromeでは、多くのWebサイトから引用されているリソースのキャッシュ利用効率を改善する『Cache sharing for extremely-pervasive resources』という機能があります。

通常のリソースはDouble-kyed HTTP Cacheですが、extremely-pervasive resourcesではSingle-keyed HTTP cacheとなります。

補足: Double-keyed HTTP Cache

Double-keyed HTTP Cacheとは、Webリソースのキャッシュキーとして、"読み元となったtop-level site"と"読み込み先のURL"の両方をキーとしてキャッシュする動作です

下記の○○.jsのキャッシュは共有されません。

こうなっている理由は、サイドチャネル攻撃によりユーザのプライバシーを損なうことを防ぐためです。(読み込み速度を計ることで、それらがキャッシュ済み == 特定サイトに訪問済みかが分かるなど。)

Cache sharing for extremely-pervasive resources

Double-keyed HTTP Cacheはもちろんキャッシュの利用効率を下げるため、一般に広く利用されているリソース (extremely-pervasive resources)のみはSingle-keyed HTTP cache扱いになります。( extremely-pervasive resourcesであればサイドチャネル攻撃のリスクが低い)

読み込んだリソースURLのみをキーとするため、

下記の○○.jsのキャッシュは共有されます

extremely-pervasive resourcesの例としては下記のような、一般に使われるjsファイル類などです

https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js
...

具体的には、chromeのソースコードに含まれているのでそこで確認できます
https://chromium.googlesource.com/chromium/src/+/master/services/network/pervasive_resources/shared_resource_checker_patterns.h

Prefetchしたリソースが実際に使われたか確認できる Prefetch Activation Beacon API

Chromeの開発者メーリングリストで『Prefetch Activation Beacon API』という機能が提案されています。

この機能を使うことで、prefetchしたリソースが有効活用されていることが確認できます。

Webにおいて、prefetchしたリソースが実際に有効に使用されているか確認することは重用です。不要にprefetchしていたり、逆に必要なリソースがprefetchされてないことがあります。

Prefetch Activation Beacon API

Prefetch Activation Beacon APIの大まかな流れは次のとおりです

ブラウザがまずprefetchを実行します。例えば、ブラウザにprefetchをさせるには次のようなlinkタグで実行させることが出来ます

<link rel="prefetch" href="/app/style.css" />

サーバ側は、prefetchリクエストに対して、on-prefetch-activationレスポンスヘッダを付けてレスポンスします。(同じドメインである必要があります)

on-prefetch-activation: https://example.com/beacon-endpoint?/app/style.css

prefetchでキャッシュしたリソースを実際に使用する際に、指定されたエンドポイントにHEADリクエストを送信します。これにより、実際に利用されたことがサーバ側で確認できるようになるという仕組みのようです

128bit以上の可変長をもつ UUID Long の提案仕様

128bit以上の値を持てる『UUID Long』という提案仕様がIETFに提出されています。(ただし、提案仕様は誰でも提出でき、それだけで標準化が進むものではない点に注意してください。)

UUID Long

UUID Longのフォーマットは次のとおりです。128bit領域は既存のUUIDと同じフォーマットであり、Variantとして0xFが入るのが特徴です。そのあとに、可変長領域 (UUID Long Data)が入ります

例としては

xxxxxxxx-xxxx-xxxx-Fxxx-xxxxxxxxxxxx-yy..zz
  • xxx: ショートUUID bit
  • F: Variant固定値
  • yy...zz: 32~3968 のUUID Long Data
Sub-Variant

UUID Long Dataに格納されるデータは、Sub-Variant, Algorithm, Length で指定されたデータを持ちます。

Sub-Variantは仕様中で定義されており、例えば、Sub-Variant 2 は時間ベースのデータが定義されています。

同様にSub-Variant 3はハッシュ値ベースのものが定義されています。

エンコーディング

UUID Longは文字列表現が長くなることから、通常の16進数表記に加えBase32やBase64でのエンコーディングに対応すると明示されています。

また、著者によって新しいエンコーディングとして下記の提案仕様が別途出されていたりもします。

RFC 9931、HTTP/1.1における楽観的プロトコル遷移のセキュリティ

RFC 9931 Security Considerations for Optimistic Protocol Transitions in HTTP/1.1』が発行されました。

このRFCはHTTP/1.1におけるプロトコル遷移(Protocol Transitions)のセキュリティ上の注意点について記述しています。HTTP/1.1ではWebSocket(Upgrade)やCONNECT-TCPといった機能で、確立したコネクションを別の用途に使用することが出来ます。この時に楽観的な処理を行うとセキュリティ上の問題になるということです。

この問題は、RFCを書く人やプロトコルスタックを実装する(ブラウザ実装者など)が意識する問題で、通常のWebエンジニアは特に意識することはないのかなと思います。

楽観的プロトコル遷移によるRequest Smuggling

楽観的プロトコル遷移(Optimistic Protocol Transitions)とは、UpgradeやCONNECTを行うリクエストを送り、成功したことを前提に後続のデータを送信し始めることです。もちろんプロコトル遷移に失敗することもあります。その場合、Request Smuggling攻撃が成立します。

CONNECTメソッドの例を下記に上げます。


  • クライアントは、CONNECTメソッドを送信します
  • クライアントは続けて、CONNECTをメソッドが成功したこと前提に、CONNECT後のデータの送信します。このとき、Request Smuggling攻撃の例としてHTTPとして解釈できるデータが送信されるものとします。
  • サーバは、CONNECTメソッドに対して エラー系レスポンスを返します。
  • サーバは、後続のデータをHTTP/1.1として解釈して処理します

このように、Request Smuggling攻撃が成立します。

なお、HTTP/2以降ではHTTPヘッダの情報はHEADERSフレームに格納されますが、プロトコル遷移後のデータはDATAフレームに格納されるためRequest Smuggling攻撃は成立しません。

既存の仕様はどうなっているか?

楽観的プロトコル遷移が許可されているかは個別の仕様によります

  • WebSocket: Upgradeの楽観的な使用は既に禁止されています
  • connect-udp: 元々楽観的なUpgrade可能でしたが、今回HTTP/1.1では禁止になりました
  • connect-ip: Upgradeの楽観的な使用は既に禁止されています

今後のプロトコル設計について

プロトコルの設計として、楽観的なプロトコルを遷移を禁止するか、もしくは後続データをHTTP/1.1と解釈できなくなるように設計するようにガイダンスされています。

具体的には

  • HTTP Upgradeの楽観的な使用を禁止する
  • 遷移後のデータとして、最初にHTTP/1.1処理を意図的に終了させる固定の文字列を埋め込む (HTTP/2 Preface)
  • クライアントからサーバーへのデータに高エントロピーマスキングを適用する(WebSocket)

という感じでした