本文へスキップ
totonoe.tech

セキュリティを整える

専門

XSSのしくみを整える。

= 入力をそのまま画面に出すと、なぜ危ないのかを安全に体感

XSS が初めての方は、先に そもそも XSS とは・どんな場面で出会うか をどうぞ。

アニメで見る — XSS(格納型)のしくみ 開くと1ステップずつ動きます
🦹

攻撃者

悪意ある入力者

🧨 <script>…</script>
🖥️

サービス

サーバ / DB

🗄️ そのまま保存
🖥️

サービス

サーバ / DB

🗄️ 罠入りデータ
🙍

別の利用者

何も知らない人

🌐 ページ表示
💥 コードが実行
🍪 Cookie等が盗まれる
🖥️

サービス

出力時エスケープ

🗄️ 罠入りデータ
🔤 &lt;script&gt; に変換
🙂

別の利用者

安全に閲覧

📄 ただの文字として表示

STEP 1

※ イメージ図です。下の体験デモでは、scriptは安全に無効化された状態で「解釈の様子」だけを見られます。

SAFE DEMO — 入力をHTMLに入れると何が起きる? scriptは無効化・送信ゼロ

🔒 このデモは安全です。 「危険な実装」パネルは、入力を sandbox 属性つきの隔離された枠 (allow-scripts を付けていません)に表示します。 だから <script> や onerror は ブラウザに無効化され、実行されません。「マークアップがどう解釈されるか」だけを安全に観察できます。

例:

❌ 危険な実装(innerHTML 相当)

入力を“そのまま”HTMLとして解釈させる

⚠ 本番にsandboxが無ければ、ここでコードが実行されます。 このデモでは allow-scripts を付けていないため、scriptやonerrorは 無効化され実行されません(=マークアップの解釈だけが見えます)。

✅ 安全な実装(エスケープ / textContent)

入力を“ただの文字”として表示する

エスケープ後のHTML(このまま埋めても安全)

⚖ これは攻撃の練習ではなく、開発者が「なぜ入力を信用してはいけないか」を学ぶための防御教育です。 実在のサイトや他人のサービスで、許可なくこうした入力を試す行為は不正アクセス禁止法などに触れるおそれがあります。 学習はこのページや、自分で用意した検証環境の中だけで行ってください。

やってはいけない

入力を信用してHTMLに入れる

  • ✕element.innerHTML = userInput で、入力を生のHTMLとして描画。
  • ✕テンプレートに値を“素通し”で埋め込む(自動エスケープを切る)。
  • ✕URLや属性を検証せず href や on* に流す。

こうする

出力する瞬間に無害化する

  • ✓element.textContent = userInput で、必ず「文字」として扱う。
  • ✓HTMLに出すなら出力時エスケープ(< → &lt;)。
  • ✓フレームワークの自動エスケープを切らない。

そもそも XSS とは

他人が書いた文字が、閲覧者の画面で「プログラム」として動いてしまう弱点。

XSSは クロスサイトスクリプティング(Cross-Site Scripting) の略です。サイトが、外から入力された文字を安全に処理しないまま画面に出してしまうと、その文字に紛れたプログラムが、閲覧した人のブラウザで動いてしまいます。略称が X なのは、CSS(スタイルシート)と区別するためです。

たとえるなら、掲示板に貼られた紙の中に「この紙を読んだ人は、財布を出してください」と書かれていて、読んだ人が従ってしまうようなものです。被害に遭うのは、サイトを作った人ではなく、そのサイトを見に来た人です。

どこで・どんな場面で出会うか

  • 問い合わせフォームや掲示板、コメント欄

    訪問者が書いた文字を、あとで画面に表示するところです。表示のしかたを誤ると、ここが入口になります。

  • 検索結果の画面

    「◯◯の検索結果」のように、入力された語をそのまま画面に出す作りは、よくあります。出し方に注意が要る場所です。

  • 会員のプロフィールやユーザー名の表示

    本人が自由に入力できる名前や自己紹介は、ほかの会員の画面にも表示されます。

  • 管理画面で、受け取った内容を確認するとき

    訪問者から届いた入力を、管理者が見る画面です。管理者の権限が狙われると、影響が大きくなります。

  • CMS のテーマやプラグインを入れるとき

    WordPress などの追加部品に、出力の処理が甘いものがあると、サイト全体の弱点になります。更新が止まった部品は特に注意が必要です。

知らないと何が困るか

  • 閲覧者のログイン状態が奪われるおそれがある。訪問者のブラウザで動くので、その人としての操作や情報が、第三者に渡る可能性があります。
  • サイトの画面が書き換えられ、偽の入力欄で利用者がだまされる。見た目は本物のサイトなので、見分けがつきません。
  • 信用と対応の負担が大きい。被害が出ると、お知らせ・調査・再発防止まで、運営側の仕事が一気に増えます。

