プラグインのファイルは変わらないまま管理画面が狙われた

つくば市のホームページ制作会社

WordPressのプラグインは、更新のたびに配布元のファイルが差し替わる。だから「更新していないなら中身は変わっていないはず」と考えるのは自然で、実際その通りであることがほとんどだ。ところが今月、その前提の外側から入られた事例が報告された。プラグインのファイルは一行も書き換わっていないのに、管理画面を開いた管理者のブラウザで攻撃用のコードが動いていた、という話である。

対象になったのはBdThemesというElementor向けアドオンの開発元で、Element PackやPrime Slider、Ultimate Post Kitなど七つの製品が影響を受けた。WordPress.orgの公式ディレクトリでは、調査のあいだこれらの配布が一時停止されている。

更新していないサイトで何が起きていたか

報告によると、これらのプラグインにはBiggoptiという内部の部品が入っていて、開発元のサーバーから宣伝用のバナー情報をJSONで取得し、WordPressの管理画面に表示していた。攻撃者はそのJSONが置かれていたDigitalOcean Spacesのバケットに書き込める状態を手に入れ、正規のバナーデータを細工したものに差し替えた。

プラグイン本体は公式ディレクトリに置かれたまま、一文字も変わっていない。変わったのは、プラグインが管理画面を開くたびに取りに行く先の中身だけだ。セキュリティ企業のWordfenceがファイアウォール側でこの攻撃を検知したのが8月7日、公式ディレクトリでの配布停止が8月8日。汚染されたデータに残っていた日付をたどると、6月下旬には動き始めていた可能性があるとされている。

囲い忘れた一箇所が入口になった

差し替えられたデータが、それだけで害になるわけではない。効いてしまったのは、受け取った値の扱いに抜けがあったからだ。BiggoptiはJSONに含まれるdisplay_idという値を、エスケープしないままHTMLのid属性に埋め込んでいた。つまり外から届いた文字列が、そのままHTMLの一部として書き出される状態になっていた。

これはクロスサイトスクリプティング、いわゆるXSSの典型で、危険度はCVSSで5.4、中程度と評価されている。単体の欠陥としては目を引く数字ではない。ただ、値の供給元が攻撃者の手に渡った時点で、その中程度の欠陥が管理者のブラウザで任意のコードを走らせる経路に変わった。

調査で指摘されているのは、すぐ隣にある別の属性はきちんとエスケープされていた、という点だ。意図的な仕込みではなく、3月に入った変更のときの見落としとみられている。5月に追加された無害化の処理も、この属性までは届いていなかった。

ログイン中の管理者の権限がそのまま使われる

埋め込まれたコードは、アニメーションの開始をきっかけにするイベントハンドラを使い、管理画面が描画された直後に動く。そこから外部のサーバーへ追加のスクリプトを取りに行き、開いている管理者のセッションとnonceを借りる形で、REST API経由で新しい管理者アカウントを作る。

続いて、無害そうな名前の偽プラグインを追加し、その中にウェブシェルを置く。さらにMust-Useプラグインの領域へ居座り用の部品を仕込み、特定のURLパラメータを付けるだけでログインなしに管理者として入れる裏口を用意していた。もうひとつの部品はデータベースへの問い合わせに介入し、作成された管理者アカウントを利用者一覧から隠したうえ、人数の表示までつじつまを合わせていたという。

作られるアカウントの名前や連絡先は、サイトのホスト名から機械的に導ける形になっていた。攻撃する側は被害サイトの一覧を持ち歩かなくても、あとから同じ資格情報を計算し直せる。裏を返せば、調べる側にとっては何を探せばよいかがはっきりしているということでもある。

手元のサイトで確かめられること

この件が厄介なのは、ファイルの比較やプラグインのバージョン確認では手がかりが出てこないところだ。見るべきなのは結果として残ったもののほうで、具体的には管理者アカウントの一覧、プラグインディレクトリとMust-Useプラグインの中身、そしてオプションを保存しているテーブルになる。心当たりのない管理者が増えていないかは、専用のツールがなくても管理画面から確認できる。

より広く見れば、管理画面に外部から取ってきた内容を表示する部品は珍しくない。宣伝バナー、開発元からのお知らせ、キャンペーンの案内など、有償版の販売を持つ製品ほど組み込まれている。今回はその仕組みそのものが悪いというより、外から届いた値を自分のHTMLに置くときの手当てが一箇所抜けていたことが決め手になった。作る側の視点では、遠くから来た文字列は例外なく汚れているものとして扱う、という基本の話に戻る。

制作を請け負う立場だと、納品後のサイトは触る機会が減り、更新の通知が出ていなければ問題なしと見なしがちだ。今回のように配布物が無傷のまま影響が出る攻撃があると分かった以上、管理者の一覧をときどき眺めるくらいの軽い確認は、手間の割に効き目がありそうに思える。

