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 では、メモリ管理の変更により解放後メモリ使用の問題が発生する。
| Field | Details |
| Vulnerability | Critical flaw in PHP’s extract() function allows arbitrary code execution |
| Affected Versions | PHP 5.x (double-free), PHP 7.x & 8.x (use-after-free) |
| Root Cause | Improper memory management when using extract() with EXTR_REFS flag, especially during object destruction |
| Trigger Condition | An object’s __destruct method unsets a variable during an ongoing zval_ptr_dtor call in extract() |
| Vulnerability Type | Double-free (PHP 5.x), Use-after-free (PHP 7.x, 8.x) |
| Impact | Heap 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 で、この問題にパッチを適用している。したがって、管理者は以下の対応を行う必要がある。
- PHP のバージョンを、最新のものへと速やかに更新する。
- 安全が確保されないで “extract()” の使用について、特にユーザーが制御するデータ (例:extract($_POST)) の使用について、コードを監査する。
- “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 で検索と併せて、ご参照ください。
You must be logged in to post a comment.