A newly disclosed vulnerability in PHP’s widely used extract() Function has put all major PHP versions—5.x, 7.x, and 8.x—at risk of severe security breaches, including arbitrary native code execution.
The flaw, discovered by independent security researcher LCFR and coordinated via SSD Secure Disclosure, affects the core memory management of PHP and can be exploited to gain full read/write access to the interpreter’s memory, enabling attackers to execute code at the native level.
Technical Overview
The vulnerability lies in how PHP’s extract()
function manages memory when importing variables from an array into the current symbol table, particularly when the EXTR_REFS
The flag is used.
This flag causes variables to be extracted as references, which in turn exposes a complex interaction between variable destruction, memory deallocation, and object destructors.
Vulnerable Code Path
In PHP 5.x, the relevant code is found in the PHP_FUNCTION(extract)
implementation:
cextract_refs = (extract_type & EXTR_REFS); // Set EXTR_REFS
...
if (extract_refs) {
// Path taken when EXTR_REFS is set
...
if (zend_hash_find(EG(active_symbol_table), Z_STRVAL(final_name), Z_STRLEN(final_name) + 1, (void ** ) & orig_var) == SUCCESS) {
zval_ptr_dtor(orig_var); // Attempt to remove and free the variable
*orig_var = *entry;
}
...
}
If the variable being extracted is an object, its __destruct()
the method may be called during this process.
If the destructor unsets the same variable, it triggers a double-free scenario: the memory for the same variable is freed twice, corrupting the heap and leading to exploitable conditions.
PHP 7.x and 8.x split the logic into helper functions, but the core issue remains.
The function php_extract_ref_overwrite() in PHP 8.x, for example, similarly attempts to destroy existing variables before replacing them, leading to a use-after-free or double-free if the object’s destructor interferes.
Exploitation Details
Attackers can craft PHP code that manipulates the heap allocator’s free list by overlapping allocations of different types (such as strings and arrays), gaining arbitrary read/write access to PHP’s memory.
By leveraging this, they can:
- Leak internal memory structures (e.g., HashTable and executor_globals)
- Calculate the addresses of critical structures like the function table
- Overwrite function pointers to hijack execution flow and run arbitrary code
A minimal proof-of-concept exploits the bug by defining a class with a destructor that unsets a global variable during extraction, causing the double-free:
phpclass GetFree {
public function __destruct() {
unset($GLOBALS["b"]);
}
}
$b = new GetFree();
$array = ["b" => "AB"];
extract($array, EXTR_REFS);
Vendor Response and Mitigation
Zend, the PHP vendor, has acknowledged the issue and released a security advisory.
However, their initial response downplayed the risk, stating, “We do not generally consider code that is specifically crafted to cause crashes security issues.”
Nevertheless, a patch is in progress.
Affected Versions
- PHP 5.x (all versions)
- PHP 7.x (all versions)
- PHP 8.x (all versions)
Risk Factor Table
Risk Factor | Description | Severity |
---|---|---|
Impact | Arbitrary code execution, memory corruption, full interpreter compromise | Critical |
Attack Vector | Local code execution, but exploitable via crafted PHP scripts | High |
Affected Systems | All platforms running PHP 5.x, 7.x, 8.x | Universal |
Exploitability | Requires ability to run or inject PHP code (e.g., shared hosting, plugins) | High |
Mitigation | Patch pending, avoid use of extract() with EXTR_REFS | Moderate |
This vulnerability underscores the dangers of complex memory management in dynamic languages like PHP.
Until patches are widely deployed, developers are urged to avoid using extract()
the EXTR_REFS flag and to audit code for unsafe variable extraction patterns.
The risk of arbitrary code execution makes this a critical issue for all environments running PHP.
Find this Story Interesting! Follow us on LinkedIn and X to Get More Instant Updates