投稿の編集画面がiframeに一本化された

つくば市のホームページ制作会社

WordPress 7.1 が8月19日に公開され、投稿の編集画面まわりに地味ながら影響範囲の広い変更が入った。投稿エディタが、条件にかかわらず常に iframe の中で動くようになったことだ。画面の見た目はほとんど変わらないので気づきにくいが、ブロックを拡張するプラグインや自作ブロックを抱えているサイトでは挙動が変わる可能性がある。

これまでは記事の中身しだいで切り替わっていた

WordPress はここ数年、編集画面を少しずつ iframe の中へ移してきた。最初に移ったのはテンプレートエディタで、5.8 のときだった。その後サイトエディタや端末別のプレビューも常時 iframe 化され、最後まで残っていたのが投稿の編集画面だった。

7.0 の時点では、投稿に挿入されているブロックのブロック API のバージョンを見て判断していた。挿入済みのブロックがすべて API バージョン3以上なら iframe 化し、それより古いブロックがひとつでも混ざっていれば互換性を優先して iframe をやめる、という仕組みだ。つまり同じサイトの中でも、記事の中身によって編集画面の作りが変わっていたことになる。

7.1 からはこの条件分岐がなくなった。テーマの種類にも、登録されているブロックの API バージョンにも、本文に入っているブロックにも関係なく、投稿の編集画面は常に iframe になる。従来ながらのメタボックスを登録しているサイトも対象に含まれる。

切り離すことで何が変わるのか

iframe は別の HTML 文書を画面の中に読み込む仕組みで、中と外でスタイルの適用範囲が分かれる。編集画面を iframe に入れると、管理画面側の CSS が本文の表示に混ざり込まなくなる。ビューポート単位やメディアクエリも、ブラウザのウィンドウ幅ではなく編集領域そのものの幅を基準に効くようになる。

編集画面の見た目と公開後の見た目をそろえるという点では、筋のいい方向だと思う。7.1 ではタブレットとモバイルの表示を theme.json 側から指定できる仕組みも入っており、幅の判定基準をはっきりさせる必要はもともと高まっていた。条件によって iframe になったりならなかったりする状態のままでは、同じテーマでも記事ごとに確認結果が変わりかねない。

つまずくとしたら document と window のあたり

公式の開発者向け案内によると、ほとんどのブロックは手を入れなくても iframe 化された編集画面で動くとされている。問題が出る場合も、原因はだいたい同じところに行き着くという。iframe は自前の document と window を持っており、編集画面のスクリプトが動いている管理画面側とは別物だ、という点だ。

グローバルな document や window をそのまま参照して編集領域の要素を触っているコードは、意図しない側の文書を見に行ってしまう。対処としては、編集領域の中にある要素から ownerDocument とその defaultView をたどって正しい文書を取得する方法と、イベントリスナーの登録と解除を useRefEffect で行う方法が案内されている。自作ブロックやエディタ拡張を納品している制作者なら、更新前に手元の環境で開いて確かめておきたいところだ。

なお Gutenberg プラグインでは 22.6 以降、プラグインが有効な環境では投稿エディタを強制的に iframe 化する挙動が先行して入っていた。互換性の問題を早めに表面化させ、コアに入る前に報告してもらうためだという。プラグイン版を入れて運用していたサイトは、すでにこの状態を通ってきていることになる。

一覧画面の行見出しも入れ替わっている

同じ 7.1 では、投稿一覧の表の組み立ても変わった。行の見出しを担う、scope 属性が row の th 要素が、チェックボックスの列からタイトルの列へ移っている。チェックボックスのセルは td になり、タイトルのセルが th になって、投稿タイトルを aria-label として持つ形になった。

読み上げソフトが各行をチェックボックスではなく投稿名で認識できるようになるので、アクセシビリティの面では順当な改善だ。ただしこのあたりの markup は2010年ごろからほとんど動いていなかった部分で、一覧画面に独自の列を足すプラグインや、管理画面向けに書いた CSS が暗黙のうちに依存している場合がある。チェックボックス列のクラスを狙っているセレクタや、投稿タイトルが td の中にある前提で書いた JavaScript があれば、更新後に一度見ておくと安心だ。

中小企業のサイト運用では、編集画面まわりの変更は不具合として上がってくるより先に、なんとなく使いにくくなったという曖昧な形で相談が来ることが多い。更新後に自分で新規投稿を一本開いて、普段使っているブロックとプラグインがいつもどおり動くかを確かめておく。それだけで、たいていの不安は先回りして片付けられる。

ゲスト購入した注文をあとから会員に紐づけられるように

