対象
WordPress本体(コア)のページテンプレート解決機構です。
原因
この脆弱性は、WordPressがページを表示する際にテンプレートファイルを選び出す処理の中に存在します。
攻撃者は認証なしで、フォームのPOSTリクエストにpagenameとpage_idという2つの公開クエリ変数を同時に送りつけることができます。
本来はパス区切り文字として扱われるはずの記号がパーセントエンコードされたまま初期のサニタイズ処理をすり抜け、page_idによって実在の公開ページが選択された後も、pagenameの値はクエリオブジェクトに残り続けます。
その後、get_page_template()関数がurldecode()でこの値をデコードする際に、エンコードされていた区切り文字や親ディレクトリを指す記号が有効なファイルシステムの構文として復活してしまいます。
WordPressは固定の「page-」という接頭辞と「.php」という拡張子を付けてファイルを探しますが、最終的なインクルード処理はrealpath()でパスを正規化し、その存在・拡張子・読み取り可能性を確認するだけで、解決されたパスが実際にテーマディレクトリの内側に収まっているかどうかまでは確認していません。
つまり「正規化されていること」と「信頼された場所に閉じ込められていること」は別物であり、この取り違えによって、テーマディレクトリの外にある読み取り可能なローカルPHPファイルを読み込ませることが可能になっています。
影響を受けるシステム
WordPress本体
修正版:
7.1系は7.1.2
7.0系は7.0.6
加えて4.7系までの古いブランチにもバックポートがあり、攻撃条件を満たす特定のテーマ構成・サーバー構成を持つ環境。
想定される被害
この脆弱性自体は、認証もプラグインもユーザーの操作も必要とせず、匿名のリクエストだけで成立するローカルファイルインクルージョンです。
ただしこれが即座に任意コード実行につながるわけではなく、具体的には、読み取り可能なpearcmd.phpエントリーポイントが存在し、Web向けのPHP設定でregister_argc_argvが有効になっており、PHPプロセスが一時ディレクトリに書き込める、という条件がすべて揃って初めて、1回目のリクエストで攻撃者が制御するPHPコードを含むファイルを生成させ、2回目のリクエストで同じ脆弱性を使ってそのファイルを読み込ませる、という2段階の手順が成立します。
また、この検証はテーマルート直下に「page-」で始まるディレクトリ(例:page-templates/)が存在すること、正しいカスタムテンプレートが事前に割り当てられていないこと、読み取り可能なローカルPHPファイルが実在することなど、複数の前提条件がすべて揃って初めて成立するものです。
攻撃が成立した場合、サービスアカウントの権限に応じて、設定情報やデータベースの認証情報へのアクセス、サイトデータの閲覧・改変、書き込み可能なアプリケーションリソースの改変、サイトの機能停止などが起こり得ます。
対策
修正済みバージョン(7.1系は7.1.2、7.0系は7.0.6、または4.7系までの該当バックポート)へWordPressを更新します。
Web向けのPHP設定でregister_argc_argvが不要であれば無効化します使用していない、Webから読み取り可能なPEARのエントリーポイントを削除します。
PHPアカウントのファイルシステムへのアクセス権・書き込み権限を制限します。
これらの追加的な対策はコアの修正を補完するものであり、修正版への更新の代わりにはなりません。