事例レポート#PHP#WordPress#Cloudflare#Claude#サイバーセキュリティ

PHP脆弱性「php2shell」をきっかけにWordPressを卒業した話|静的化・Cloudflare移行・DNS切り替えの実践記録

公開日 / 最終更新 / 読了時間 約15分/ 執筆 代表取締役 橋本/ カテゴリ 事例レポート
PHP脆弱性php2shellをきっかけにWordPressを卒業し、静的HTML化・Cloudflare Pages移行・DNS切り替えを行った実践記録

2026年10月21日、PHPの緊急脆弱性「php2shell」(CVE-2026-109618/CVE-2026-109619)の修正版が公開されました。その日、カトルセはWordPressとPHPのアップデートを「やらない」と決め、コーポレートサイトを静的HTMLに置き換えてCloudflare Pagesへ移しました。PHPが動かないサーバーには、PHPの脆弱性は届かないからです。

この記事は、その判断の理由と、実際に行った手順(静的化・Cloudflare移行・DNS切り替え・SEO対策)を、中小企業のWeb担当者が同じことを再現できる粒度でまとめた実践記録です。作業の多くはClaude(生成AI)と分担し、作業を5つの段階に分けて確認しながら進め、全体を約2時間で終えました。どの段階でも数分で元に戻せる手順を用意したうえでのことです。

この記事で分かること
  • 脆弱性対応で「パッチを当てる」以外の選択肢と、その判断基準
  • WordPressサイトを、URLを変えずに静的サイトへ置き換える方法
  • Cloudflare PagesとVercelの違いと、コーポレートサイトにCloudflareを選んだ理由
  • メールを止めずにDNS(ネームサーバー)を移す手順と、事故を防ぐ確認ポイント
  • 移行で検索順位を落とさないためのリダイレクトとサイトマップの扱い

※ 本記事では、セキュリティ上の理由からサーバーのIPアドレス、アカウント名、DNSレコードの値、社内システムの名称などは伏せています。

背景:PHPの脆弱性は「パッチを当てれば終わり」ではなかった

php2shellは、ログインなしで外部からサーバー上のプログラムを実行されるおそれがある、PHPの2件の脆弱性の通称です。深刻度はCVSS v4.0で9.2(緊急)。WordPressなどのCMSを含め、Webのリクエストを処理するPHPの動かし方はすべて対象です。対象バージョン・修正版・更新手順・応急処置は、解説記事「PHPの緊急脆弱性「php2shell」とは」にまとめています。

公表された脆弱性への正攻法は、修正版(パッチ)を当てることです。しかしphp2shellでは、PHP 8.1以前にはPHP公式の修正版が出ません。当社のサイトは、まさにその前提が崩れていました。調べると、現状は次のような状態でした。

項目状態意味すること
サーバー国内の共用レンタルサーバーOSやWebサーバーの更新は事業者任せ。PHPは利用者が版を選ぶ
PHP公式サポートが終了した7系本家からの修正版はもう出ない。「当てるパッチが無い」
WordPress数年前のメジャーバージョン最新版はPHPの上げ幅も大きく、テーマとプラグインの互換性が読めない
サイトの中身新しいページ群は既に静的HTML。WordPressには「お知らせ」約77件と固定ページ・投稿が残る動的に動かす必要があるのはお問い合わせフォームだけ。それも外部のシステムに送信していた

つまり「PHPを動かし続ける理由」が、もうほとんど残っていませんでした。ここから、取りうる3つの道を比べました。

同じ状況の企業は少なくありません。制作会社に作ってもらったWordPressサイトが、更新されないまま数年たっている、というケースです。まずは自社サイトのPHPとWordPressのバージョンを確かめることから始めてください。

選択肢A:WordPressを最新版にする(採用しなかった)

一番に思いつく対応ですが、当社は「やらない」と決めました。理由は、必要な作業量に対して、得られる安全が一時的だからです。

