HTTP Cookie

HTTP Cookie (ウェブ Cookie、ブラウザー Cookie) は、サーバーがユーザーのウェブブラウザーに送信する小さなデータであり、ブラウザーに保存され、その後のリクエストと共に同じサーバーへ返送されます。一般的には、二つのリクエストが同じブラウザーから送信されたものであるかを知るために使用されます。例えば、ユーザーのログイン状態を維持することができます。Cookie は、ステートレスな HTTP プロトコルのためにステートフルな情報を記憶します。

Cookie は主に、以下の 3 つの用途で使用されます。

セッション管理
ログイン、ショッピングカート、ゲームのスコア、またはその他のサーバーが覚えておくべきもの
パーソナライゼーション
ユーザー設定、テーマ、その他の設定
トラッキング
ユーザーの行動の記録及び分析

Cookie は、クライアント側の汎用的な記憶領域として使用されたことがあります。これは他にクライアントへデータを保存する手段がなかった頃は合理的でしたが、現在では新しいストレージ API を使用することが推奨されています。 Cookie はすべてのリクエストで送信されるので、 (特にモバイルデータ通信で) 性能を悪化させる可能性があります。クライアントストレージ向けの新しい API として、Web Storage API (localStorage および sessionStorage) と IndexedDB があります。

保存された Cookie (およびウェブページが使用できる他のストレージ) を確認するには、開発ツールのストレージインスペクターを有効化して、ストレージのツリーで Cookie を選択してください。

Cookie の作成

HTTP リクエストを受け取った後、サーバーはレスポンスで Set-Cookie ヘッダーを送信することができます。通常 Cookie はブラウザーに保存され、また Cookie は同じサーバーに対して行われるリクエストと共に HTTP の Cookie ヘッダーの中で送信されます。有効期限や期間を設定することができ、その後は Cookie が送信されなくなります。特定のドメインやパスへの追加の制約を設定することができ、Cookie をどこに送信するかを制限することができます。以下で言及されているヘッダー属性の詳細については、 Set-Cookie のリファレンス記事を参照してください。

HTTP の Set-Cookie レスポンスヘッダーは、サーバーがユーザーエージェントへ Cookie を送信するために使用します。単純な Cookie は次のように設定されます。

Set-Cookie: <cookie-name>=<cookie-value>

これは、サーバーからクライアントへ Cookie の組み合わせを保存するよう指示することを表します。

HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

[ページの内容]

また、そのサーバーへのその後のすべてのリクエストにおいて、ブラウザーは以前格納されたすべてのクッキーを、 Cookie ヘッダーを使用してサーバーへ送信します。

GET /sample_page.html HTTP/2.0
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
注: 様々なサーバー側アプリケーションにおける Set-Cookie ヘッダーの使い方を紹介します。

Cookie の持続時間は2通りの方法で定義することができます。

  • セッション Cookie は現在のセッションが終了すると削除されます。ブラウザーはいつ「現在のセッション」が終わったと見なすかを定義し、ブラウザーによっては再起動時にセッションの復元を使用するため、セッションクッキーが無期限に持続することがあります。
  • 持続的 Cookie は、 Expires 属性で指定された時刻、または Max-Age で指定された期間が経過した後に削除されます。

例を示します。

Set-Cookie: id=a3fWa; Expires=Wed, 31 Oct 2021 07:28:00 GMT;

: Expires の日付を設定した場合、設定された日時はサーバーではなく、Cookie が設定されるクライアントの日時に関連します。

サイトがユーザーを認証する場合、ユーザーが認証するたびに、すでに存在するセッションクッキーも含めて、セッションクッキーを再生成して再送する必要があります。この手法は、第三者がユーザーのセッションを再利用するセッション固定攻撃を防ぐのに役立ちます。

Cookie へのアクセス制限

クッキーが安全に送信され、意図しない第三者やスクリプトからアクセスされないようにするには、 Secure 属性と HttpOnly 属性の2つの方法があります。

Secure 属性がついたクッキーは HTTPS プロトコル上の暗号化されたリクエストでのみサーバーに送信され、安全でない HTTP では決して送信されないため、中間者攻撃者が簡単にアクセスすることはできません。 (URL に http: を含む) 安全でないサイトは、 Secure 属性を使用してクッキーを設定することができません。ただし、 Secure によってクッキー内の機密情報へのアクセスをすべて防げると思ってはいけません。例えば、クライアントのハードディスクへアクセスすることで読み取られる可能性があります。

