ITの教科書検索
入門・発展ページ読了 約11分

Cookieとは ― セッションIDとの関係

Cookieとは、Webサーバがブラウザに預け、次のリクエストから送り返させる値です。ログインした状態が続く仕組み、セッションIDとの関係、番号を盗まれる攻撃と防ぎ方が分かります。

目次
  1. Cookieとは
  2. Cookieが要る理由
  3. Set-CookieとCookieヘッダ
  4. セッションIDとの関係
  5. ログインから次のページまで
  6. Cookieの種類
  7. 属性と書かないときの動き
  8. セッションハイジャック
  9. 練習問題

Cookieとは、サーバがブラウザに預けて送り返させる値

Cookieは、Webサーバがブラウザに預け、次からのリクエストに付けて送り返させる名前と値の組です。HTTPはリクエストを1つずつ切り離して扱うので、サーバはCookieを手がかりに、同じ利用者からのリクエストかを見分けます。

ログインした状態が次のページでも続くのは、この仕組みによるものです。多くのサイトは、Cookieに番号だけを入れ、利用者の情報はサーバの側に置きます。この番号がセッションIDです。

Cookieが要る理由は、HTTPが前のリクエストを覚えないから

HTTPの仕様であるRFC 9110は、3.3節でHTTPを状態を持たないプロトコルと定めています。1つ1つのリクエストは、それだけで意味が分かるように作られています。前にどんなリクエストが来たかによって、意味が変わることはありません。

同じ節によると、同じ接続で届いた2つのリクエストでも、原則として同じブラウザからのものと決めつけてはいけません。このままでは、ログインのリクエストと次のページのリクエストが、サーバから見て別々の出来事になります。そこでサーバは、最初の応答で目印を渡します。ブラウザは、次から目印を付けて送ります。

Set-CookieヘッダとCookieヘッダのやり取り

サーバは、レスポンスのSet-Cookieヘッダで、Cookieの名前と値をブラウザに渡します。ブラウザは、受け取ったCookieを保存します。同じサイトへ次にリクエストを送るとき、ブラウザは値をCookieヘッダに入れて付けます。

レスポンスサーバ → ブラウザ
HTTP/1.1 200 OK
Set-Cookie: SID=31d4d96e407aad42; Path=/; Secure; HttpOnly

# SID が名前、31d4d96e407aad42 が値
# 「;」の後ろの Path・Secure・HttpOnly が属性
リクエストブラウザ → サーバ
GET /mypage HTTP/1.1
Host: example.com
Cookie: SID=31d4d96e407aad42

# 送り返すのは名前と値だけ

上の例は、Cookieの仕様であるRFC 6265の3.1節にあるものです。保存場所と流れる向きを、図にすると次のとおりです。

ブラウザCookieの保管場所SID=31d4d96e407aad42① Set-Cookieで番号を渡す② Cookieヘッダで毎回付けて送るサーバセッション表番号中身31d4d96e407aad42利用者A・ログイン中
サーバは、Set-Cookieヘッダで番号だけをブラウザに渡し、利用者の情報は自分のセッション表に残します。ブラウザは、同じサイトへリクエストを送るたびに、その番号をCookieヘッダに付けます。色を付けた2つの値は、同じ番号です。

Cookieヘッダに入るのは、名前と値だけです。RFC 6265の4.2.2節のとおり、PathやSecureなどの属性は送り返されません。属性は、ブラウザがいつどこへ送るかを決めるための指示です。

Cookieを消したいとき、サーバは期限を過去の日時にしたSet-Cookieを送ります。ブラウザは、期限の切れたCookieを送らなくなります。

セッションIDとの関係:中身はサーバ、ブラウザは番号だけ

利用者の名前や権限を、Cookieにそのまま入れることもできます。ただし、RFC 6265の8.4節は、サーバが番号だけをCookieに入れる使い方が一般的だと述べています。サーバは、その番号を鍵にして、自分の手元の表から利用者の情報を引きます。

冒頭で触れたセッションIDは、この番号のことです。以下では、番号と中身を対応させる表をセッション表と呼びます。ブラウザが持つのは番号だけなので、Cookieを見られても利用者の情報そのものは漏れません。RFC 6265は、この点を番号を使う利点に挙げています。