つくば市のホームページ制作会社

ウェブショップを動かすWooCommerceの新しい版、11.0が公開されました。八月四日付の公開で、551件の変更が取り込まれ、89人が関わった大きめの更新です。中身は目新しい機能を足すより、土台の整理と積み残しの解消に寄っています。その中で買い物客の側から見て分かりやすいのが、ゲスト購入まわりの扱いの変化です。

WooCommerceには以前から、購入手続きを終えたあとにアカウントを作れる仕組みが用意されていました。11.0ではそこから一歩進んで、購入者が過去のゲスト注文を自分で探し出し、メールアドレスの確認を経てアカウントに結び付けられるようになっています。会員登録を後回しにしたまま何度か買い物をした人でも、あとから注文履歴を一つにまとめられる、という流れです。店舗側で名寄せの問い合わせに対応していた手間が、そのぶん減る可能性があります。

規模の大きい店舗向けの速度改善も入りました。内部の問い合わせの最適化、Store APIの改善、注文処理を通した在庫状態の扱いの見直しが挙げられており、商品数や注文数が増えるほど効いてくる部分です。ほかに、計測の取りこぼしを減らす調整、返金を売上の集計に反映する変更、取り込みに失敗した過去データをやり直せる仕組みも含まれています。

直後に出た修正版もあわせて

その六日後には11.0.1が出ています。こちらはセキュリティ更新の扱いで、ゲストのセッションcookieがソルト付きのより強いハッシュに変わりました。古いcookieは期限が切れるまで有効なままなので、更新をまたいでもゲストのカートは残ります。ほかにも、商品の短い説明にもパスワード保護が及ぶようになった点、Store APIでクーポンの利用回数の上限が正しく適用されるようになった点、カートや購入手続きのブロックに表示される通知の中身が安全に処理されるようになった点が並びます。ログの書き込みのたびにフォルダ全体を走査しなくなり、記録がたまった店舗で購入手続きが重くなりにくくなった改善も入りました。あわせて、次のWordPress 7.1に向けた互換性の調整も進んでいます。注文一覧が新しい一覧表の記述に合わせられた、といった地味な内容ですが、本体の更新を控えている店舗にとっては先に当てておきたい版といえます。

会員登録を必須にすると買い物の途中で離れられやすい、という悩みは店舗の規模を問わず共通です。ゲストのまま買えるようにしておき、必要になったときに履歴をアカウントへ寄せられる作りは、無理のない落としどころだと感じます。会員向けの案内やクーポンを届けたい店舗にとっても、購入のハードルを上げずに接点を作れる余地が広がります。一方で、注文とアカウントを結び付ける処理はメールアドレスの確認を挟むとはいえ個人情報に触れる部分なので、公開前に自分の店舗の設定で挙動を一度確かめておきたいところです。11.0はデータベースの更新を伴うため、控えを取ったうえで検証環境から順に試すのが安全です。

更新前に確かめておきたいWordPressの挙動変更

つくば市のホームページ制作会社

WordPressの次の版が8月19日に公開される予定で、いまは公開直前の候補版が配布され、検証が進んでいる段階です。新機能の紹介はあちこちで出そろってきましたが、制作の現場で先に気になるのは、いま動いているサイトのどこが変わるかのほうではないでしょうか。

公式の開発者向けまとめを読むと、機能追加とは別に、既存のテーマやプラグインが前提にしていた作りが静かに変わる箇所がいくつかあります。派手な話ではありませんが、当たっていると管理画面の見た目や動きに出ます。更新前に目を通しておきたいものを並べてみます。

投稿の編集画面が常に枠の中で動く

これまでは、テーマの種類やブロックの版によって、投稿編集画面がiframeの中に入るかどうかが切り替わっていました。次の版では条件によらず常に枠の中で動きます。どちらになるか読めない状態が解消されるのは扱いやすくなる方向の変更です。

ただし、編集画面に独自の見た目を足している場合は挙動が変わる可能性があります。enqueue_block_editor_assetsのような正規の入口から読み込んでいれば影響は小さいはずですが、管理画面全体のCSSに紛れ込ませていたり、親の画面を直接触るスクリプトを書いている場合は、実際に開いて確かめておくのが早いです。

一覧画面の表の作りが変わる

投稿一覧などの表で、行の見出しとして扱われるセルが、チェックボックスの列からタイトルの列へ移ります。読み上げたときの筋道としては素直になる変更ですが、列の位置を決め打ちしたセレクタに頼っている拡張は影響を受けることがあります。

一覧に独自の列を足すプラグインは、中小企業のサイトでもよく入っています。受注状況や公開予定日を一覧に出すような作り込みをしている場合は、更新前に検証用の環境で開いてみる価値があります。

