PHP 5・PHP 7 のサイト|アップグレードとセキュリティ修正

古いPHPサイトのアップグレード。長年潜んでいた脆弱性もまとめて直します

PHP 7以前のバージョンは、公式のセキュリティ修正がとうに終わっています。Arz(阿茲)と申します。最近、長く動いてきた3つのサイトをPHP 8へ移す作業をしています。サーバーに入ってみると、どのサイトでも「バージョンが古い」より急ぐべき問題が見つかりました。1年以上前にバックドアを仕掛けられていたサイトもあれば、決済画面で項目を1つ書き換えるだけで注文金額を変えられるサイトもありました。

技術の知識は不要です。URLと、どのホスティング会社を使っているかを sharefood@gmail.com までお送りいただければ、そこから相談を始められます。

こんな状況なら、対応の時期です

  • ホスティング会社から「PHP 7を停止する」と連絡が来た。または旧バージョンの継続に追加料金を求められた
  • 何年も前に外注で作ったサイトで、当時の制作会社とはもう連絡がつかない
  • 管理画面の一部が、保存すると真っ白になる。それ以来だれも触っていない
  • 独自開発か、かなり古いフレームワークで作られている。WordPressではないので引き受け手が見つからない
  • 侵入されたことがあるのか分からない。サーバーの中をだれも調べたことがない
  • テスト用ファイル、バックアップファイル、phpMyAdminが本番サイトに置かれたままになっている
PHP各バージョンの公式セキュリティ修正の期限
バージョンセキュリティ修正
PHP 5.62018年12月に終了
PHP 7.02019年1月に終了
PHP 7.22020年11月に終了
PHP 7.42022年11月に終了
PHP 8.12025年12月に終了
PHP 8.42028年12月まで

出典:php.net のサポート対象バージョンとサポート終了バージョン一覧。

3つのサイトで、サーバーに入って実際に見つかったこと

いずれも最近担当したサイトです。顧客名とURLは伏せています。それ以外は当時の評価報告書と修正記録に基づいており、数字もそのまま載せています。

農産物のオンラインショップ

  • PHP 7.2 → 8.3
  • 本番切り替え済み
見つかったこと
  • 決済時に項目を1つ追加して送ると、注文金額を任意の数字に変えられた
  • 管理画面の複数のページで、URLパラメータにSQLインジェクションの脆弱性があった
  • アカウント管理ページはメニューから隠してあるだけで、スタッフならだれでもURLを直接開いて管理者を追加できた
  • テスト用フォルダに外部ログイン連携の鍵ファイルが残っており、外部からダウンロードできた
対応
決済は、許可リストにある項目だけを受け付けるよう変更しました。URLパラメータは整数に変換し、権限はサーバー側で確認するようにしました。テスト用ファイルとバックアップファイルはすべて削除し、鍵の再発行は引き継ぎ事項としてオーナーに依頼しました。
確認方法
公開側はスクリプトで439ページを巡回しました。管理画面は58ページを確認し、11のモジュールを1つずつ保存しました。さらに金額を偽装した注文を実際に送信し、偽装した値が無視されて正しい金額になることを確かめました。

ツアー予約サイト

  • PHP 7.0 → 8.4
  • 新サーバーでの検証完了
見つかったこと
  • OS、PHP、データベースのすべてがサポート終了で、同じサーバー上でのアップグレードはできなかった
  • サーバーに1年以上前のスキャン記録が残っており、当時、難読化されたバックドアファイルが置かれていたことが分かった
  • 管理画面のコードの一部が、任意のコマンド実行に悪用できる状態だった
  • 提携先向け管理画面のファイルアップロード機能が、ログインなしで使えた
  • 決済の入金通知で署名を検証しておらず、「支払い済み」を偽装できた
対応
旧サイトを丸ごとコピーすることはせず、クリーンなコードを新サーバーに配置し直しました。アップロード機能にログイン確認を追加し、アップロード用フォルダではスクリプトを実行できないようにしました。メール送信ライブラリは修正済みのバージョンに入れ替え、入金通知には署名検証を追加しました。
確認方法
クレジットカード、ATM振込、窓口払いの3つの支払い方法を、決済会社のテスト環境でそれぞれ最後まで通しました。偽装した入金通知は拒否され、注文の状態は変わりませんでした。アップロード済みの3,499ファイルは、旧サーバーと1件ずつ照合して一致を確認しています。

ブランド公式サイト

  • PHP 7.1
  • インシデント調査とアップグレード評価
見つかったこと
  • きっかけは「サーバーを乗っ取られた疑いがある」という通報。ログインして調べ、バックドア(webshell)がアップロードされていることを確認した
  • OS、PHP、データベースはいずれもベンダーのサポート期間を過ぎていた
実施したこと
まず完全バックアップを取り、ファイルが壊れていないことを検証しました。続いてPHPファイル4,823個、約39万行を調べ、アップグレード後に確実に動かなくなる記述を143か所特定して、評価報告書にまとめました。
提案
2本立てで進めます。アップロードの脆弱性はアプリケーション側の問題なので、今の環境のまま先に塞げます。プラットフォームの移行は大きな作業なので、別に日程を組みます。移行を待つために修正を後回しにするべきではありません。