HttpOnly 属性を持つクッキーは、JavaScript の Document.cookie API にはアクセスできません。サーバーに送信されるだけです。例えば、サーバー側のセッションを持続させるクッキーは JavaScript が利用する必要はないので、 HttpOnly 属性をつけるべきです。この予防策は、クロスサイトスクリプティング (XSS) 攻撃を緩和するのに役立ちます。

例を示します。

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly

Cookie の送信先の定義

Domain および Path 属性は、Cookie のスコープ、つまり Cookie を送信する対象の URL を定義します。

Domain 属性

Domain 属性は、Cookie を受信することができるホストを指定します。指定されていない場合は、既定でクッキーを設定したのと同じオリジンとなり、サブドメインは除外されますDomain が指定された場合、サブドメインは常に含まれます。したがって、 Domain を指定すると省略時よりも制限が緩和されます。ただし、サブドメイン間でユーザーに関する情報を共有する場合は有用になるでしょう。

例えば、Domain=mozilla.org を設定すると、developer.mozilla.org のようなサブドメインも含まれます。

Path 属性

Path 属性は、 Cookie ヘッダーを送信するためにリクエストされた URL の中に含む必要がある URL のパスを示します。 %x2F ("/") の文字はディレクトリ区切り文字として解釈され、サブディレクトリにも同様に一致します。

例えば、Path=/docs を設定すると、以下のパスに一致します。

  • /docs
  • /docs/Web/
  • /docs/Web/HTTP

SameSite 属性

SameSite 属性により、サーバーがオリジン間リクエスト (ここでサイトは登録可能なドメインによって定義されます) と一緒にクッキーを送るべきではないことを要求することができます。これは、クロスサイトリクエストフォージェリ攻撃 (CSRF) に対していくらかの防御となります。

取ることができる値は Strict, Lax, None の3つです。 Strict では、クッキーはそれが発生したものと同じサイトに対してのみ送信されます。 Lax も似ていますが、ユーザーがリンクをたどるなど、外部のサイトからある URL に移動した場合は除きます。 None はサイト間リクエストの制限はありません。

次に例を示します。

Set-Cookie: mykey=myvalue; SameSite=Strict

SameSite 属性の値は大文字小文字の区別はありません。

ブラウザーはクッキーの既定値を SameSite=Lax にするように移行しつつあります。 Cookie をオリジン間で送信する必要がある場合は、 None ディレクティブを使って SameSite の制限を解除してください。None ディレクティブは Secure 属性を必要とします。

Cookie の仕組みの設計では、クッキーが安全なオリジンに設定されているかどうか、クッキーが当初はどこに設定されたのかをサーバーが確認することができないようになっています。

サブドメイン上にある脆弱性のあるアプリケーションが Domain 属性を使用してクッキーを設定すると、ほかのすべてのサブドメインでクッキーにアクセスできるようにすることができます。この仕組みはセッション固定攻撃で悪用される可能性があります。主な対策方法はセッション固定化を参照してください。

しかし、多層防御として、 Cookie に関する特定の事実を主張するために Cookie の接頭辞を使うことが可能です。以下の二つの接頭辞が利用可能です。

__Host-
Cookie 名にこの接頭辞がついている場合、 Set-Cookie ヘッダーが受け入れられるのは Secure 属性で指定されており、安全なオリジンから送信されており、 Domain 属性を含んでおらずPath 属性が / に設定されている場合のみです。この場合、これらの Cookie は「ドメインにロックされている」と見なすことができます。
__Secure-
Cookie 名にこの接頭辞がある場合、 Set-Cookie ディレクティブが受け入れられるのは、 Secure であり、安全なオリジンから送信されている場合のみです。これは __Host- 接頭辞よりも弱いものです。

これらの接頭辞が付いていて、制約に適合していないクッキーは、送られてもブラウザーが拒否します。これにより、仮にサブドメインで接頭辞の付いた Cookie を作成した場合、サブドメインに限定されるか、完全に無視されるかします。アプリケーションサーバーは、ユーザーが認証されているか、あるいは CSRF トークンが正しいかどうかを判断するときに、特定の Cookie 名をチェックするだけなので、これはセッションの固定化に対する防御手段として効果的に機能します。

アプリケーションサーバ上では、ウェブアプリケーションは接頭辞を含む完全な Cookie 名をチェックしなければなりません。—ユーザーエージェントは、リクエストの Cookie ヘッダーを送信する前に Cookie から接頭辞を削除しません

Cookie の接頭辞とブラウザー対応の現在の状態については、 Set-Cookie リファレンス記事の接頭辞の節を参照してください。

JavaScript でDocument.cookies を使用してアクセスする

