XSS(クロスサイトスクリプティング)とは、Webページへ意図しないスクリプトなどが入り込み、閲覧者のブラウザ上で実行される脆弱性・攻撃の総称です。
お問い合わせ内容、コメント、検索キーワード、URLパラメータなど、外部から受け取った値を安全に処理せずHTMLへ出力すると、文字列として表示すべき内容がブラウザにコードとして解釈される可能性があります。
WordPress運営者にとって重要なのは、攻撃方法を覚えることではありません。 WordPress本体・テーマ・プラグインを更新し、開発側では入力検証・サニタイズ・出力時エスケープを適切に行い、WAFやCSPを追加防御として使うことが基本です。
30秒でわかる結論
30秒でわかる結論
- XSSは、意図しないスクリプト等が閲覧者のブラウザ上で実行される脆弱性・攻撃
- 原因は、信頼できない入力を安全に処理せずHTML・属性・JavaScript等へ出力すること
- 代表的にStored XSS、Reflected XSS、DOM-based XSSがある
- 入力値を消すだけではなく、出力する場所に合ったエスケープが重要
- HTMLを許可する必要がある場合は、許可要素を限定したサニタイズを使う
- WordPressではesc_html()、esc_attr()、esc_url()、wp_kses()などを用途に応じて使う
- WAFやCSPは追加防御であり、一般利用者はWordPress・テーマ・プラグインの更新と不要なものの削除を最優先する
XSSとは?
XSSは「Cross-Site Scripting」の略です。 Webアプリケーションが受け取ったデータを安全に処理せずページへ出力した結果、ブラウザがその内容を単なる文字列ではなくスクリプトやHTMLとして解釈してしまうことで発生します。
外部入力 → 安全な処理なし → ページへ出力 → ブラウザがコードとして解釈
OWASPでは、XSSによってアカウントのなりすまし、利用者行動の観察、外部コンテンツの読み込み、機密情報の窃取などにつながる可能性があると説明しています。
XSSは「サーバーへ侵入する攻撃」とは限らない
XSSの中心は、被害者のブラウザ上で不正な処理を実行させることです。サーバーOSへの直接侵入とは仕組みが異なります。
なぜ「クロスサイト」と呼ばれる?
名称は歴史的な経緯から残っています。 OWASPも、現在のXSSは必ずしも「別サイトをまたぐ」攻撃だけを意味するわけではなく、Webページへ不正なコンテンツを注入する広い概念として使われていると説明しています。
初心者は名称より仕組みを見る
「外部から受け取った値が、閲覧者のブラウザで意図しないコードとして実行される」と理解すれば十分です。
XSSが起きる基本的な仕組み
通常、フォームやURLから受け取った値は「データ」として扱う必要があります。 ところが、出力先に合った安全処理をせずHTMLへ埋め込むと、ブラウザがタグやスクリプトとして解釈することがあります。
重要なのは、「入力された時点」だけでなく「どこへ出力するか」に応じて防御することです。 HTML本文、HTML属性、URL、JavaScriptでは必要な処理が異なります。
XSSで狙われる入力箇所
確認対象になりやすい場所
- お問い合わせフォーム
- コメント欄
- サイト内検索
- プロフィール入力
- URLパラメータ
- 投稿・レビュー機能
- 管理画面の設定値
- 外部APIから取得したデータ
「ユーザー入力」だけを警戒すればよいわけではありません。 WordPress公式も、ユーザー、外部API、データベースなど信頼できない可能性のあるデータを検証し、出力時にエスケープする考え方を示しています。
Stored XSSとは?
Stored XSSは、悪意ある入力がデータベースなどへ保存され、その後ページを表示した利用者のブラウザで実行されるタイプです。 「Persistent XSS」と呼ばれることもあります。
仕組みの例
投稿・コメントなどへ危険な内容が入力される
↓
データベースへ保存される
↓
別の利用者がページを表示
↓
安全処理が不十分だとブラウザで実行される
保存されるため影響が継続することがある
対象データが残っている間、複数の利用者へ影響する可能性があります。
Reflected XSSとは?
Reflected XSSは、リクエストで受け取った値をサーバーがそのままページへ反映し、そのレスポンス内で危険な内容が実行されるタイプです。
仕組み
URL・フォーム等から値を送信
↓
サーバーが値をレスポンスへ反映
↓
出力処理が不十分だとブラウザがコードとして解釈
Stored XSSとの違いは、危険な値がサーバーへ永続保存されることを前提としない点です。
DOM-based XSSとは?
DOM-based XSSは、主にブラウザ側のJavaScriptが信頼できない値を危険な方法でDOMへ書き込むことで発生します。
たとえば、URLなどから取得した値を安全に処理せず、HTMLとして解釈するAPIへ渡すと問題になる可能性があります。
サーバー側だけ確認しても足りない
DOM-based XSSはブラウザ内のJavaScript処理だけで成立する場合があります。フロントエンドコードも確認が必要です。
3種類の違い
| 種類 | 主な特徴 |
|---|---|
| Stored XSS | 危険な入力が保存され、後から表示時に実行 |
| Reflected XSS | リクエスト値がレスポンスへ反映されて実行 |
| DOM-based XSS | ブラウザ側JavaScriptのDOM操作で発生 |
実際の脆弱性では、これらの分類が重なるように見える場合もあります。 初心者は「保存型・反射型・ブラウザ側処理型」という違いを押さえれば十分です。
XSSで起こり得る被害
代表的な影響
- 利用者になりすました操作
- ページ内容の書き換え
- 偽フォームの表示
- 外部サイトへの誘導
- 利用者情報の不正取得
- 管理者権限での意図しない操作
被害範囲は、脆弱性が存在するページ、利用者の権限、Cookieの設定、CSPなど追加防御によって変わります。
XSSとSQLインジェクションの違い
| 項目 | XSS | SQLインジェクション |
|---|---|---|
| 主な対象 | ブラウザ・HTML・JavaScript | データベース |
| 問題 | 意図しないコードがブラウザで実行 | 意図しないSQL処理 |
| 主な防御 | 出力エスケープ・サニタイズ | プリペアドステートメント等 |
SQLインジェクションは、別記事「SQLインジェクションとは?仕組みと対策を解説」で扱います。
XSSとCSRFの違い
XSSとCSRFも別の攻撃です。
| 項目 | XSS | CSRF |
|---|---|---|
| 中心 | ブラウザで意図しないコードを実行 | ログイン済み利用者に意図しないリクエストを送らせる |
| 代表対策 | エスケープ・サニタイズ・CSP | CSRFトークン・SameSite等 |
CSRFの詳細は、別記事「CSRFとは?仕組みと対策を初心者向けに解説」で扱います。
XSS対策1.入力値を検証する
入力項目で受け付ける値が決まっているなら、期待する形式だけを許可します。
検証例
- 年齢 → 整数
- 選択肢 → 許可した値だけ
- メールアドレス → メール形式
- ID → 期待する文字・数字の形式
WordPress公式も、可能な場合は単に不要文字を取り除くサニタイズより、期待する形式かを確認して受け入れ・拒否するバリデーションを優先する考え方を示しています。
入力検証だけではXSS対策は完了しない
正しい入力に見えても、出力する文脈が変われば危険になる場合があります。出力時のエスケープも必要です。
XSS対策2.入力値をサニタイズする
サニタイズは、入力データから不要・不適切な内容を取り除いたり、安全な形式へ整えたりする処理です。
WordPressでは用途に応じて、sanitize_text_field()などの関数があります。
サニタイズとエスケープは別
サニタイズは主に入力データを整える処理、エスケープは出力先でコードとして解釈されないようにする処理です。片方だけで済ませないでください。
XSS対策3.出力時にエスケープする
XSS防御で特に重要なのが出力エスケープです。
OWASPは、ブラウザがHTML、属性、URL、JavaScript、CSSなどを異なる文脈として解析するため、出力場所に合ったエンコーディングが必要だと説明しています。
「どんな値か」だけでなく「どこへ出すか」でエスケープ方法を選ぶ
| 出力場所 | WordPressの代表例 |
|---|---|
| HTML本文 | esc_html() |
| HTML属性 | esc_attr() |
| URL | esc_url() |
| 許可HTML | wp_kses() / wp_kses_post() |
WordPress公式は「できるだけ遅く、実際に出力する直前でエスケープする」方針を推奨しています。
esc_html()とは?
esc_html()は、HTML要素内へ文字列を表示するときに使う代表的なエスケープ関数です。
考え方
見出しや通常テキストとして表示したい値は、HTMLとして解釈させず文字列として安全に出力します。
WordPressテーマ・プラグイン開発では、外部入力やデータベースから取得した値をそのままechoしないことが基本です。
esc_attr()とは?
esc_attr()は、HTML属性の値を安全に出力するときに使います。
対象例
- title属性
- alt属性
- value属性
- data属性の文字列
WordPress公式では、属性値に使われる特殊文字を適切にエスケープする関数として案内されています。
esc_url()とは?
リンク先や画像URLなど、URLを出力するときはesc_url()を使います。
URLを単純にHTML属性用のエスケープだけで処理するのではなく、URLとして安全な形式・プロトコルかを考慮する必要があります。
用途ごとの関数を使う
HTML本文、属性、URLをすべて同じ関数で処理するのではなく、出力先に合ったWordPress APIを使ってください。
HTMLを許可したい場合はwp_kses()を使う
投稿フォームやリッチテキストなど、利用者へ一部HTMLを許可したい場合、すべてを文字列化すると必要な装飾まで消えてしまいます。
そのような場面では、許可するHTML要素・属性を限定して危険な内容を除くサニタイズが必要です。
WordPressの代表例
- wp_kses()
- wp_kses_post()
wp_kses()は許可したHTML要素・属性だけを残すために使えます。
XSS対策4.危険なDOM操作を避ける
ブラウザ側JavaScriptでは、外部から取得した文字列をHTMLとして解釈するAPIへ直接渡さないことが重要です。
単純な文字列表示なら、HTMLとして解析する方法ではなく、テキストノードとして扱える安全なAPIを優先します。
DOM-based XSSはWAFだけでは防ぎにくい
ブラウザ内だけで発生するDOM-based XSSは、サーバーへ攻撃文字列が送信されない場合があります。フロントエンドコード自体を安全に実装する必要があります。
XSS対策5.CSPを追加防御として使う
CSP(Content Security Policy)は、ブラウザがどのスクリプト等を実行・読み込みできるか制限するHTTPヘッダーです。
MDNとOWASPは、厳格なCSPをXSSの影響を抑える追加防御として案内しています。 ただし、CSPだけで脆弱な出力処理を修正できるわけではありません。
エスケープ・サニタイズ=根本対策
CSP=追加の防御層
CSPの設定方法と注意点は、別記事「CSPとは?Content Security Policyの仕組みを解説」で扱います。
WAFはXSS対策になる?
WAFは、XSSに見られる不正なリクエストを検知・遮断する追加防御として役立つ場合があります。
しかし、OWASPはWAFをXSSの根本対策として推奨していません。 新しい回避方法が見つかる可能性があり、DOM-based XSSのようにクライアント側だけで成立する問題を防げないためです。
WAFの位置づけ
脆弱なコードを直す+WAFを追加防御として使うのが基本です。
WordPressでXSSが起こる主な原因
確認する場所
- 古いWordPress本体
- 脆弱性のあるプラグイン
- 脆弱性のあるテーマ
- 独自テーマの出力処理
- 独自プラグイン
- ショートコード
- Ajax処理
- 外部APIデータの表示
WordPress本体だけを更新しても、古いプラグインや独自コードに脆弱性が残っていれば問題になる可能性があります。
WordPress利用者ができるXSS対策
コードを書かない一般利用者は、まず脆弱なソフトウェアを残さないことが重要です。
運営者向けチェック
- WordPress本体を最新版へ更新する
- テーマを更新する
- プラグインを更新する
- 不要なテーマ・プラグインを削除する
- 更新停止したプラグインを見直す
- WAFを利用できるなら有効化を検討する
- 定期バックアップを取る
更新が最優先
既知のXSS脆弱性が修正版で対処されている場合、古いバージョンを使い続けること自体がリスクになります。
WordPress開発者が確認すること
開発時の基本
- 信頼できない入力を検証する
- 保存前に用途に応じてサニタイズする
- 出力直前に文脈に合ったエスケープを行う
- HTMLを許可するならwp_kses()等で許可範囲を限定する
- 危険なDOM APIへ外部入力を直接渡さない
- WordPress公式APIを優先して使う
WordPress公式は「Never trust user input」「Escape as late as possible」をセキュリティ原則として示しています。
「入力時に危険文字を全部削除」で十分?
十分ではありません。
XSS対策では、同じ値でも出力先によって必要な処理が異なります。 HTML本文用の処理をJavaScriptやURLへそのまま流用すると、安全にならない場合があります。
一括置換へ頼らない
特定文字を全部削除する独自ルールより、フレームワークやWordPressが提供する、文脈ごとの標準APIを使う方が安全です。
HTMLエスケープだけで全部防げる?
いいえ。
HTML本文へ文字列を表示する場合はHTMLエスケープが有効ですが、URL、CSS、JavaScript、イベントハンドラなどは異なる文脈です。
OWASPは、危険なコンテキストへ信頼できない変数を入れること自体を避けるよう案内しています。
最も安全な考え方
信頼できない値をコードとして実行される場所へ入れない。必要な場合だけ、出力先専用の安全なAPIを使います。
CookieをHttpOnlyにすればXSSは防げる?
XSSそのものは防げません。
HttpOnly属性は、JavaScriptから対象Cookieへアクセスしにくくすることで被害を軽減する対策です。 しかし、XSSによる不正なスクリプト実行そのものを止める機能ではありません。
被害軽減と根本対策を分ける
Cookie属性、CSP、WAFは重要な追加防御ですが、脆弱な出力処理そのものを修正する必要があります。
XSSが疑われるときの対応
本番サイトで攻撃コードを試さない
脆弱性診断は、自分が管理する検証環境か、明確に許可を得た環境で行ってください。第三者サイトへ無断でテストを行わないでください。
レンタルサーバー利用者は何を確認すればよい?
個人ブログ
優先:更新
WordPress・テーマ・プラグインを更新し、不要なものを削除します。
会社サイト
優先:更新+WAF
問い合わせフォームを含むため、更新に加えてサーバー標準WAFも検討します。
EC・会員サイト
優先:多層防御
個人情報・ログイン機能を扱うため、コードレビュー、WAF、CSP、監視などを組み合わせます。
独自開発サイト
優先:実装確認
入力検証、サニタイズ、出力エスケープ、DOM操作を開発者が確認します。
XSS対策の優先順位
教科書判定
WordPress利用者は「更新」、開発者は「出力時エスケープ」を最優先する
一般的なWordPress運営者が、XSSの攻撃コードやブラウザ内部の細かな仕様まで覚える必要はありません。
まずWordPress本体・テーマ・プラグインを更新し、不要なものを削除することを優先してください。 レンタルサーバーにWAFがあるなら追加防御として有効化を検討します。
テーマ・プラグイン・独自Webアプリを開発する側では、入力値を信用せず、検証・サニタイズを行い、最終的に出力する文脈に合ったエスケープを行うことが基本です。
CSP、Trusted Types、WAF、Cookie属性などは有効な防御層ですが、脆弱なコードを放置する理由にはなりません。
FAQ
Q.XSSとは簡単にいうと何ですか?
Webページへ意図しないスクリプト等が入り込み、閲覧者のブラウザ上で実行される脆弱性・攻撃です。外部入力を安全に処理せずページへ出力することが主な原因になります。
Q.XSSとSQLインジェクションは同じですか?
違います。XSSは主にブラウザ上での不正なコード実行、SQLインジェクションはデータベースへ意図しないSQLを実行させる問題です。対策方法も異なります。
Q.WordPressならXSS対策は不要ですか?
不要ではありません。WordPress本体だけでなく、テーマ・プラグイン・独自コードに脆弱性が見つかる場合があります。更新を続け、開発時はWordPress公式の安全なAPIを使ってください。
Q.WAFを有効にすればXSSは完全に防げますか?
完全には防げません。WAFは追加防御として有効ですが、DOM-based XSSを含め対応できないケースがあります。根本対策は安全な実装と脆弱性修正です。
Q.CSPを設定すればエスケープは不要ですか?
不要にはなりません。CSPは不正スクリプト実行を抑える追加防御です。入力検証、サニタイズ、出力エスケープなどの根本対策と組み合わせて使います。
まとめ
この記事の結論
- XSSは閲覧者のブラウザ上で意図しないコードが実行される脆弱性・攻撃
- Stored・Reflected・DOM-basedなどの種類がある
- 外部入力をそのまま出力しない
- 入力検証とサニタイズだけでなく出力時エスケープが重要
- HTML・属性・URLなど出力先ごとに適切な処理を使う
- WordPressでは公式のesc_*関数やwp_kses()等を使う
- CSP・WAF・Cookie属性は追加防御として利用する
- WordPress利用者は本体・テーマ・プラグイン更新を優先する
- 脆弱性テストは許可された環境だけで行う
XSS対策の中心は、「外部から来た値をコードとして実行させないこと」です。 WordPress利用者は更新と不要プラグイン削除を徹底し、開発者は入力時だけでなく、実際にページへ出力する瞬間まで安全性を確認してください。
「SQLインジェクションとは?仕組みと対策を解説」「CSRFとは?仕組みと対策を初心者向けに解説」「CSPとは?Content Security Policyの仕組みを解説」もあわせて確認してください。