
PHPの重大な脆弱性「PHP2Shell」を狙う攻撃を検証、公開サーバーがHTTP500エラーを44回返した原因はメモリ不足だった
正常に表示できていたPHPのページが、攻撃POSTを受けてHTTP500を返した。エラーログには「Allowed memory size of 134217728 bytes exhausted」。我々が観測用に公開しているPHPサーバーで、設定した128MiBのメモリ上限に達し、リクエストの処理が止まった。
前回は、PHPの重大な脆弱性群「PHP2Shell」を狙うPOSTから、サーバーを他の相手への攻撃に使うプログラムの取得命令を見つけた。その後も観測を続けると、10月24日と26日にはメモリ不足が繰り返し発生した。今回は、実際に処理が失敗した場面をログと通信本文から追う。時刻は断りがない限り2026年の日本時間で記す。
正常だったページが、POSTの直後にHTTP500を返した
10月24日8時19分59秒、/index.phpへのGETにはHTTP200が返っていた。続いて同じ送信元からクエリ付きのPOSTが届き、8時20分02秒にメモリ不足の致命的エラーとHTTP500が記録された。
2026-10-24 08:19:59 GET /index.php → 200
2026-10-24 08:20:02 POST /index.php?... → 500
※時刻はログ出力時刻。POSTの受付時刻は08:20:01。[23-Oct-2026 23:20:02 UTC] PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 12288 bytes) in Unknown on line 0134,217,728バイトは128MiB。さらに12,288バイトを確保しようとして失敗している。この12,288バイトは、PHPが追加で確保しようとした量だ。送られてきたPOSTのサイズを示す値ではない。
メモリ不足は3つの時間帯に、計44件起きた
10月23日17時39分から26日10時07分までの回収ログで、PHPのメモリ不足は44件あった。すべて修正前のPHP8.3.35で発生し、各時間帯のアクセスログにも合計44件のHTTP500が残っていた。
止まったのは、そのPOSTを処理していたPHPの処理だ。最後のエラーの後、10月26日2時21分33秒には、別のPOSTにHTTP200と通常ページが返っている。今回、実際に確認できた影響は、メモリ不足による処理の中断とHTTP500の応答だ。
| 公開していた環境 | 回収ログで確認した結果 |
|---|---|
| PHP8.3.35(修正前) | メモリ不足44件。同じ時間帯にHTTP500が44件 |
| PHP8.3.36(修正を含む) | 同じ集計期間にメモリ不足の記録なし |
2台は別のIPで公開している。攻撃者から同じ本文・同じ回数が届いた条件ではないため、この件数だけで修正の効果を比較することはできない。修正前後に同じ入力を与えた検証は、PHP2Shellの検証記事に掲載している。
POSTの中には、空のファイル項目と深い入れ子があった
10月26日2時17分台の保存パケットを読むと、POSTはmultipart/form-dataだった。multipartは、フォームの項目やファイルを境界で区切って送る形式だ。通信本文には、ファイル名が空の項目や、角括弧で何段も入れ子になった項目名、長いヘッダーが並んでいた。
POST /index.php?... HTTP/1.1
Content-Type: multipart/form-data; boundary=[省略]
Transfer-Encoding: chunked
Connection: close本文を分割して送るTransfer-Encoding: chunkedが使われ、この要求のヘッダーにContent-Lengthはなかった。受信データの量に加え、PHPが項目やヘッダーを内部で展開するときのメモリ消費が問題になる。
PHPの公式勧告は、multipartの多数のヘッダー、空のファイル項目、入れ子の項目名などによって、見かけの入力制限内でもメモリ不足に到達し得ると説明している。今回の本文にもこれらの特徴があり、PHP2Shellを狙った攻撃とみられる。
メモリ不足が、なぜコード実行につながるのか
PHP2Shellのうち、今回の本文と関係するのがメモリ不足時の処理の脆弱性だ。公式勧告によると、修正前のPHPでは、メモリ不足で処理を途中終了した際に、不完全な状態のデータが残る場合がある。続く終了処理がそれを参照すると、攻撃者のコード実行につながり得る。
我々の環境はApacheにPHPを組み込んで動かすmod_phpで、公式が説明する影響対象の構成だった。アプリケーションのコードが動き始める前の、POST本文の解析でも問題が起き得る。
- 今回、メモリ不足による処理の失敗は起きた。 PHPの致命的エラーとHTTP500が記録された。
- 不正な外部コマンドが実行された形跡はなかった。 対象期間のOS監査ログには、攻撃に対応する実行記録は残っていない。
メモリ上限を設定していても、更新が必要だ
今回のサーバーには、PHPのメモリ上限128MiBとPOSTの上限8MiBを設定していた。それでも、公開先に届いたPOSTでメモリ不足が発生した。入力の量と、その入力を処理するためのメモリ量は一致しない。
PHPの公式勧告は、この脆弱性への完全な対処として、修正を含むPHPへの更新を求めている。修正を初めて含むのは8.2.35、8.3.36、8.4.27、8.5.12だ。運用環境では、利用中の系列で修正を含むリリースへ更新する。
POST本文のサイズやmultipartの項目数・ヘッダー数を入口で制限することも、負荷を抑える助けになる。今回のようにPHPの処理が失敗しているかは、HTTP500の発生時刻とPHPのエラーログを照合すると追いやすい。
自社システムの脆弱性対応やセキュリティ対策について、お気軽にご相談ください。