管理画面の入力部品の大きさがそろう

管理画面の部品群では、大きさを指定していたプロパティが役目を終え、フォーム部品は一律で40ピクセルの高さで描かれるようになります。小さめの指定は渡しても効かなくなり、非推奨の扱いになります。

独自の設定画面を持つプラグインを作っている場合、詰めて並べていた入力欄の高さが変わり、レイアウトが縦に少し伸びることがあります。壊れる類の変更ではありませんが、二列に並べていた部分の折り返しなど、見た目の調整が必要になるかもしれません。

ナビゲーションの文字サイズの効き方が変わる

ナビゲーションのブロックが、子の項目に自分の文字サイズを押し付けなくなります。入れ子のドロップダウンで文字サイズが掛け算のように効いてしまい、階層が深いほど不自然に大きくなる、あるいは小さくなるという問題への対処です。

回り道の指定でごまかしていた部分が本体側で正されるのはありがたい変更ですが、裏を返せば、更新後にメニューまわりの見た目が変わるサイトはあるということです。納品済みのサイトが複数ある制作者は、階層メニューを持つものだけでも一度目視しておきたいところです。

実験段階だった機能が正式に使えるようになる

タブとプレイリストのブロックが実験扱いから外れ、標準の部品として使えるようになります。加えて、背景にグラデーションと画像を重ねられる指定や、ブロックの最小幅を指定できる仕組みも増えました。管理画面に説明の吹き出しを出すための関数も用意され、読み上げに配慮した形で組み込めるようになっています。

これまで小さなプラグインや自作のブロックで賄っていた部分が、本体側だけで足りるようになるかもしれません。プラグインの数を減らせれば更新の手間も脆弱性の窓口も減るので、棚卸しのきっかけにはなりそうです。

公開までは一週間ほどです。候補版は検証用に配布されているので、複雑なテーマや作り込んだ管理画面を抱えているサイトは、本番の更新を待つ前に複製した環境で一度開いておくと、当日は落ち着いて臨めます。

WordPressの土台にあるReactの入れ替えが先送りになった

つくば市のホームページ制作会社

WordPressの管理画面、とくにブロックエディタの中身は、Reactというメニューや画面部品を組み立てるためのJavaScriptライブラリで動いています。そのReactを新しい世代に入れ替える作業がしばらく進められていたのですが、8月に予定されている次のWordPressには入らないことになりました。開発チームが7月下旬にMake WordPress Coreで経緯を公開しています。

いったんはGutenbergプラグインの側で新しい世代に切り替えてみたものの、想定していなかった不具合が続けて報告され、数日で元に戻されたとのことです。原因として挙げられているのは大きく二つ。ひとつは、プラグインがReactの部品をWordPress本体から借りずに自前で同梱していたケースで、この場合は古い世代と新しい世代が同じ画面の中で同時に動いてしまい、内部のデータの持ち方が食い違って壊れます。もうひとつは、新しい世代で廃止された古い書き方が、プラグイン側にそのまま残っていたケースです。文字列で書くref、関数コンポーネントへのdefaultProps、旧来のcontextの定義などが具体例として挙がっています。

本体は当面そのまま、試したい人には実験用のスイッチ

そのため、次のWordPressは従来どおりのReactを載せたまま出ます。切り替えを先に試しておきたい開発者向けには、Gutenbergプラグインの23.4以降に実験用のスイッチが用意されました。設定画面から有効にすると、本体が配っている部品だけが新しい世代に差し替わり、公開済みのプラグインが将来直面する状況をそのまま再現して確かめられます。あわせて、公式のPlugin Checkプラグインには、問題になりやすい書き方を自動で見つける検査を追加する作業が進められています。手作業で全部を洗い出さなくてよくなったのは、地味ですが助かる変更です。

サイトを運用している立場からすると、今回のニュースは特に何かをする話ではありません。ただ、独自のブロックや管理画面の拡張を自作している、あるいは制作会社に作ってもらっている場合は、事情が少し変わります。いずれ切り替えは来るので、その前に一度実験用のスイッチで動作を確かめ、ブラウザのコンソールにエラーが出ていないかを見ておくと、あとで慌てずに済みます。ブロックエディタまわりのカスタマイズは、こうした土台の入れ替えの影響をまっすぐ受ける場所です。

互換性の問題が見つかった時点で無理に押し通さず、二日で元に戻して検証期間を取り直したという判断は、更新のたびに現場が振り回されないという意味ではありがたい話でもあります。管理画面が急に開かなくなったときに困る度合いは、社内に専任の担当を置きにくい中小企業のサイトほど大きくなります。派手さのない先送りですが、その裏側を眺めておくと、次に来る更新への構え方も少し変わってきます。