コア更新の影響調査のつもりで functions.php を開いたら、バックドアが出てきた話
WordPress のコア更新にあたって、「カスタム投稿タイプのブロックエディタ制御コードが動かなくなるか見てほしい」という依頼を受けました。よくある互換性調査です。結論から書くと、その調査の途中で未認証のバックドアが見つかりました。
何が入っていたか
functions.php の後半、自作の関数がいくつか並んだ後ろに、見慣れない数行が挟まっていました。要約すると、特定の GET パラメータを付けてアクセスするだけで、管理者ユーザーとしてログイン状態にするという内容です。
パスワードもトークンも要りません。URL を知っていれば誰でも管理者になれます。
インデントも書き方も周囲のコードに寄せてあり、ざっと眺めただけでは自作の処理に見えます。ファイル更新日時も、直近の作業日と大きくは違いませんでした。
その場でやったこと
侵入の経路調査より先に、まず入口を閉じます。順番はこうでした。
- 該当コードを除去
- 全ユーザーのセッションを無効化(ログイン中のセッションを強制的に切る)
- 管理者権限を持つアカウントの一覧を確認し、身に覚えのないユーザーがいないかチェック
- 残っている管理者アカウントのパスワードを更新
- アクセスログを遡り、当該パラメータ付きのリクエストが来ていないか確認
3番で身に覚えのないアカウントが増えているケースは珍しくありません。今回はありませんでした。
依頼範囲との関係
厳密に言えば、これは受けた依頼の範囲外です。ただ、見つけてしまった以上は報告しないという選択肢がありません。状況を説明したうえで即時対応の可否を確認し、その場で作業しました。
こういうときに「範囲外なので次回見積もりします」と返すと、その数日のあいだ穴が開いたままになります。止血だけ先にやって、原因調査と再発防止はあらためて見積もる、という分け方が現実的だと思っています。
コア更新のほうの話
本題だった互換性調査のほうも書いておきます。Block Hooks 関連の処理が REST コントローラ側へ移っていたため、旧来の書き方をしていたフックが期待通りに動かなくなる箇所がありました。あわせて register_post_type_args での上書きと競合していた古いコードを整理しています。
教訓めいたこと
コア更新の前に functions.php を通しで読む、という作業には副産物があります。互換性の確認だけが目的でも、そのファイルに何が書かれているかを人間が一度読む機会自体が、意外と少ないからです。
長く運用しているサイトほど、誰がいつ書いたか分からないコードが溜まっています。更新のタイミングは、それを棚卸しする数少ない口実でもあります。
ほかの記事