本気でやる場合に必要な作業

  1. サイト一式とデータベースのバックアップ
  2. 検証環境(ステージング)の用意
  3. WordPress本体を段階的に更新(メジャーバージョンを飛ばすとデータベースの変換で失敗しやすい)
  4. テーマ・プラグインの互換性確認。開発が止まったプラグインは代わりを探す
  5. 制作会社が作った独自テーマの修正(壊れたら自社では直せない)
  6. 全ページの表示確認と本番反映

採用しなかった理由

  • これだけでは今回の脆弱性は塞げない。今回の問題はPHP側にあり、WordPressを上げてもPHPは古いままです。
  • 維持費が続く。WordPressは本体・テーマ・プラグインがそれぞれ更新され、更新を止めた瞬間から攻撃対象になります。管理画面とログイン画面を外部に公開し続けることにもなります。
  • 使っていない機能にコストを払う。新しい記事は既に別の仕組みで作っており、WordPressは「過去のお知らせを表示するだけ」の役割でした。
  • 決めた日の夜には終わらない。互換性の確認に時間が読めず、その間もサイトは脆弱なままです。

選択肢B:PHPを新しいバージョンに上げる(採用しなかった)

レンタルサーバーの管理画面では、PHPのバージョンをプルダウン一つで切り替えられます。作業としては最も短く済みますが、これも見送りました。

採用しなかった理由

  • 古いWordPressは新しいPHPで動かない。PHP 8系では廃止された関数や変わった挙動が多く、古い本体・テーマ・プラグインは画面が真っ白になる、管理画面に入れなくなるといった障害を起こしがちです。
  • 結局、選択肢Aとセットになる。PHPを上げるにはWordPressも上げる必要があり、Aの作業量がそのまま乗ってきます。
  • 切り戻しはできても、脆弱な状態に戻るだけ。不具合が出てPHPを元に戻せば、サイトは表示されても脆弱性は残ります。

AもBも「PHPとWordPressを今後も使い続ける」ことが前提です。当社は、その前提自体を外すことにしました。

意思決定:「直す」のではなく「なくす」

選んだのは、サイトを静的HTMLに置き換え、PHPを動かさない配信基盤(Cloudflare Pages)へ移す道です。攻撃される部品そのものを取り除くので、今回の脆弱性だけでなく、今後のPHP・WordPressの脆弱性もまとめて無関係になります。

php2shell対策の3つの選択肢比較:WordPress更新・PHP更新・静的化とCloudflare
観点A WordPress更新B PHP更新C 静的化+Cloudflare(採用)
今回の脆弱性解消しない解消(WordPressが動けば)解消(PHPが無い)
今後の脆弱性更新を続ける限り対応更新を続ける限り対応攻撃される部品がほぼ無い
壊れるリスク中〜高(互換性)高(古いコード)低(仮のURLで事前に全件確認できる)
切り戻しバックアップから復元管理画面で戻すDNSを1行戻す(数分)
住み続けるコスト本体・プラグインの更新作業+サーバー代同左サーバー代は無料枠内。更新作業は内容の変更時のみ
失うものなしなし管理画面からの記事投稿

判断の決め手になった3つの問い

  1. サーバー側で動かす必要がある機能は何か?── お問い合わせフォームだけ。しかも送信先は既に別システムだった。
  2. 管理画面から記事を書く人はいるか?── 新しいページはClaudeと一緒にHTMLで作っており、管理画面は使っていなかった。
  3. 過去のページを捨てられるか?── 捨てられない。新しいトップから過去のお知らせへリンクしており、検索の評価もそこにある。→ 同じURLのまま静的なコピーで残すと決めた。

1と2の答えが「ほぼ無い」なら、静的化は有力な選択肢です。逆に、会員機能やEC、非エンジニアによる日々の記事更新があるサイトでは、静的化だけでは済みません。

実践①:Claudeと進める静的ページへのリプレース

静的化の要点は「今あるページを、同じURL・同じ見た目のHTMLファイルにする」ことです。作り直しではなく引っ越しと考えると、作業の大半をClaude(Claude Code)に任せられます。