上のデモで、入力した文字が「文字のまま」表示される場合と、そうでない場合の違いを見比べてみてください。

XSSを防ぐ5つの守り

「入力は信用しない、出力で無害化する」が鉄則。

  1. 1

    出力時エスケープ

    HTMLに値を埋める瞬間に < > & " ' を実体参照へ変換。タグとして解釈されなくなり、ただの文字になります。埋める場所(HTML本文・属性・URL・JS・CSS)ごとに正しいエスケープを使うのが要点。

  2. 2

    textContent / DOM API を使う

    innerHTML ではなく textContent や setAttribute で値を入れれば、ブラウザが自動で「文字」として扱い、コードとして実行しません。そもそもHTMLを文字列連結で組み立てないのが安全。

  3. 3

    CSP(Content-Security-Policy)

    「どこのスクリプトを実行してよいか」をHTTPヘッダで宣言する保険。script-src 'self' などで、万一エスケープ漏れがあってもインラインスクリプトの実行をブラウザ側で止められます(多層防御)。

  4. 4

    HttpOnly Cookie

    セッションCookieに HttpOnly を付けると、JavaScriptから document.cookie で読めなくなります。仮にXSSが起きても、セッション乗っ取りの被害を小さくできます(Secure / SameSite も併用)。

  5. 5

    フレームワークの自動エスケープ

    React・Vue・Svelte・Astro などは、値の埋め込みを既定でエスケープします。だからこそ dangerouslySetInnerHTML や v-html のような「自動エスケープを切る入口」を安易に使わないことが大切。生HTMLが必要なときは DOMPurify などのサニタイザを通します。

🔒 このデモはすべてあなたのブラウザの中(JavaScript)で完結します。入力はサーバに送られません(送信ゼロ)。外部CDN・APIも使いません。「危険な実装」の表示は sandbox 付き iframe で隔離され、script は実行されません。

このツールについて

『入力をそのまま画面に出すと、なぜ危ないのか』——XSS(クロスサイトスクリプティング)を、安全な環境で自分の目で確かめるための防御教育ツール。危険な実装と、エスケープした安全な実装を並べて対比します。scriptは必ず無効化されるので、実際には何も実行されません。送信ゼロ・登録不要。

入力を信用してHTMLに入れると何が起きるかを、scriptが無効化された安全な環境で対比体験。防ぎ方も学べる。

🔰 かんたんに言うと

サイトに入力した文字が「命令」として実行されてしまう不具合(XSS)を、安全な箱の中で体験します。

主な機能

  • 危険な実装と安全な実装を2パネルで横並び対比
  • 入力はsandbox付きiframeに隔離(allow-scripts無し)でscriptは絶対に実行されない
  • エスケープ後の安全なHTMLをその場で確認・コピー
  • 格納型XSS(入力→保存→他人の画面で発火)をStepDiagramで図解
  • 出力時エスケープ/textContent/CSP/HttpOnly Cookieの防御を解説
  • 送信ゼロ・防御教育(攻撃の練習ではない)

よくある質問

Q. このデモを使うと自分の環境にウイルスが入りませんか?

A. 入りません。入力は allow-scripts を付けない sandbox iframe に隔離され、scriptは実行されません。すべてブラウザ内で完結し送信もしません。

Q. なぜ「危険な実装」パネルでもalert等が出ないのですか?

A. sandbox属性(allow-scripts無し)でスクリプト実行がブラウザに禁じられているためです。本番でsandboxが無ければ、同じ入力でコードが実行されてしまいます。

Q. XSS(クロスサイトスクリプティング)とは何ですか?

A. 攻撃者の入力が無害化されないままHTMLに混ざり、別の利用者のブラウザで意図しないコードが実行される脆弱性です。

Q. 格納型・反射型・DOM型の違いは?

A. 格納型はサーバに保存され他者の画面で発火、反射型はリクエストに含めた入力がその場で返り発火、DOM型はクライアントのJSが入力を危険に扱うことで発火します。

Q. 一番確実な防ぎ方は?

A. 出力時にエスケープし、innerHTMLでなくtextContent/DOM APIで値を入れること。フレームワークの自動エスケープを切らないことが基本です。CSPやHttpOnly Cookieは被害を抑える保険(多層防御)です。

Q. 学んだ手法を実在のサイトで試してよいですか?

A. いけません。許可のない検証は不正アクセス禁止法等に触れるおそれがあります。学習はこのページや自分の検証環境内に限ってください。

入力値はURLの「#」以降に入るためサーバーには送信されません。リンクを開くと同じ状態を復元します。

続けて整える

totonoe.tech を運営する株式会社Koinobori は、法人向けの研修サービス「NOBORIBA®」も運営しています。 ここで手を動かした内容を、講師から教わる形の研修です。このページの道具は無料のまま、登録もいりません。

運営サイト

私たちが運営するサイト