作業の進め方

  1. サーバーに入って現状を見る

    アンケートから推測することはしません。実際に動いているバージョン、入っているソフト、不審なファイルの有無を調べ、工数の見積もりを添えた評価報告書にまとめます。

  2. テスト環境で修正する

    本番サイトには手を付けません。コードはバージョン管理に入れ、修正はまとまりごとに記録します。いつ何を変えたかを後から確認できます。

  3. 1ページずつ検証する

    公開側はスクリプトで全ページを巡回します。管理画面は各モジュールで保存と削除を試します。決済機能がある場合は、テスト環境で支払いの流れを最後まで通します。

  4. 本番に切り替える

    切り替え前に本番サイトを完全にバックアップします。切り替え後はもう一度全体を巡回し、テスト環境の結果と比べます。

  5. 引き継ぐ

    変えたこと、変えていないこと、お客様の判断やホスティング会社の協力が必要なことを、文書にしてお渡しします。終わっていない項目も省かずに書きます。

修正記録より抜粋(顧客情報は削除済み)
  • ショートタグ <? → <?php:57ファイル255か所
  • 管理メニューページの eval() を許可リスト方式の変数に変更(RCEの原因だった)
  • PHPMailer 5.2.6 → 6.12.0(CVE-2016-10033 ほか)
  • 決済:foreach($_POST) で変数に展開する処理を削除し、許可リストの項目のみに変更
  • 管理画面の id 系パラメータを int に変換(SQLインジェクション複数)
  • CAPTCHAを random_int に変更し、誤答で無効化(以前は何度でも試せた)
  • アップロード用フォルダの .htaccess:スクリプト実行を禁止
  • 公開側439ページを巡回:販売終了商品と期限切れ文書を除きすべて200

AIに任せること、自分でやること

作業にはAIを使っています。隠すことではないと考えています。数万行の古いコードを読む速さは、AIのほうが人よりはるかに上です。ただ、AIの指摘が正しいかどうかは、テスト環境で1件ずつ試して初めて分かります。

AIに任せること

  • コード全体を読む
  • PHP 8で動かなくなる記述と不審なコードを洗い出す
  • 修正案を出す
  • 巡回用とテスト用のスクリプトを書く

自分でやること

  • 直すかどうか、どう直すかを決める
  • すべての修正をテスト環境で確認してから本番に出す
  • 先にお伝えすべきリスクを判断する
  • 結果に責任を持つ

自己紹介と、やらないこと

Arz(阿茲)です。台湾の造雨人科技でエンジニアをしています。システム開発に20年以上携わり、管理システム、決済連携、業務の自動化を手がけてきました。

セキュリティの専門家として経歴を積んできたわけではなく、セキュリティ関連の資格も持っていません。私の仕事は、古いコードを保守の続いているバージョンへ移し、その途中で見つかった穴を塞ぐことです。ペネトレーションテストの報告書、デジタルフォレンジック、コンプライアンス監査が必要な場合は、セキュリティ専門会社に依頼すべき内容ですので、その旨をはっきりお伝えします。WordPressも主な対応範囲ではありません。得意なのは独自開発のPHPサイトです。

Arzのシステム開発の経歴を見る(中国語)

よくある質問

古いPHPをそのままにしておくと、どうなりますか。

サポートが終了したバージョンでは、新しく見つかった脆弱性は修正されません。ホスティング会社も旧バージョンを順に停止していきます。サイトがすぐに動かなくなるわけではありませんが、問題が起きたときに適用できる修正がありません。実際には、古いサイトにはすでに別の問題があり、だれも調べていないだけということがよくあります。

アップグレードにはどのくらいかかりますか。

コードの量と、決済、会員機能、外部ログイン連携の有無で変わります。まずサーバーに入って評価を行い、報告書に工数の見積もりとその根拠を書きます。それを読んでから、進めるかどうかを決めてください。コードを見る前に出した日数は、たいてい当たりません。

作業中、サイトは停止しますか。

修正はすべてテスト環境で行うので、本番サイトはそのまま動き続けます。本番に触れるのは最後の切り替えだけです。切り替え前に完全バックアップを取り、日時も事前にご相談して決めます。切り替え後はサイト全体をもう一度巡回して確認します。

過去に侵入されたかどうかは、どうすれば分かりますか。

公開ページを見るだけでは、たいてい分かりません。サーバーに入り、不審なファイル、身に覚えのないアカウント、書き換えられた設定、残っている記録を調べる必要があります。このページで紹介した3つのサイトのうち2つで、過去にバックドアを仕掛けられた形跡が見つかりました。

料金はどのように決まりますか。

評価を先に行い、その後で見積もりを出します。評価では、コードの量、アップグレード後に動かなくなる箇所の数、検証が必要な機能の数を調べます。作業開始後に範囲外の問題が見つかった場合は、手を付ける前に確認を取ります。このページに固定料金は載せていません。

最初に何を伝えればよいですか。

サイトのURLと、ホスティング会社の名前だけで相談を始められます。サーバーへのログイン権限が必要になるのは、評価を行うと決めた後です。安全な受け渡し方法はそのときに決めます。メールでパスワード、認証コード、顧客データを送らないでください。

URLを送ってください

次の3つを sharefood@gmail.com までメールでお知らせください。サイトのURL、ホスティング会社、最近起きている問題です。内容を確認したうえで、対応する価値があるか、どの種類の問題と考えられるか、次に何をすればよいかをお返事します。パスワードと顧客データは、この段階では送らないでください。

メールでURLを送る