手順

  1. 棚卸し ── 公開中のURLを全件洗い出す。サイトマップ、サーバー上のファイル、データベースの投稿一覧を突き合わせる。当社では、既存の静的記事60本超に加え、WordPress側にお知らせ約77件・固定ページ31件・投稿13件がありました。
  2. バックアップ ── 公開フォルダを丸ごと、データベースも書き出して社内の共有ドライブへ。脆弱性の公表中なので、WordPressの管理画面へのログインは避け、FTPとデータベースの画面で作業しました。
  3. 静的なコピーを作る ── ブラウザに表示されているHTMLをそのまま保存し、同じパスに置く。画像・CSS・JavaScriptも含める。
  4. 入れないものを決める ── 管理画面・ログインページ・XML-RPC・REST API・PHPファイル全部。初期状態のまま残っていたサンプルページやテストページもここで整理。
  5. 転送ルールを移す ── サーバーの設定ファイル(.htaccess)や転送プラグインにあったリダイレクトを、Cloudflare Pagesの _redirects ファイルに写し替える。整理したページも、近いページへ転送する。
  6. GitHubの非公開リポジトリに入れる ── 以後の更新はすべてここから。変更履歴が残り、いつでも前の版に戻せます。
  7. 突き合わせチェック ── 旧サイトと新サイトで全URLの応答を比べ、404が無いか機械的に確かめる。

Claudeに任せたこと、人がやったこと

作業担当ポイント
URLの洗い出し、ページ種別の分類Claudeサイトマップと実ファイルの突き合わせを自動化
静的コピーの作成、不要ファイルの除外Claude「.phpが1つも無いこと」を完了条件にした
転送ルールの変換、サイトマップの作成Claude人は結果を確認するだけ
全URLの突き合わせチェックClaude新旧の応答コードを比較
手順書兼チェック表の作成Claude全員で同じ進捗を見られる共有ページにした
各サービスへのログイン、設定の変更ボタン人認証情報はAIに渡さない
見た目の確認、切り替えの判断人最後の「進む/戻す」は人が決める
コツ:Claudeには「作って」より「確かめて」を多く頼むと、移行の質が上がります。当社では、旧サーバーにも www 付きのアドレスが存在していたことを、事前の確認で後から発見して手順を直しています。

実践②:配信基盤にCloudflareを選んだ理由(Vercelとの比較)

コーポレートサイトのような静的サイトなら、Cloudflare Pagesが最も無理なく経営できると判断しました。決め手は、商用でも無料で使えることと、DNS・CDN・セキュリティが1か所にまとまることです。

当社は社内システム(お問い合わせの受付など)を既にVercelで動かしており、「どちらか一方」ではなく「役割で使い分ける」結論になりました。

観点Cloudflare PagesVercel
商用利用の無料枠無料プランで商用利用可無料のHobbyプランは個人・非商用に限定。企業サイトは実質有料プラン
転送量静的配信は実質無制限プランごとに上限あり。超過分は従量課金
DNS無料のDNSを一体で提供。wwwなしのドメインも素直に向けられるDNSは外部でも可。wwwなしは指定のAレコードで対応
セキュリティDDoS対策、ボット対策、HTTPS強制、TLSの最低版の指定などが無料で使える標準でDDoS対策とHTTPS。細かいWAFは上位プラン中心
得意分野静的サイトと、その前段のネットワーク全般Next.jsなど、サーバー処理を含むWebアプリ
開発体験GitHub連携、プレビューURL、_redirects による転送GitHub連携、プレビューURL、管理画面の分かりやすさは業界屈指
当社での役割コーポレートサイトとDNS社内システム・お問い合わせ受付

※ 料金・上限は執筆時点の公開情報に基づく概要です。契約前に各社の公式ページで最新の条件を確かめてください。

