セッション管理とセキュアなCookie設定
HttpOnly、Secure、SameSite属性の役割と設定方法。
cookie🍪とは何か?
Cookieとは、ウェブサイトを訪問したユーザーの情報を一時的または永続的に保存しておくために、ウェブサーバーがユーザーのブラウザに発行し、保存させる小さなテキストデータのことです。
Cookieに保存される情報には、主に以下のようなものがあります。
セッション情報: ログイン状態を維持するためのID(セッションID)。
ユーザー設定: サイトの表示言語、テーマ(ダークモード/ライトモード)、地域設定など。
トラッキング情報: 過去の訪問履歴、カートに入れた商品、広告の表示履歴など。
どのような仕組み?(Cookieの動作原理)
Cookieの仕組みは、Webサーバー、ブラウザ(クライアント)、そしてHTTPプロトコルが連携して動作します。
1.発行
サーバーは、ユーザーを識別するためのデータ(例:セッションID)を生成します。
このデータを含む Set-Cookie という名前のHTTPレスポンスヘッダーを生成し、ユーザーのブラウザへ送信します。
2.保存
ブラウザはサーバーからのレスポンスヘッダーを受け取ると、その指示に従い、指定された名前、値、有効期限などの属性とともに、Cookieをユーザーのコンピューター(ローカル)にテキストファイルとして保存します。
3.送信
ユーザーが同じウェブサイトの別のページにアクセスしたり、再度訪問したりする際、ブラウザは保存されているCookieを自動で検出し、HTTPリクエストヘッダーの Cookie フィールドに含めてサーバーに送り返します。
4.利用
サーバーはブラウザから送られてきたCookie(例:session_id=12345)を読み取り、このIDを基にデータベースを照会することで、「このユーザーはログイン済みである」「このユーザーの設定言語は日本語である」といった情報を確認し、適切なコンテンツを返します。
この繰り返しによって、ウェブサイトはユーザーの「状態」を記憶し、セッションを維持することを実現します。
cookieの属性それぞれの機能、対応できる攻撃
Secure属性
HTTPS通信時のみ Cookieをサーバーに送信するようブラウザに指示する属性です。
暗号化されていないHTTP通信ではCookieは送信されません。
対策できる攻撃
Cookieの盗聴(中間者攻撃):
Secure属性がない場合、HTTP通信でCookieが平文(暗号化されていない状態)で流れる可能性があり、通信経路上の第三者に盗聴されるリスクがあります。
Secure属性を設定することで、盗聴リスクの低いHTTPS通信に限定され、Cookieが暗号化されたチャネルでのみやり取りされるため、セッションハイジャックなどの攻撃を防ぐのに役立ちます。
ウェブサイト全体でHTTPS通信を強制する必要があります。HTTP通信しか使っていない場合は意味がありません。
HttpOnly属性
JavaScriptからのCookieへのアクセスを制限する属性です。具体的には、document.cookieなどを使ったCookieの読み書き・操作ができなくなります。
対策できる攻撃 クロスサイト・スクリプティング(XSS)によりCookie窃取
クロスサイト・スクリプティング(XSS) によるCookie窃取
・XSS攻撃により悪意のあるJavaScriptがWebページに埋め込まれた場合、このスクリプトがdocument.cookieを使ってユーザーのセッションIDなどの重要なCookie情報を盗み出し、攻撃者のサーバーに送信することを試みます。
・HttpOnly属性を設定することで、JavaScriptからのCookieアクセスがブロックされ、XSS攻撃によるセッションCookieの盗難を防ぐことができます。
※HttpOnly属性はXSS脆弱性そのものを解消するものではなく、XSSが引き起こす被害を軽減するための「緩和策」
なぜHttpOnlyはXSSを防げないのか?
HttpOnly属性は、Cookieの利用方法に制限をかけるものであり、Webページへのスクリプトの挿入自体を防ぐ機能はないためです。
image
具体的な流れ
攻撃者はWebサイトのフォームやURLパラメータなどの脆弱な入力欄を利用し、 のような悪意のあるコードを挿入します。
サーバーはこのコードを含むページをユーザーのブラウザに返します。
ブラウザは、この悪意のあるコードを信頼できるWebサイトのコードの一部として実行してしまいます。
HttpOnly が効くのはここから:実行された悪意のあるJavaScriptが、セッションCookieを盗もうとして document.cookie にアクセスしようとしたとき、HttpOnly 属性が設定されているためアクセスが拒否されます。
つまり、HttpOnly は「XSSという火災が発生するのを防ぐ」のではなく、「火災が発生しても、重要な金庫(Cookie)を燃やさないように守る」役割を果たしているのです。
HttpOnly は「層 2」として不可欠ですが、「層 1」の対策を怠ると、Cookie以外の情報(例:フォームに入力されたパスワードなど)が盗まれたり、ページの内容が改ざんされたりする被害は防げないため注意が必要だということ。
セキュリティは多層防御(Defense in Depth) が原則です。
防御層1: 根本的な対策 出力時のエスケープ、入力時のサニタイズ 攻撃コードの挿入・実行を未然に防ぐ。
防御層 2: 実行時の緩和策 HttpOnly 属性 XSSが成功してもセッションCookieの盗難を防ぐ。
防御層 3: 制御の緩和策 CSP(Content Security Policy) 実行されるスクリプトのソースや種類を制限する。
SameSite属性
サイトをまたがるリクエスト(クロスサイトリクエスト)が発生した際に、ブラウザがCookieをサーバーに同送するかどうかを制御する属性です。主にファーストパーティCookie(アクセス中のサイトと同一ドメインのCookie)の扱いに影響します。
対策できる攻撃 クロスサイトリクエストフォージェリ(CSRF)
クロスサイトリクエストフォージェリ(CSRF):
・攻撃者が用意したサイトから、ユーザーがログインしている正規のサイトへ、ユーザーの意図しないリクエストを送りつける攻撃です。通常、このリクエストには認証情報(Cookie)が自動で付与されてしまうため、正規サイトはユーザーからの正当なリクエストと誤認してしまいます。
・SameSite属性を設定することで、他サイトからのリクエスト時にCookieの送信を制限し、CSRF攻撃を効果的に防ぐことができます。
image
SameSiteには、以下の3種類があります。
1.Strict(ストリクト):最も厳しい認証
開発上の挙動: 自分のサイト(mysite.com)のCookieは、mysite.com内でのリクエストでのみ送信されます。
【具体的な影響】 外部サイト(例:SNSやメール)にあるリンクからmysite.comのページに遷移しようとしても、ブラウザはセッションCookieを送信しません。
結果: ユーザーはリンクをクリックしてサイトに戻るたびに、再ログインが必要になります。
採用シーン: 銀行の取引画面や管理画面など、セキュリティが極めて重要で、再ログインの手間を許容できる場面。
2.Lax(ラックス):デフォルトのバランス
現在、ほとんどの主要ブラウザでデフォルトとして採用されています。
開発上の挙動: 外部サイトからのリクエストであっても、画面全体を遷移させる GET リクエスト(例:リンクのクリック) の場合に限り、Cookieを送信します。
具体的な影響
許可: メールやSNSのリンクをクリックしてサイトに戻っても、ログイン状態は維持されます。
拒否: POSTフォーム送信、非同期通信(JavaScriptのfetchなど)、タグの埋め込みなど、裏側で行われる操作ではCookieは送信されません。
結果: CSRF攻撃の主な手法である不正なPOSTリクエストを防ぎつつ、ユーザーの利便性を保つため、一般的なWebサービスで推奨される設定です。
3.None(なし): 外部連携のための許可
開発上の挙動: 外部サイトからのすべてのクロスサイトリクエストでCookieが送信されます(GET、POST、非同期通信、画像読み込みなど、すべてOK)。
【具体的な影響】
用途: 自分のサイトのコンテンツや機能(例:コメントウィジェット、トラッキングピクセル)を他社のサイトに埋め込みたい(サードパーティCookieとして使いたい)場合に必要です。
必須要件: Secure属性(HTTPS必須) を同時に設定しなければ、この設定は無効化されます。セキュリティリスクを負う代わりに、通信の安全性を確保する義務が生じます。
//Cookieのセキュリティ設定
http.SetCookie(w, &http.Cookie{
Name: "session",
Value: "超長いランダム文字列123456789abcdef...", // セッションIDの値
HttpOnly: true, // → XSSによるCookie窃取対策
Secure: true, // → 盗聴によるCookie漏洩対策
SameSite: http.SameSiteLaxMode, // → CSRF攻撃対策
})
この設定により、セッションCookieの安全性が多角的に高められます。
実装の依存先は、バックエンド?という点は、半分正しく、半分誤解があります。
結論から言うと、Set-Cookieヘッダーの送信(Cookieの設定)は、完全にバックエンド(Webサーバー/アプリケーション)の処理に依存します。しかし、そのCookieの利用や解釈、制限の適用は、ブラウザ(クライアントサイド) の挙動に依存します。
※ クリックジャッキングとは別物である。
・個人的にCSRFの内容を深ぼっていくと、似たような体験があったため補足で「違い」をまとめました。
クリックジャッキングと、クロスサイトリクエストフォージェリ(CSRF)の違い
セキュリティ上の脅威であるという点は共通していますが、目的、手法、そして主な防御策が異なる「別物」
「サイトが二重で開かれる」「別のサイトに飛ばされる」という現象は、攻撃者がアフィリエイト報酬を不正に得るために、ユーザーを意図せず特定のアフィリエイトリンクを経由させる目的で利用されていました。
クリックジャッキングという攻撃手法は、現在も有効な脅威であり、「NGになった(技術的に実行不可能になった)」わけではないようです。
まとめ
| 項目 | クロスサイトリクエストフォージェリ(CSRF) | クリックジャッキング |
|---|---|---|
| 主な目的 | ユーザーの状態変更(送金、パスワード変更、退会など)を実行させること。 | ユーザーに意図しないクリックを行わせること。 |
| 悪用観点 | ユーザーが持つ認証情報(Cookie) が、他サイトからのリクエストに自動で付与されるブラウザの挙動。 | サイトの上に透明なレイヤー( |
| 攻撃のターゲット | 認証が必要な重要な機能(データの更新・変更) を持つサーバー側のエンドポイント。 | ユーザーインターフェース(UI)上のクリック可能な要素(ボタン、リンクなど) |
| 防御策 | 1. CSRFトークンの導入。 2. SameSite Cookie属性(Lax/Strict)の設定。 | 1. CSP frame-ancestors ヘッダーの設定。 2. X-Frame-Options (XFO) ヘッダーの設定。 |
| 攻撃の例 | ログイン状態のユーザーに、攻撃サイトから「送金リクエスト」を自動送信させる。 | ユーザーがサイトの「再生ボタン」を押したつもりが、裏の透明なアフィリエイトリンクをクリックしていた。 |