【入門編】Web Storage (LocalStorage/SessionStorage)のXSSによる窃取リスク – アプリケーションセキュリティ & 安全な開発防御ガイド

あなたのWebアプリ、玄関の鍵を「透明な箱」に入れていませんか?:LocalStorageとXSSの危険な関係

こんにちは。日夜、デジタル世界の「鍵」を守る仕事をしているセキュリティエンジニアです。

今日は、多くの開発者がついついやってしまいがちな「認証情報の保存場所」という、いわば「家の鍵の置き場所」の話をしましょう。

「ログイン後のトークン(秘密の合言葉)を、どこに保存するのが一番安全か?」

この問いに対して、安易に localStorage を選んでいないでしょうか? もしそうなら、あなたのWebアプリケーションは、泥棒に「鍵はここですよ」とわざわざ看板を出しているようなものかもしれません。なぜそう言えるのか、一緒に紐解いていきましょう。

—

1. LocalStorageは「透明な金庫」である

まず、localStorage という場所をイメージしてください。これはブラウザが持っている「便利な物置」です。JavaScriptから簡単に読み書きできるため、多くの開発者が「ここにトークンを入れておけば、画面を閉じてもログイン状態を維持できるし便利だよね!」と考えます。

しかし、セキュリティの視点から見ると、localStorage は「中身が透けて見える金庫」なんです。

なぜ「透けて見える」のか?

JavaScriptで動くプログラムなら、誰でも(たとえそれが悪意ある攻撃者が仕込んだスクリプトであっても)localStorage.getItem('token') と書くだけで、中身を丸裸にできてしまうからです。

—

2. XSSという「忍び込み」の手口

ここで登場するのが、セキュリティの定番攻撃「XSS(クロスサイトスクリプティング)」です。

例えば、掲示板のコメント欄に なんて書き込まれていたとします。

もしあなたのサイトがこの入力をそのまま画面に表示していたらどうなるでしょう?
あなたのサイトを訪れたユーザーのブラウザ上で、その「泥棒スクリプト」が勝手に実行されます。結果、ユーザーのログイン用トークンは、攻撃者のサーバーへそのまま転送されてしまうのです。

これが「XSSによる窃取」のメカニズムです。鍵(トークン)を盗まれた泥棒は、ユーザーになりすまして自由にアプリを操作できてしまいます。

—

3. 防御の鉄則:HttpOnly属性という「最強のガードマン」

では、どうすればいいのでしょうか? 答えは、「JavaScriptから触らせない」ことです。

ここで活躍するのが「Cookie」です。ただし、ただのCookieではありません。HttpOnly 属性という特別な「ガードマン」を付けたCookieを使います。

HttpOnly Cookieの仕組み

サーバーからブラウザに送る際、以下のような指示を出します。

Set-Cookie: session_token=abc123xyz; HttpOnly; Secure; SameSite=Strict

  • HttpOnly: JavaScriptから「このCookieを読み取らせない」という設定です。これで、万が一XSSが起きてスクリプトが動いても、攻撃者はトークンを盗むことができません。
  • Secure: 通信を暗号化(HTTPS)しない限り送信しません。
  • SameSite=Strict: 他のサイトからの不正なリクエストをブロックします。

これらは、いわば「指紋認証付きの頑丈な鍵」です。たとえ泥棒が家の中に侵入(XSS)しても、鍵本体には指一本触れさせない仕組みです。

—

4. もしLocalStorageをどうしても使うなら?

システムの都合上、どうしても localStorage しか使えない…というケースもあるかもしれません。その場合は、「鍵を暗号化する」という選択肢が残されています。

ただし、注意してください。LocalStorageに保存したものを暗号化するための「鍵」自体をどこに持つのか?という問題が発生します。結局、その「鍵」を盗まれると元も子もありません。

ですので、基本方針としては以下の順序で検討してください。

1. 第一候補: HttpOnly 属性付きのCookieを使用する。(これが現代のWeb開発のスタンダードです!)
2. 第二候補(どうしてもJSで管理する場合): トークンの有効期限を極限まで短くし、万が一盗まれても被害を最小限に抑える(短命トークン)。

—

最後に:セキュリティは「完璧」を目指すものではない

セキュリティの世界には「絶対」はありません。しかし、「攻撃の手間を100倍にする」ことは可能です。

XSSを防ぐために、入力値のチェックや出力時のエスケープ(HTMLタグを無効化する処理)を行うことはもちろん重要です。ですが、「もし防ぎきれなかったら?」を常に想定する「多層防御」の考え方が、あなたのアプリを守る最後の砦になります。

今日からあなたのコードを見直して、大事な「鍵」を「透明な箱」から「ガードマン付きの金庫」へ移してみませんか?

一歩ずつ、着実に対策していきましょう。応援しています!

コメント

タイトルとURLをコピーしました