技術向上

プログラミングの学び、気になるテクノロジーやビジネストレンドを発信

Cookieの概要とセキュリティ

Webサーバとブラウザ間で状態を管理する通信プロトコル、その管理の中でブラウザに保存された情報を指します。
主な用途は、ショッピングサイトのカートの状態などで、ユーザーが操作した情報を一定期間保存して利便性を高めるために使われます。

動作

  1. サーバがHTTP-Responseのヘッダに、Set-Cookieを設定してクライアントに返却。nameとvalueのペアの他、有効期限や対象となるパスなどを指定できる

  2. クライアント側に情報が保存される

  3. 次回以降のHTTP-Requestは、ヘッダにCookie情報が含まれてサーバに送信される


Set-Cookieでは各種属性を用いて有効期限などを指定します。後述しますが、属性による制御は、クライアント側に強制するものではありません。セキュリティやプライバシーの観点から、クライアント側でCookieが削除されることがあります。


属性

Domain

CookieをRequestに含めて送信できるdomainを制御します。
指定されたdomainとそのsub-domainでのみ、Cookieが有効になります。
domain属性を指定しない場合、クライアントは、そのCookieが生成されたサーバにのみ、Cookieを送信します。(ただし一部のブラウザでは、これが当てはまらないことがあります。)
また、異なるホスト名を含むdomainを指定した場合は、その指定が無視されます。
指定するdomainの先頭が「.」の場合、その「.」は無いものとして扱われます(domain指定には問題ない)。ただし、末尾が「.」の場合、そのdomain指定自体が無視されます。

生成元とは異なるsub-domainが含まれるようにdomain属性を指定すると、非セキュアな状態を生んでしまうことに注意が必要です。例えばfoo.example.comのサーバが、Set-Cookieによってexample.comをdomainに指定すると、他のsub-domainであるbar.example.comへのRequest送信に際してもCookieを含めることができます。barはこのCookieと自身が作成したCookieを判別することができない可能性があります。これはfooがbarを攻撃できる可能性を持っていることを意味します。


Path

Cookieを送信できるURL pathを制御します。
path属性の指定を省略すると、Cookie生成元のURLのpathが指定されます。大抵、同一domain内の全てのRequestでCookieを送信したいと考えるため、pathにルートディレクトリ「/」を指定することが多くなります。
このpath属性は、セキュリティ保護には利用できません。pathを制御できるのはあくまでRequestによる送信のみであり、サーバからのResposeに対しては制御することができないからです。あるURL pathからのRequestに対して、異なるpathを指定したResponseを返すことができてしまいます。そのため、セキュアに保護すべき情報をCookieに格納すべきではありません。


Max-Age

Cookieの有効期限を秒数で表現します。Cookieの発行から指定された秒数が経過するまで、クライアントはCookieを維持することができます。
ただし、この有効期限はクライアントに保持を強制するものではありません。記憶容量の上限やプライバシー保護の観点から、クライアントが一方的にCookieを削除することがあります。
max-ageを指定しない場合、ブラウザを閉じると同時にCookieは削除されます。
古いブラウザですと、max-ageをサーポートしていない場合があります。


Expires

Cookieの有効期限を指定日時によって表現します。指定日時を経過するまで、クライアントはCookieを維持することができます。
ただし、この有効期限はクライアントに保持を強制するものではありません。記憶容量の上限やプライバシー保護の観点から、クライアントが一方的にCookieを削除することがあります。
expiresを指定しない場合、ブラウザを閉じると同時にCookieは削除されます。
max-ageも指定されている場合、max-ageが優先され、expiresは無視されます。


Secure

この属性をtrueにすると、接続がhttpsにより保護されている場合にのみCookieをRequestヘッダに含めることができます(ただしこれは一般論であり、https = secureと定義されているわけではなく、secureの定義はブラウザに任されています)。
一見すると、この属性の指定によりセキュアな状態が確保されると思われますが、そうではありません。
secureが制御するのはRequest送信のみです。よって悪意ある攻撃者は、http通信からのResposeを模倣してSet-Cookieヘッダを注入することにより、httpsによるRequestにCookieを注入することができます。それを受信するhttpsサーバは、送られてきたCookieと自身が生成したCookieを判別することができないため、この手法を用いて攻撃することは可能です。


HttpOnly

この属性をtrueにしない場合、JavaScriptからもCookieを参照することができます。
JavaScriptからの参照を許可する場合、XSSによる被害にあう可能性が高くなります。Cookieがセキュアに保護すべき情報を含む場合、httpOnlyをtrueにすべきでしょう。


セッション識別子

セキュリティ上の観点から、サーバがセッション情報をCookieに直に格納する代わりに、セッション識別子(使い捨ての番号)を格納することがよく行われます。サーバはセッション識別子を伴うRequestを受信すると、そのセッション識別子をキーにしてセッション情報を検索することができます。攻撃者は、Cookieからセッション識別子を読み取っても、さらにサーバと通信して成功しなければ欲しい情報を得ることができないため、Cookieを読み取られた時の被害を抑えることができます。

ただし、セッションハイジャックの一つである、セッションID固定化攻撃には注意が必要です。
セッションID固定化攻撃の流れは次の通りです。攻撃者が自身のブラウザで、あるサイトから正規にセッション識別子を取得した後、それを含めたURLをメールなどで被害者に共有しアクセスを促します。被害者がそのURLにアクセスすると、攻撃者がセッション識別子を利用してサーバと直に通信することができるようになります。
対策を講じるには、ログイン前とログイン後で異なるセッション識別子を用いるようにする、またはログイン後にセッションIDとは異なる情報を使って認証する必要があります。


参考

RFC 6265 — HTTP State Management Mechanism (日本語訳)

HTTP cookie - Wikipedia

Cookie の仕様とセキュリティ