Cloudflare Pagesの設定(静的サイトの場合)

  • GitHubを接続し、対象のリポジトリだけにアクセスを許可する
  • フレームワーク:なし/ビルドコマンド:空欄/出力ディレクトリ:リポジトリ直下
  • 公開されると、まず プロジェクト名.pages.dev の仮のURLで表示される。本番のDNSに触る前に、このURLで全ページを確かめられるのが大きな利点
  • _redirects は行数に上限がある(執筆時点で静的な転送2,000行)。大規模なサイトは事前に数えておく

実践③:DNSの切り替え ── 5つの段階に分け、約2時間で切り替える

移行で一番怖いのは、サイトではなくメールが止まることです。ドメインのDNSには、Webサイトの行き先だけでなく、メールの行き先やなりすまし防止の設定が入っているからです。そこで当社は、作業を5つの段階に分け、各段階の確認を終えてから次へ進むやり方で、作業全体を約2時間で終えました。

WordPressから静的サイトへの移行の5段階:DNSを移す日とサイトを切り替える日を分ける
本来は「DNSを移す日」と「サイトを切り替える日」を分けるのが安全です。上の図のように、DNSだけを移して48時間ほどメールとサイトの様子を見てから切り替えれば、問題が起きたときに原因を切り分けやすくなります。当社が待たずに約2時間で終えられたのは、①段階0でDNSレコードを全件実際に引いて照合し終えていた、②新サイトを仮のURLで全ページ確認済みだった、③メールの行き先は変えず値を写すだけだった、④各段階の切り戻し手順を用意していた、からです。メールの設定が複雑な場合や、棚卸しに自信がない場合は、日を分けてください。

方針:変えるものと変えないもの

変える変えない
ネームサーバー(DNSの管理場所)をCloudflareへドメインの契約先(レジストラは移管しない)
Webサイトの配信元をCloudflare Pagesへメールの行き先(DNSレコードをそっくり写す)
ページのURL、お問い合わせの送信先

ネームサーバーごと移したのは、wwwなしのドメイン(例:example.co.jp)をCloudflare Pagesに向けるには、DNSをCloudflareで管理する必要があるためです。レジストラのDNSのままだと、転送のためだけに旧サーバーを残すことになります。

段階 0棚卸し(本番に影響なし)

  1. レジストラで、ドメインの有効期限と自動更新を確認(移転中の期限切れを防ぐ)
  2. 現在のDNS設定画面を丸ごとスクリーンショットで保存
  3. 画面の一覧だけを信じず、実際の値を引く。Google Admin ToolboxのDigなどで、A・AAAA・MX・TXT(SPF)・DKIM・DMARC・CAAと主なサブドメインを1つずつ引き、「DNS棚卸し表」に書き込む。レンタルサーバーの「かんたん設定」で入ったレコードは、一覧に出ないことがある
  4. Search Consoleの所有権確認、外部ツールのドメイン認証など、社内で使っているサブドメイン・TXTを洗い出す
  5. メールの行き先を確定させる。旧サーバーのメールを使っているアドレスがあれば、解約前に移す計画が必要
  6. DNSSECが無効であることを確かめる(DSレコードが空)。有効なままネームサーバーを変えると、サイトもメールも全く引けなくなる

段階 1新しいサイトを用意(本番に影響なし)

「実践①」「実践②」のとおり、静的化したサイトをCloudflare Pagesに載せ、仮のURLで全ページを確認します。

段階 2DNSだけを移す(数分で戻せる)

  1. Cloudflareにドメインを追加(Freeプラン)し、自動スキャンの結果を棚卸し表と1文字ずつ照合する
  2. この段階では全レコードを「DNSのみ」(灰色の雲)にする。中身は今と全く同じで、管理する場所だけが変わる状態を作る
  3. SPFのTXTは1つだけにする(2つあるとメールが不達になる)。DKIMの長い値は末尾まで比べる
  4. レジストラの管理画面でネームサーバーをCloudflare指定の2つに変更。旧DNSのレコードは消さない(戻すときに使う)
  5. DigでNSがCloudflareになり、他の値が今までと同じであることを確認
  6. 社外→社内、社内→社外のメールを送り、SPF・DKIM・DMARCがPASSすることを確認。お問い合わせフォームも本番でテスト
  7. メールとサイトに異常が無いことを確かめてから段階3へ。慎重に進めるなら、ここで48時間ほど様子を見る(当社は確認を終えた時点で続けて段階3へ進んだ)