Document.cookie プロパティを使用して新しい Cookie を作成することができますし、 HttpOnly フラグが設定されていない限り、既存の Cookie に JavaScript からアクセスすることもできます。

document.cookie = "yummy_cookie=choco"; 
document.cookie = "tasty_cookie=strawberry"; 
console.log(document.cookie); 
// "yummy_cookie=choco; tasty_cookie=strawberry" をログに記録

JavaScript で生成された Cookie は HttpOnly フラグを含むことができません。

後述するセキュリティの節に記載したとおり、セキュリティの影響に注意してください。JavaScript で使用できる Cookie は、XSS によって盗まれる可能性があります。

セキュリティ

情報をクッキーに保存するときは、すべてのクッキーの値がエンドユーザーから見え、変更できることを理解しておいてください。アプリケーションによっては、サーバー側で検索される不透明な識別子を使用するか、 JSON ウェブトークンのような代替の認証/機密性メカニズムを調べたほうが良いかもしれません。

クッキーへの攻撃を緩和する方法には次のようなものがあります。

  • HttpOnly 属性を使用して、 JavaScript からクッキーの値にアクセスすることを防ぎます。
  • 機密情報 (認証を示す場合など) のために使用されたクッキーは、持続時間を短く、 SameSite 属性を Strict または Lax に設定してください。 (上記の SameSite Cookie を参照。) SameSite に対応しているブラウザーでは、これは、認証クッキーがオリジン間リクエストと一緒に送信されないようにする効果があるので、そのようなリクエストはそのアプリケーションサーバーに対して事実上認証されていないことになります。

トラッキングとプライバシー

サードパーティの Cookie

Cookie はドメインに関連付けられます。このドメインが閲覧しているページのドメインと同じである場合、そのクッキーは、ファーストパーティ Cookie と呼ばれます。ドメインが異なる場合は、サードパーティ Cookie と呼びます。ウェブページをホスティングしているサーバーがファーストパーティ Cookie を設定する一方で、ページには他のドメインのサーバーに保存されている画像やその他のコンポーネント (例えば、広告バナー) が含まれている場合があり、サードパーティクッキーが設定されることがあります。これらは主にウェブ上での広告やトラッキングに使用されます。例えば Google が使用している Cookie の種類を参照してください。サードパーティのサーバーは、複数のサイトにアクセスした際に同じブラウザから送信されたクッキーに基づいて、ユーザーの閲覧履歴や習慣のプロファイルを構築することができます。 Firefox は既定で、トラッカーを含むことが知られているサードパーティのクッキーをブロックします。サードパーティのクッキー (またはトラッキングクッキー) は、他のブラウザーの設定や拡張機能によってもブロックされる場合があります。クッキーをブロックすると、一部のサードパーティ製コンポーネント (ソーシャルメディアウィジェットなど) が意図した通りに機能しなくなることがあります。

クッキーの使用を対象とした法規制には、以下のようなものがあります。

  • EU の 一般データ保護規則 (GDPR)
  • EU の ePrivacy 指令
  • カリフォルニア州消費者プライバシー法

これらの規制は、これらの管轄区域 (EUとカリフォルニア州、特にカリフォルニア州の法律は総収入が2,500万ドルを超える事業体にのみ適用されるという注意事項がある) のユーザーがアクセスするワールドワイドウェブ上のあらゆるサイトに適用されるため、世界的な広がりを持っています。

これらの規制の要件には次のようなものがあります。

  • サイトがクッキーを使用することをユーザーに通知する。
  • ユーザーが一部またはすべてのクッキーをオプトアウトできるようにする。
  • ユーザーがクッキーを受け取らなくても、サービスの大部分を利用できるようにする。

地域によっては、他にもクッキーの使用を管理する規制があるかもしれません。これらの規制を理解し遵守することは、自分自身の責任となります。これらの規制を遵守するのに役立つ「クッキー禁止」コードを提供している会社もあります。

ブラウザーに情報を格納する他の方法

ブラウザーにデータを保存する別のアプローチとして、 Web Storage API があります。 window.sessionStoragewindow.localStorage プロパティはセッションクッキーと持続的クッキーに対応していますが、ストレージの容量制限がクッキーより大きく、サーバーに送信されることはありません。より構造化された大量のデータは、 IndexedDB API またはその上に構築されたライブラリを使用して保存することができます。

「ゾンビ」クッキーと呼ばれる、クッキーが削除された後に再作成されるようにするための他の技術が作成されています。これらの技術は、ユーザーのプライバシーとユーザー制御の原則に違反し、データプライバシー規制に違反する可能性があり、これらの技術を使用しているウェブサイトが法的責任にさらされる可能性があります。

関連情報