その代わり、番号を知った人は、その利用者になりすませます。この危険は、後のセッションハイジャックの節で説明します。持っているだけで使える点は、アプリに権限を渡すOAuthのアクセストークンも同じです。サーバを複数台並べると、表を持たないサーバにリクエストが届くことがあります。その場合は、ロードバランサで同じ利用者を同じサーバに送り続けます。

動かして確かめる:ログインから次のページを開くまで

利用者Aがログインし、次のページを開くまでを5段に分けました。段を選ぶと、流れるメッセージと、ブラウザとサーバが持つ値が変わります。通信はHTTPSとします。最後の段では、別の人が同じ番号を送ります。

ブラウザ → サーバ
POST /login HTTP/1.1
Host: example.com

id=user-a&password=(入力した値)
ブラウザが持つCookie
まだ無い
サーバのセッション表
まだ行が無い
利用者Aが、IDとパスワードを送ります。まだCookieを持っていないので、リクエストにCookieヘッダは付きません。

3段目と5段目で、サーバに届くリクエストは同じ形です。違うのは送り主だけで、サーバにはそれが見えません。

Cookieの種類:セッションCookieと有効期限付きのCookie

期限を書くかどうかで、残る長さが変わる

Set-CookieにExpiresもMax-Ageも書かないと、Cookieはブラウザが決めるセッションの終わりまでしか残りません。このCookieをセッションCookieと呼びます。MDNの説明では、セッションの終わりはブラウザを終了したときです。ただし、次の起動時にタブを復元する機能を使うと、セッションCookieも一緒に戻ります。

ExpiresかMax-Ageを書いたCookieは、ブラウザを閉じても期限まで残ります。Expiresは期限の日時で、Max-Ageは残りの秒数で書きます。両方あるときは、Max-Ageが優先です。期限は上限で、ブラウザは容量やプライバシーの理由で先に消すことがあります。

ファーストパーティとサードパーティ

開いているページのサイトが自分で発行したCookieは、ファーストパーティCookieです。ページの中に広告など別のサーバのコンテンツがあると、ブラウザはそのサーバにもリクエストを送ります。そのサーバが発行したCookieが、サードパーティCookieです。

RFC 6265の7.1節は、同じ第三者のコンテンツを置いた複数のサイトをまたいで、利用者を追跡できる点を挙げています。同じ節のとおり、サードパーティCookieの扱いはブラウザによって大きく違います。

Cookieの属性と、書かないときの動き

Set-Cookieの「;」の後ろに並ぶのが、属性です。属性は、ブラウザがCookieをどこへ、いつまで、どの通信で送るかを決めます。書かなかった属性には、次のような既定の動きがあります。

属性付けたとき書かないとき
Domainそのドメインと、サブドメインにも送る発行したホストにだけ送る
Pathそのパスと、その下のパスにだけ送るリクエストしたURLのパスの、最後の「/」より前を使う
Expires
Max-Age
その期限まで保存する。期限は上限で、先に消えることもあるブラウザが決めるセッションの終わりまで
SecureHTTPSなど安全な通信のときだけ送るHTTPでもHTTPSでも送る
HttpOnlyページのスクリプトから読めなくするスクリプトから読める
SameSite別のサイトから始まったリクエストに送るかを決めるブラウザによって違う

Domainは、書くと送り先が広がり、書かないほうが狭くなります。Pathを書かないときは、たとえば /shop/cart への応答で受け取ったCookieなら /shop になります。 /login のように「/」が1つだけのパスなら、/ になります。RFC 6265の4.1.2.4節は、Pathは同じホストの中でCookieを分離して守る手段にはならないとしています。

Secureは盗聴から値を守りますが、偽のCookieの差し込みは防げません。RFC 6265の4.1.2.5節は、経路上の攻撃者がHTTPの通信からSecure付きのCookieを上書きできるとしています。RFC 6265の改訂版の草案は、この上書きを止める決まりを足しました。それでも、HTTPの応答を偽れば、同じサイトあての別のCookieを差し込めると草案の8.6節は述べています。

HttpOnlyを付けたCookieも、リクエストには付いて送られます。読めなくなるのは、document.cookie などを使うスクリプトからだけです。