.jpドメインのネームサーバー情報は最大で約1日キャッシュされるため、切り替えも切り戻しも、全員に行き渡るまで時間がかかる前提で計画します。作業は、切り替え後もしばらく対応できる時間帯に行うのが安全です。

段階 3サイトを切り替える(戻すのも1行)

  1. 切り替え前に、今のAレコードの値を控えておく(戻すとき用)
  2. Cloudflare Pagesの「カスタムドメイン」でドメインをつなぐ。画面の案内に従い、旧サーバー向けのAレコードをPages向けの記録に差し替える。www付きも同じようにつなぎ、wwwなしへ301で転送
  3. MXやTXTなど、メール関係のレコードには触らない
  4. 証明書の発行を待ち(数分〜15分)、本番で全ページ・フォーム・アクセス解析・メールを確認。応答ヘッダーが Cloudflare から返っているかも見る
  5. 「常に HTTPS を使用」をオン、TLSの最低バージョンを1.2に

段階 4後片付け

  • 当日中に旧サーバーのWordPressを止める。DNSを切り替えても、IPアドレスを直接指定すれば旧サーバーには届きます。止めない限り、古いPHPのWordPressは攻撃され続けます。解約までの間も、公開フォルダへの外部アクセスをすべて拒否する設定を入れておきましょう
  • テストのために一時追加した許可設定(フォームのボット対策、送信元の許可など)を外す
  • 旧サーバーの解約は後日、別途行う(当社も解約はこれから)。直前にもう一度バックアップを取り、メールで使っていないことを再確認
  • 余裕があれば、Cloudflare側でDNSSECを有効にする

起こりうる事故と戻し方

事故主な原因戻し方/防ぎ方
メールが届かないMX・SPF・DKIMの写し漏れ・写し間違いネームサーバーを元に戻す。棚卸し表との照合で事前に防ぐ
サイトもメールも引けないDNSSECが有効なままネームサーバーを変更ネームサーバーを戻す。段階0で無効を確認
証明書エラー証明書の発行待ち待つ。15分を超えたらAレコードを戻す
一部のページが404静的コピーの取りこぼし・転送漏れ_redirects に足して再公開
お問い合わせが送れないボット対策の対象ドメイン、送信先の許可設定設定に追加(数分)
旧WordPressが狙われ続ける旧サーバーで動いたまま切り替え当日に停止

SEOへの影響と対策

サーバー移転そのものは、URLと内容が変わらなければ検索順位にほぼ影響しません。順位を落とすのは、ページが消える(404)ことと、転送の設定ミスです。当社では次の5つを徹底しました。

WordPressから静的サイトへの移行でSEOを落とさない5つの対策
  1. URLを変えない。過去のお知らせも含め、全ページを同じURLの静的なコピーで残す。外部からのリンクもブックマークもそのまま生きます。
  2. 消すページは必ず301で転送する。サンプルページや不要になったページは、内容が近いページへ「恒久的な移動」として転送。転送を設定してから消す、の順番を守ります。
  3. サイトマップを作り直す。WordPressが自動で出していたサイトマップは静的サイトでは生成されないため、新しい sitemap.xml を置き、旧サイトマップのURLは新しい方へ転送。Search Consoleで新しいサイトマップを送信し、古い方を削除します。
  4. 所有権の確認方法を確かめる。Search Consoleの確認がDNSのTXTならそのまま有効。HTMLファイルやタグで確認していた場合は、新サイトにも同じものを置く必要があります。
  5. 正規URLをそろえる。wwwあり/なし、http/httpsをどれか1つに統一し、他は301で転送。各ページのcanonicalも同じURLを指すようにします。

移行後2週間は、Search Consoleの「ページ」レポートで404やリダイレクトエラーが増えていないかを見続けます。

