PHP extract() の脆弱性 CVE-N/A が FIX:レガシー関数の危険性と現代のエコシステム

Critical Flaw in PHP’s extract() Function Enables Arbitrary Code Execution

2025/04/17 gbhackers — PHP の extract() 関数に、深刻な脆弱性が発見された。この脆弱性の悪用に成功した攻撃者は、メモリ破損を引き起こし、任意のコード実行を達成するという。この問題は、PHP のバージョン 5.x/7.x/8.x に影響を及ぼす。攻撃者により、PHP 5.x では二重解放が、PHP 7.x/8.x では解放後メモリ使用が引き起こされ、最終的にはリモート・コード実行 (RCE) にいたるという。

技術的な詳細

この脆弱性は、extract() 関数の EXTR_REFS フラグの不適切な処理に起因すると、SSD はレポートしている。この処理は、変数を参照してシンボル・テーブルにインポートするものである。

既存の変数を上書きする際に、この関数は zval_ptr_dtor を呼び出し、オリジナルの値を破壊する。したがって、オリジナルの変数がオブジェクトの場合には、その “__destruct” メソッドが破棄の途中で呼び出されるため、攻撃者は入力を細工することで、ヒープを操作できるようになる。

// Example triggering the vulnerability

$malicious_array = ['var' => new ExploitableClass()];

extract($malicious_array, EXTR_REFS);

このプロセスにおいて、オブジェクトのデストラクタが同じ変数を解放すると、PHP の内部関数 “zval_ptr_dtor” は、メモリを繰り返して解放し、ヒープを破壊する。

PHP 5.x では、この処理により二重解放が発生するが、PHP 7.x/8.x では、メモリ管理の変更により解放後メモリ使用の問題が発生する。

FieldDetails
VulnerabilityCritical flaw in PHP’s extract() function allows arbitrary code execution
Affected VersionsPHP 5.x (double-free), PHP 7.x & 8.x (use-after-free)
Root CauseImproper memory management when using extract() with EXTR_REFS flag, especially during object destruction
Trigger ConditionAn object’s __destruct method unsets a variable during an ongoing zval_ptr_dtor call in extract()
Vulnerability TypeDouble-free (PHP 5.x), Use-after-free (PHP 7.x, 8.x)
ImpactHeap corruption, arbitrary read/write, and remote/native code execution
悪用による影響

個の脆弱性を悪用する攻撃者は、以下のアクションを引き起こす可能性を手にする:

  • 重要なメモリ構造の上書き: 例として挙げられるのは、PHP の HashTable オブジェクトや zval オブジェクトである。
  • ヒープ割り当てを操作した、Read/Write プリミティブを取得による、任意のネイティブ・コードを実行。
  • PHP の内部関数ハンドラを乗っ取りによる、disable_functions などのセキュリティ・メカニズムの回避。

PoC エクスプロイトが示すのは、これらのプリミティブを連鎖させ、RCE を実現する方法である。たとえば、”system()” などの無効化された関数のハンドラを、正当なアドレスで上書きすると、実行機能が復元される。

すでに PHP チームは、GitHub アドバイザリ GHSA-4pwq-3fv3-gm94 で、この問題にパッチを適用している。したがって、管理者は以下の対応を行う必要がある。

  1. PHP のバージョンを、最新のものへと速やかに更新する。
  2. 安全が確保されないで “extract()” の使用について、特にユーザーが制御するデータ (例:extract($_POST)) の使用について、コードを監査する。
  3. “extract()” を、明示的な変数割り当てに置き換える。もしくは、EXTR_PREFIX_ALL などのフラグを使用して変数を分離する。

この脆弱性が浮き彫りにするのは、長年にわたり PHP の “extract()” に存在してきたリスクである。この関数は、数十年にわたり、悪用されやすいことが指摘されていた。過去の事例には、次のようなバックドアもある。

@extract($_REQUEST);

@die($ctime($atime)); // Allows $_REQUEST['ctime']('command') execution [4]

開発者に対して強く推奨されるのは、ユーザー入力における “extract()” の使用を完全に排除し、安全なコーディング手法を採用することだ。”extract()” の脆弱性が浮き彫りにするのは、現代のエコシステムにおけるレガシー関数の危険性である。

すでにパッチが提供されているが、このようなリスクを軽減するためには、積極的なコード・レビューと依存関係の更新が重要となる。

PHP を使用する組織にとって必要なことは、アップグレードと安全が確保されないパターンの排除を優先し、悪用の可能性を防ぐことだ。

PHP に深刻な RCE 脆弱性が発見されました。CVE 未採番ですが、すでに PoC が提供されています。開発者の皆さんは、十分にご注意ください。なお、PHP の直近の脆弱性は2025/03/17 の「PHP に存在する5つの深刻な脆弱性が FIX」となります。よろしければ、PHP で検索と併せて、ご参照ください。