SameSiteは、RFC 6265の改訂版の草案で定める属性

SameSiteは、RFC 6265には無い属性です。RFC 6265を置き換える改訂版の草案が定めています。2026年10月28日の時点で、この草案はIETFの承認を終え、RFCとして発行されるのを待つ段階にあります。RFCの番号は、まだ付いていません。

草案によると、Strictは、同じサイトから始まったリクエストにだけCookieを送ります。Laxは、それに加えて、別のサイトのリンクから移ってきたときのように、ページ全体が切り替わる移動にも送ります。MDNによると、この移動はGETのような安全なメソッドに限られ、POSTは含みません。Noneは、別のサイトから始まったリクエストにも送ります。Noneを使うときは、Secureも付ける必要があります。

SameSiteを書かなかったときの扱いは、ブラウザによって違います。草案は、Laxと同じ扱いを既定にしています。MDNの互換性の表では、Chromeは80から、Edgeは86から、書かないCookieをLaxとして扱います。FirefoxとSafariは、既定ではLaxとして扱いません。

Chromeには例外もあります。作られてから2分以内のCookieなら、別のサイトからのページ全体のPOSTにも付けます。Chromiumの公式の説明は、この例外を一時的な措置としています。

SameSiteで止めていなければ、ブラウザは、別のサイトのフォームから送らされたリクエストにもCookieを付けます。この性質を悪用し、利用者が意図しない操作をサイトに送らせる攻撃が、クロスサイトリクエストフォージェリです。SameSiteは、この攻撃を防ぐ手段の1つです。ただし草案は、Laxだけでこの攻撃を完全には防げないとしています。攻撃の流れと、トークンなどほかの対策は、CSRFの記事にまとめました。

Cookieが盗まれると、セッションハイジャックが起きる

セッションIDを他人に知られると、その人は利用者になりすましてサイトを使えます。IPAの「安全なウェブサイトの作り方」は、この攻撃をセッションハイジャックと呼んでいます。上の図の5段目が、この状態です。

IPAは被害の例として、不正な送金、ウェブメールの盗み見、設定の書き換えを挙げています。RFC 6265の8.3節によると、Cookieの中身を暗号化しても、盗んだCookieを別のブラウザで使われることは防げません。

番号を知られる経路

  • 推測:番号が時刻などから単純な規則で作られていると、他人に当てられます。
  • 盗聴:HTTPのまま流れたCookieは、中間者攻撃の記事で説明したように経路上で読まれます。
  • スクリプトによる読み取り:XSSの記事で説明したように、埋め込まれたスクリプトにCookieを読まれます。
  • 固定化:攻撃者が用意した番号を利用者に使わせ、その番号のままログインさせます。

守り方

IPAの「安全なウェブサイトの作り方」は、セッションIDの扱いについて次の対策を挙げています。HttpOnlyは、同じ資料のXSSの節で、Cookieの漏えいに備える保険的な対策に挙げられています。

  • セッションIDを、推測されにくい乱数で作る
  • セッションIDを、URLの中に入れない。リンク先のサイトに、URLごと送られることがあるため
  • HTTPSで使うCookieに、Secure属性を付ける
  • ログインに成功したら新しいセッションを始め、古いセッションIDを無効にする
  • Cookieの有効期限を、必要以上に長くしない
  • HttpOnly属性を付け、スクリプトからCookieを読めなくする

練習問題(全6問)

Q1Cookieのやり取りとして正しいものは?
Q2セッションIDを使うサイトで、ログイン中の利用者の情報が置かれている場所は?
Q3Set-CookieにExpiresもMax-Ageも書かなかったCookieは、いつまで残る?
Q4Domain属性を書かずに、www.example.com が発行したCookieは、どこへ送られる?
Q5Cookieに付けるHttpOnly属性の効果として正しいものは?
Q6セッションIDの固定化を防ぐ対策として、IPAが挙げているものは?

選んでから「採点する」を押すと、解説つきで答え合わせができます。

参考にした資料

関連記事

おすすめの本 PR

ネットワークを初めて学ぶ人向けの入門書です。

目的別の本の選び方を見る

ネットワークの記事を探す