はじめまして。株式会社レコチョク システム開発推進部の祖父江です。
先日業務でサブドメイン間でログイン情報を共有する、という作業がありました。
このときにCookieの接頭辞について調べる機会があり、種類や使い分けについて勉強になったので今回はそれをまとめたいと思います。
Cookie
CookieとはWebブラウザとWebサーバ間で状態を保持し管理するために、ユーザのWebブラウザで保存されるデータのことです。
WebブラウザとWebサーバは以下のようにCookieをやりとりします。
- 最初のWebサービスへ接続
- WebサーバからWebブラウザに向けてCookieが送信される
- Cookieはブラウザーに保存され、2回目のWebサーバの接続時にWebサーバから受け取ったCookieを返送する
Cookieの属性
Cookieに設定してある情報のことを「属性」と呼び、以下の種類があります。
属性はサーバからWebブラウザに保存して欲しい情報としてレスポンスにのせて送信されます。
属性 | 内容 |
---|---|
Name | 名前 |
Value | 値 |
Expires | 有効期限 |
Max-Age | 残存時間 |
Domain | Cookieが利用されるドメイン |
Path | Cookieが利用されるサーバ上のパス |
Secure | クライアントからのHTTPS通信時にのみCookieを送信する |
HttpOnly | JavaScript経由でCookieが取得できないようにする |
SameSite | 別サイト遷移時にCookie送信するかどうか |
今回はCookie Prefixに関わっているDomain属性とPath属性、Secure属性について抜粋して紹介します。
一言で言えば、Domain属性とPath属性はCookieの送信先を設定し、Secure属性はCookieへのアクセスを制限するための属性です。
Domain属性
ドメイン属性は、ブラウザがCookieを送信する際の対象となるサーバのドメイン名を指定します。
何も指定しなかった場合は、CookieはそのCookieがセットされたドメインに対してのみ送信されます。
ドメインを指定した場合はそのドメインを含むURLにアクセスされた場合にCookieが送信されます。
例えば、ドメイン属性が
.example.comと設定されている場合は、Cookieは
www.example.comや
sub.example.comなど、サブドメインに対しても送信されます。
このようにドメインを指定すると、Cookieの送信先が増えてしまいます。
セキュリティ面を考えると、
- Cookieを発行したサイトに対してのみCookieを送信したい場合は、ドメイン属性は指定しない
- サブドメイン間でユーザーに関する情報を共有する場合のみドメイン属性をつける
といった使い分けをする必要があります。
Path属性
Path属性は、ブラウザがCookieを送信する際のURLのパスを指定します。
パス属性が指定されていない場合、CookieはそのCookieが発行されたページに対してのみ送信されます。
/hogehoge/index.htmlでCookieを発行したならば
/hogehoge/index.htmlにのみCookieが送信されます。
パス属性を指定した場合、指定パスとその配下に対してCookieが送信されます。
例えば、パス属性が
/hogehogeと設定されている場合、
/hogehoge/index.htmlや
/hogehoge/sub/index.htmlなどのURLに対してCookieが送信されます。
パス属性を /に設定すると、そのドメイン配下の全パスに対してCookieが送信されるようになります。
パス属性を利用することでサイト内でのCookieの有効範囲を細かく設定することができます。
Secure属性
CookieのSecure属性は、ブラウザがCookieを送信する際に、安全な接続(HTTPS通信)が行われている場合のみ送信されるよう指定するものです。
HTTP接続を使用している場合、そのCookieは送信されません。
もしHTTP通信でCookieが送信されるとどんなことが起きるかというと、HTTP通信の盗聴によりCookie情報を不正に乗っ取られる(セッション・ハイジャック)可能性が発生してしまいます。
セキュリティを高めるために、HTTPS通信を行なっている場合はSecure属性を指定する必要があります。
Cookie Perfixとは
Cookie PrefixとはCookie名に接頭辞( __Host-, __Secure-)を付け足すことによってサーバからブラウザにレスポンスを送信するときに、属性が下記条件で設定されていることを保証するものです。
Cookie名に __Secure-が付けられたCookieは、以下の条件を満たす必要があります。
- Secure属性がついていること
- HTTPS等のセキュアな通信でCookieがセットされること
Cookie名に __Host-が付けられたCookieは、より制約がきびしく、以下の条件を満たす必要があります。
- Secure属性がついていること
- HTTPS等のセキュアな通信でCookieがセットされること
- Domain属性が付いていないこと
- Path属性が/であること
これらの接頭辞が付いていて、制約に適合していないCookieがサーバから送られてきた場合、ブラウザは拒否します。
// Cookieがセットされる場合 Set-Cookie: __Secure-ID=123; Secure; Domain=example.com Set-Cookie: __Host-ID=123; Secure; Path=/ // Cookieがセットされない場合 Set-Cookie: __Secure-id=1 // Secure属性が無い Set-Cookie: __Host-id=1; Secure // Path=/が無い Set-Cookie: __Host-id=1; Secure; Path=/; Domain=example.com // Domain属性が設定されている |
なぜCookie Prefixが必要なのか
なぜ、わざわざPrefixを付ける必要があるのでしょうか?
理由は、サーバからブラウザにCookieをセットしたあとに、Cookie InjectionやJavaScriptなどによって攻撃者に不正なCookieをセットされることを防ぐためです。
ブラウザからサーバにリクエストが飛ぶ際に送られてくる情報はCookie名と値だけなので、サーバはそのCookieが安全に保存されたものなのか、もしくは攻撃者によってセットされたCookieなのか判断することができません。
そこでPrefixを持つCookieについては、属性を強制し、非HTTPSやサブドメインからのセットが出来ないようにすることで不正なCookieをブラウザ側で弾いています。
それによってサーバ側はPrefixをもつCookieに関してはブラウザ側でチェックしているため、Cookieが安全に保存されたものであること判断することができます。
Cookie Prefixの使い分け
__Secure-と __Host-は制約が異なるため、ユースケースによって使い分ける必要があります。
今回自分が業務で行ったドメインとサブドメイン間でCookieを共有したい場合には、ドメイン属性を指定できる __Secure-を使用する必要があります。
例えばサイトのドメイン domain.comとそのヘルプページ help.domain.comでログイン情報を共有したいときにはCookie名の頭に __Secure-を付け、ドメイン属性に domain.comを設定する必要があります。
しかし、 __Secure-を使用すると、サブドメインへのCookieのリークのリスクが高まる(=攻撃者がコントロールするサブドメインに対してCookieを送信してしまう)可能性があります。
したがって、同一ドメインでの使用しか想定されていないCookieであれば、ドメイン属性が付与されず(=セットされたドメインに対してのみCookieが送信される)、 Path 属性が/に限定される __Host-を使用することでCookieの送信先をより厳格に制限し、セキュリティリスクを減らすことができます。
__Host-のほうが __Secure-よりもセキュリティが高いことを理解した上で、利用用途に応じた適切な使い分けが必要なんですね。
まとめ
この記事では、Cookieの属性や接頭辞(Cookie Prefix)について解説しました。
- Cookieの属性とは、サーバからWebブラウザに保存して欲しい情報としてレスポンスに乗せて送信されるもの
- Cookie Prefixとは、Cookie名に特定の接頭辞を付けることで、特定の条件を満たしたCookieを保証するものであり、不正なCookieのセットを防ぐために設けられている
- 接頭辞には __Secure-と __Host-があり、それぞれ制約や使い方が異なる
今回Cookie Prefixについて調べ、Webサービスを安全に提供するためには、このようなCookieの知識がとても重要だと理解できました。
Cookieを適切に使用できるように、今後も知識を深めていきたいです!
最後までお読みいただき、ありがとうございました。