皆さん、こんばんは!
週末は雨のところが多く肌寒かったのですが、相変わらず季節感の無い半袖で行動しているポンコツです。
さて、先日は「情報漏洩」について書かせていただいたところ、
やはり某国のAIが悪さをしているというニュースに続き、
「PHP」の脆弱性というどえらいニュースが耳に入ってきました。
今日は私も緊急で対応したこちらの件について書かせていただきたいと思います。
2026年10月、PHP本体に深刻なリモートコード実行(RCE)の脆弱性が公表されました。
今回話題になったのは「PHP2Shell」と呼ばれる脆弱性です。
RCE(Remote Code Execution)とは、攻撃者が遠隔から対象システム上で任意のコードを実行できてしまう脆弱性です。
Webアプリケーションにおいて、任意コード実行は非常に深刻な問題です。
Webサーバー上で攻撃者のコードが実行されれば、設定や実行権限によっては、
機密情報の窃取、データの改ざん、マルウェアの設置などにつながる可能性があります。
今回の問題で注目したいのは、アプリケーション側で入力チェックや認証処理を厳密に実装していても、
それだけでは防ぎきれない可能性があるという点です。
普段、Webアプリケーションを開発していると、SQLインジェクションやXSS、認可漏れといったアプリケーション層の脆弱性に意識が向きがちです。
しかし、PHPのような実行基盤そのものに問題があれば、アプリケーションの防御より手前で攻撃が成立する可能性があります。
今回は、PHP本体の脆弱性がなぜ深刻なのか、そして運用する側は何を確認すべきなのかを整理します。
1. そもそもRCEが危険な理由
RCEとは、Remote Code Executionの略です。
簡単に言えば、攻撃者が遠隔から対象システム上で任意のコードを実行できてしまう状態です。
Webアプリケーションを攻撃する場合、一般的には次のような流れを想像すると思います。
- 脆弱なエンドポイントを探す
- 入力値を細工する
- SQLインジェクションやコマンドインジェクションなどを成立させる
- アプリケーションの権限で不正な処理を実行する
しかし、今回のようにPHP本体の内部処理に問題がある場合、アプリケーションが想定している処理フローを経由せずに、攻撃が成立する可能性があります。
PHP公式が示す影響範囲や攻撃条件によっては、アプリケーションコードが実行される前の段階で問題が発生することも考えられます。
つまり、LaravelやSymfonyでバリデーションを厳密に実装しているからといって、それだけで安全とは言い切れません。
フレームワークの外側にある実行基盤にも、当然ながら脆弱性は存在します。
2. メモリ不足処理の問題
PHPには、スクリプトが使用できるメモリ量を制限する memory_limit という設定があります。
例えば、次のような設定です。
memory_limit = 128M
これは、PHPスクリプトが使用できるメモリ量に上限を設けるための設定です。
無制限にメモリを消費する処理が実行された場合でも、メモリ使用量を制限するための仕組みの一つです。
ただし、メモリ制限を設定していれば、メモリ関連の問題をすべて防げるわけではありません。
重要なのは、メモリ不足が発生したときに、PHP内部でどのような処理が行われるかという点です。
例えば、処理の途中でメモリ不足が発生した場合、通常の処理を中断し、エラー処理や後始末に移る必要があります。
このとき、内部データの初期化が完了していなかったり、解放処理が想定外の状態で実行されたりすると、メモリの不正な操作につながる可能性があります。
メモリ不足への対策とメモリ安全性は別の問題
ここで押さえておきたいのは、メモリ不足を防ぐことと、メモリ不足が発生したときの処理を安全にすることは別の問題だということです。
memory_limit を設定していても、エラー発生時の内部処理に問題があれば、脆弱性の影響を受ける可能性があります。
これはPHPに限らず、CやC++などで実装されたネイティブコードを含むソフトウェア全般に通じる話です。
通常時に正しく動作することと、異常時にも安全に動作することは同じではありません。
3. リクエスト処理と内部状態の管理
もう一つ、Webサーバーの運用で重要なのが、リクエストごとの内部状態の管理です。
PHP-FPMなどの構成では、ワーカーが複数のリクエストを順番に処理します。
ここで重要なのは、リクエストが終了したからといって、ワーカープロセスそのものが毎回終了するわけではないという点です。
概念的には、次のような流れになります。
PHP-FPM Worker
|
+-- Request A
| |
| +-- 内部状態を初期化
| +-- リクエストを処理
| +-- 処理終了
|
+-- Request B
|
+-- 次のリクエストを処理
通常であれば、リクエストごとの内部状態は適切に初期化され、前のリクエストの情報が次のリクエストに影響しないように管理されます。
しかし、内部状態が適切にリセットされなかったり、解放済みのメモリを参照したりする問題があれば、想定外の挙動につながる可能性があります。
こうした問題は、一般にメモリ管理や状態管理に関する脆弱性として扱われます。
ただし、個々のCVEの原因や攻撃条件は異なるため、具体的な脆弱性については公式アドバイザリで確認する必要があります。
なぜワーカーの再利用が重要なのか
ワーカーを再利用すること自体は、パフォーマンス上の合理的な設計です。
リクエストごとにプロセスを起動・終了するよりも、既存のワーカーを再利用する方が効率的な場合があります。
一方で、再利用する以上、リクエストごとの状態を確実に初期化しなければなりません。
これはWebアプリケーションにおけるセッションやキャッシュの管理にも通じる話です。
前の処理の状態が残ってしまうと、情報漏えいや権限判定の誤りにつながることがあります。
もちろん、アプリケーションのセッション管理とPHP内部のメモリ管理は別の仕組みです。
しかし、状態のライフサイクルを正しく管理することが重要である点は共通しています。
4. なぜアプリケーション側の対策だけでは不十分なのか
例えば、Laravelで以下のような対策を実施していたとします。
- FormRequestによるバリデーション
- CSRF対策
- 認証・認可の実装
- SQLのプレースホルダー利用
- XSS対策としての適切なエスケープ
- アップロードファイルの形式やサイズの検証
これらは、もちろん重要です。
しかし、PHP本体のリクエスト解析など、アプリケーションコードが実行される前の処理で脆弱性が発生する場合、上記の対策が呼び出される前に問題が発生する可能性があります。
つまり、セキュリティ対策には複数の階層があります。
[インターネット]
|
v
[ネットワーク・リバースプロキシ]
|
v
[Webサーバー]
|
v
[PHPランタイム]
|
v
[フレームワーク]
|
v
[アプリケーションロジック]
|
v
[データベース・外部サービス]
アプリケーションの入力値を検証することは、フレームワークやアプリケーションの層を守るうえで重要です。
しかし、PHPランタイム自体に問題がある場合は、ランタイムを修正する必要があります。
WAFを導入している、Laravelを使っている、認証を厳格にしている。
そのような対策があっても、PHP本体のアップデートが不要になるわけではありません。
5. 自分の環境が影響を受けるか確認する
脆弱性が公表された際、最初に行うべきなのは、自分の環境が影響を受けるかを確認することです。
まず、CLI版PHPのバージョンを確認します。
php -v
ただし、このコマンドで確認できるのは、基本的にはコマンドライン版のPHPです。
Webサーバーが実際に使用しているPHPと一致しているとは限りません。
例えば、CLIではPHP 8.4を使用していても、ApacheやPHP-FPMでは別のバージョンが稼働しているケースがあります。
そのため、以下の点を確認する必要があります。
- CLI版PHPのバージョン
- PHP-FPMの実行バージョン
- Apacheの
mod_phpの有無 -
php-cgiなど別の実行方式の有無 - Dockerイメージに含まれるPHPのバージョン
- 本番環境と検証環境の差異
- OSやパッケージ管理システムによる修正の適用状況
Dockerを使用している場合は、例えば次のように確認できます。
docker image ls
docker ps
実際に稼働しているコンテナや、そのコンテナで使用しているイメージを確認したうえで、コンテナ内のPHPバージョンも確認します。
docker exec <container_name> php -v
上記は確認の一例です。コンテナ名や実行環境に応じて読み替えてください。
バージョン番号だけで判断しない
ここで注意したいのは、バージョン番号だけを見て判断しないことです。
OSやディストリビューションによっては、独自に修正をバックポートしている場合があります。
そのため、単純に上流のPHPバージョンだけを見るのではなく、利用しているOSやパッケージのセキュリティ情報も確認する必要があります。
反対に、パッケージを更新したつもりでも、実際にWebサーバーが使用しているPHPが更新されていなければ、問題が残る可能性があります。
6. アップデートはバージョン確認だけで終わらせない
修正版をインストールしたら、それで終わりではありません。
実際に稼働しているプロセスが修正版を使用しているかも確認する必要があります。
例えば、パッケージを更新しても、古いワーカーが動作し続けていれば、期待した状態になっていない可能性があります。
アップデート後は、利用している構成に応じてPHP-FPMやWebサーバーなどの再起動・再読み込みを実施し、稼働プロセスと実行バージョンを確認することが重要です。
また、本番環境では、アップデート前に依存ライブラリとの互換性やアプリケーションの動作確認方法も整理しておくべきです。
緊急の脆弱性対応だからといって、無計画に本番環境を変更するのではなく、影響範囲を把握したうえで確実に修正を適用することが重要です。
7. すぐにアップデートできない場合はどうするか
現実のシステムでは、すぐにアップデートできないこともあります。
例えば、次のような事情です。
- 古いPHPに依存したアプリケーションが存在する
- フレームワークやライブラリの互換性に問題がある
- 本番環境の停止時間を確保できない
- 保守担当者が不在である
- ベンダーのサポート待ちである
しかし、アップデートできないことと、何もしなくてよいことは別です。
まずは、対象システムのインターネット公開状況、実際のPHP実行方式、重要なデータへのアクセス権限などを確認します。
そのうえで、修正が完了するまでの暫定対応として、アクセス制限や公開範囲の縮小、必要に応じたサービスの一時停止を検討します。
ただし、暫定対応は修正版へのアップデートの代わりにはなりません。
WAFやアクセス制限によって特定の攻撃経路を抑えられる場合はありますが、それだけでPHP本体の脆弱性が解消されるわけではありません。
また、通常のセキュリティ更新が提供されない古いPHPを使用している場合は、保守ベンダーによる修正の有無を確認し、サポート対象のバージョンへの移行も検討する必要があります。
8. 今回の脆弱性から考えるべきこと
今回の件で重要なのは、単に「PHPをアップデートしましょう」という話だけではないと思います。
根本的な問題は、利用している実行基盤の状態を把握できているかどうかです。
PHPを利用したWebサービスを運用している場合、アプリケーションのソースコードだけを管理していても不十分です。
OS、Webサーバー、PHPランタイム、拡張モジュール、コンテナイメージ、依存ライブラリ。
これらを含めて、どのバージョンがどこで稼働しているのかを把握できていなければ、緊急の脆弱性が公表されたときに影響範囲を調査することすら難しくなります。
また、古いシステムを維持する場合、アップデートに必要な知識や資料、担当者、予算が失われていないかも重要です。
脆弱性対応は、エンジニアがパッチを適用すれば完了する作業ではありません。
継続的に更新できる仕組みと、それを実施するための体制が必要です。
まとめ
PHP本体の脆弱性は、アプリケーション側の対策だけでは防ぎきれない場合があります。
今回のような問題から、改めて重要だと感じるのは以下の点です。
- PHP本体の脆弱性は、アプリケーションコードの修正だけでは解決できない場合がある
- メモリ不足や内部状態の初期化といった低レイヤーの問題が、深刻な脆弱性につながることがある
- CLI版とWebサーバー側のPHPが異なる可能性があるため、実際の稼働環境を確認する必要がある
- DockerやCMS、マネージド環境など、PHPを内部で利用しているシステムも確認対象になる
- 修正版への更新を優先し、難しい場合は暫定対策と移行計画を検討する
アプリケーションのセキュリティを考える際、ソースコードのレビューやフレームワークの設定だけに目を向けるのではなく、そのコードを動かしている実行基盤まで含めて考えることが重要です。
そして、脆弱性が公表されたときに迅速に対応できるかどうかは、平常時にどれだけシステムを把握し、保守できる状態にしているかで決まります。
こうした機会に、自分が管理しているPHP環境のバージョンと更新体制を見直してみてはいかがでしょうか。
最後に、脆弱性対策もきっちり実施済みのIT求人サービスは以下になります。
企業の方も、エンジニアの方も、ぜひ使ってみてくださいね!
▼求人マッチングサービス【ヴェテラン】
https://veteran-work.com/

「脆弱性ってどうやって検知するの?」
「だから!F〇NZAの情報漏洩は大丈夫なのって聞いてるんだよ!?」
など質問やご意見いただけますとパッチあてながら喜びます!
本日もお疲れ様でした。
明日も一日頑張りましょう。
