0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【セキュリティ】 Cookie Tampering(クッキー改竄)─危険と実装上の対処

Last updated at Posted at 2025-10-01

はじめに

クッキーはクライアント側に保存されるため改竄のリスクがあります。アプリがクッキーの中身をそのまま信頼して認可やログイン判定に使うと、ユーザが自分で値を書き換えて権限を偽装したり、他者のデータにアクセスできてしまいます。ここでは「何が危ないか」「現場で今すぐできる対策」「実装例(防御側)」を端的にまとめます。


1. 概要 — なぜ問題になるか

  • クッキーはユーザが自由に編集可能(ブラウザの開発者ツールやスクリプトで変更可)
  • 平文で admin=true{"id":1,"admin":false} のような情報を保存し、サーバがそれを信頼していると権限昇格なりすましが発生する
  • 攻撃者は改竄で「ログイン済み」「管理者」フラグを作り、保護された機能へアクセスする可能性がある

2. 危険な実装パターン(よくあるアンチパターン)

  • Set-Cookie: admin=true のように 権限フラグを平文で保存してそのまま判定する
  • 平文 JSON を session cookie に入れてそのまま json_decode() して権限判定する
  • 署名や検証をせずに JWT を受け入れてしまう(署名を検証していない、アルゴリズムの落とし穴)
  • Cookie に HttpOnly, Secure, SameSite を設定していない(XSS/CSRF リスク増大)

3. 安全な基本方針(原則)

  1. サーバ側でセッション管理を行う(セッションIDのみをクッキーに置き、権限等の実データはサーバ側に保管)。
  2. クッキーに重要な情報を置かない。どうしても置く場合は 署名(HMAC)暗号化 を行い、必ずサーバ側で検証する。
  3. Cookie 属性を正しく設定するHttpOnly, Secure, SameSite
  4. トークンは期限付きかつ一意にし、使い回しを禁止する。
  5. 既製のセッションライブラリ/フレームワークを使う。手作りでの実装はミスの原因になりやすい。

4. 実装例(防御側・PHP)

A. サーバ管理セッション(推奨)

// セッションはサーバ側(例:PHPのセッション)で権限を管理する
session_start();
// ログイン時(例)
$_SESSION['user_id'] = $userId;
$_SESSION['is_admin'] = $isAdmin; // でも判定は常にサーバ側で行う(DB参照も含める)
// 各リクエストで
if (!isset($_SESSION['user_id'])) {
    http_response_code(401);
    exit('Please login');
}
if (!isAdmin($_SESSION['user_id'])) { // DBチェックで確実に検証
    http_response_code(403);
    exit('Forbidden');
}
  • ポイント:クッキーは セッションIDのみ を保持し、権限等はサーバのセッションストア(DB/Redis)で管理する。

B. 署名付きクッキーの簡易例(必要な場合のみ)

// set signed cookie
function set_signed_cookie($name, $value, $secret, $expire=3600) {
    $payload = base64_encode(json_encode(['v'=>$value, 'ts'=>time()]));
    $sig = hash_hmac('sha256', $payload, $secret);
    $cookie = $payload . '.' . $sig;
    setcookie($name, $cookie, [
        'expires' => time() + $expire,
        'path' => '/',
        'secure' => true,
        'httponly' => true,
        'samesite' => 'Lax'
    ]);
}

// verify signed cookie
function verify_signed_cookie($cookie, $secret) {
    if (strpos($cookie, '.') === false) return false;
    list($payload, $sig) = explode('.', $cookie, 2);
    $expected = hash_hmac('sha256', $payload, $secret);
    if (!hash_equals($expected, $sig)) return false;
    $data = json_decode(base64_decode($payload), true);
    if (!$data) return false;
    // optional: check ts for expiry/age
    return $data['v'];
}
  • 注意点:これも自前実装は落とし穴が多いため、可能なら信頼できるライブラリを使う。hash_equals による定時比較でタイミング攻撃を防ぐ。payload 部分は改竄されても署名で検出できる。

C. JWT を使う場合の注意

  • 必ず 署名検証 を行う(公開鍵方式なら RS256 等を利用)
  • alg フィールドの改変や none アルゴリズム脆弱性に注意
  • 有効期限 (exp) を設定し、リフレッシュ運用を慎重に
  • JWT に重要な権限フラグを入れる場合、受信時に DB と突合する(可能なら権限は DB 参照)

5. Cookie 属性(必須)

  • HttpOnly:JavaScript から読めないようにする(XSS被害を軽減)
  • Secure:HTTPS のみ送信
  • SameSite:CSRF 緩和に LaxStrict を設定
  • 例:Set-Cookie: session=...; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600

6. 検出・監視(運用)

  • コードスキャン:リポジトリ内で Set-Cookieadmin=true"admin": など平文で権限を扱う文字列をgrepで検出

    git grep -n "admin=true" || true
    git grep -n "setcookie(" || true
    
  • ログ突合:受信したクッキーの内容(ハッシュや署名の有無)とサーバログを照合し、異常な値が来ていないか監視

  • WAF / IDS ルール:典型的な改竄パターン(admin=true のようなリクエストヘッダ・クッキー)を検知してアラート

  • セッション異常検知:同一セッションIDを複数IPで利用している、短時間で権限変更要求が頻発するなどはアラート


7. テスト(自動化でやること)

  • ユニット:署名付きクッキーの署名検証ロジックを検証(改竄を検出すること)
  • 統合:ログイン→セッションIDの振舞い、権限がDB側で変わった場合の挙動(古いクッキーで昇格できない)
  • 脆弱性スキャン:サードパーティライブラリやJWT実装の設定チェック
  • CIチェックgit grep ベースで「平文で権限を保存しているコード」を検出してPRをブロック(既に提案済みの方式を流用可)

8. すぐやるべき優先タスク(短期)

  1. すべての Set-Cookie を検索し、平文の権限フラグがある箇所を即時修正
  2. Cookie に HttpOnly / Secure / SameSite を付与
  3. 重要情報(権限・認可情報)は 必ずサーバ側で保持
  4. セッションライブラリやフレームワークの安全設定を確認(例:PHPの session.cookie_httponly = 1 等)
  5. CI に grep チェックを入れて継続的に検出する

9. チェックリスト(レビュー用)

  • Cookie に重要な権限情報(admin, role 等)を平文で置いていないか?
  • セッションID以外で認可判定していないか?(サーバ側データで判定)
  • Cookie に HttpOnly / Secure / SameSite を設定しているか?
  • 署名付きクッキーや JWT の署名検証を正しく実装しているか?
  • 既製のセッション管理ライブラリを使っているか(手作り実装を避ける)?
  • CI に「危険なクッキー実装」を検出するルールがあるか?

まとめ

「クッキーは信頼しない。セッションで管理し、署名/属性で守る」

クッキー改竄はシンプルなミスから生じますが、適切な設計(サーバ管理のセッション、署名、Cookie属性)と自動検出(コードスキャン/CI)でかなり防げます。まずはリポジトリ内の setcookie / admin / 平文JSON を grep して、危険箇所を洗い出しましょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?