なお、静的サイトをCDNから配信すると、PHPで毎回ページを組み立てるより表示は速くなりやすく、表示速度の指標(Core Web Vitals)にはプラスに働きます。ただし、順位を上げる施策というより、「落とさない」ための移行と捉えるのが妥当です。

自社で同じことをやるためのチェックリスト

判断の前に

  • 自社サイトのPHPとWordPressのバージョン、サポート期限を確認した
  • サーバー側で動く必要がある機能(フォーム、会員、EC、検索)を洗い出した
  • 管理画面から更新している人と頻度を確認した

移行の前に

  • 公開中のURLを全件リストにした
  • サイト一式とデータベースをバックアップした
  • DNSレコードを全件、実際に引いて棚卸し表にした(特にMX・SPF・DKIM・DMARC)
  • DNSSECが無効であることを確認した
  • ドメインの有効期限と自動更新を確認した
  • 新サイトを仮のURLで全件確認し、404が無い

切り替え当日とその後

  • DNSの移転後、メールとサイトの動作を確かめてからサイトを切り替えた(慎重に進めるなら48時間空ける)
  • メールの送受信とお問い合わせフォームを本番でテストした
  • 旧サーバーのWordPressを当日中に止めた
  • Search Consoleに新しいサイトマップを送信した
  • 旧サーバーを解約する前に、メールで使っていないことを再確認した

脆弱性情報の点検やサイト運用の見直しを、生成AIで回したい方へ

「どのシステムが、どの版の部品を使っているか」を一覧にし、新しい脆弱性の情報と照らし合わせる。今回のような移行の判断と段取りも含めて、カトルセのAI顧問がご支援します。

よくある質問(FAQ)

静的サイトにすると、お知らせの更新はどうするのですか?
当社ではClaudeに「この内容でお知らせを追加して」と依頼し、仮のURLで確認してから公開しています。非エンジニアが頻繁に更新する場合は、ヘッドレスCMSとの組み合わせも検討の余地があります。
お問い合わせフォームは静的サイトで動きますか?
動きます。フォームの送信先を外部のシステム(フォームサービス、CRM、サーバーレス関数など)にすれば、ページ自体は静的なままで構いません。移行時は、ボット対策の対象ドメインと送信元の許可設定を忘れずに確認します。
ドメインもCloudflareに移管すべきですか?
必須ではありません。当社は契約はそのままにして、ネームサーバーだけを移しました。変えるものを減らすほど、事故の原因も減ります。
作業中にサイトが止まる時間はありますか?
DNSの移転では止まりません。サイトの切り替えでは、レコードの差し替えと証明書の発行の間、数分程度表示できないことがあります。問い合わせの少ない時間帯を選びましょう。
移行にはどれくらい時間がかかりましたか?
当社は、棚卸しから本番の切り替えまでを約2時間で終えました。静的化やURLの突き合わせなど、手間のかかる作業をClaudeに任せたことが大きいです。旧サーバーの解約は、後日別途行います。

まとめ

脆弱性への対応は「パッチを当てる」だけではありません。使っていない機能のために攻撃される部品を持ち続けているなら、その部品をなくすのが最も確実で、維持費も下がります。生成AIのおかげで、こうした移行は中小企業でも社内だけで現実的な工数で行えるようになりました。

カトルセでは、今回のような生成AIを使った業務の進め方を、自社で実践しながら発信しています。

関連記事

※本記事は2026年10月22日時点の当社の作業記録と、各サービスの公開情報に基づきます。画面の名前や料金・上限は各社の変更で変わることがあるため、最新の情報は公式の発表で確認してください。

SHARE /
X f L
AUTHOR / 執筆者

この記事の執筆者

K.H

橋本 健太郎

株式会社カトルセ 代表取締役

生成AI研修・AI開発・AI顧問・PM/PMO支援を提供。累計2,000名以上のAI研修を支援し、大手企業の生成AI活用、ローカルLLM/RAG/AIエージェント導入、業務改善プロジェクトに携わる。実務に直結する「使えるAI活用」を一貫して伝えている。