PHP 8.0: phar://
stream wrapper no longer unserialize
s meta data automatically
A security improvement in PHP 8.0 is that the Phar stream wrapper (phar://
) no longer automatically calls unserialize on stream wrapper operations, such as file_exists('phar://file.txt')
.
Prior to PHP 8.0, when the Phar stream wrappers (phar://
) were used, it automatically attempted to unserialize
the Phar meta data. This behavior could be exploited and expanded to a remote code execution vulnerability because the unserialize
function attempts to autoload and instantiate a class, possibly controlled by an attacker.
Calling functions that accepted stream wrappers (fopen
, file_exists
, etc) with a phar://
URI immediately triggered the unserialize
call, which is changed in PHP 8.1.
In PHP 8.1, stream wrapper functions no longer attempt to unserialize
meta data. Only explicit calls to Phar::getMetadata
and PharFile::getMetadata
attempt to unserialize the Phar meta data.
Further, the Phar::getMetadata
and PharFileInfo::getMetadata
methods now accept an array of unserialization options, that behave similar to the unserialization options parameter in the unserialize
function. This allows safer unserialization of meta data by explicitly disallowing all PHP classes. See more information at the unserialize
function documentation.
class Phar {
// ...
- public function getMetadata() {}
+ public function getMetadata(array $unserializeOptions = []) {}
}
class PharFileInfo {
// ...
- public function getMetadata() {}
+ public function getMetadata(array $unserializeOptions = []) {}
}
When attempting to retrieve the meta data, it is now possible to neutralize the potential security vulnerabilities from the unserialize
call by passing a list of classes that are allowed to be unserialized. Passing an empty array ([]
) completely disables class instantiating entirely, which is the highly recommended setting.
$phar = new Phar('path/to/phar.phar');
$phar->getMetadata(['allowed_classes' => []]);
Backwards Compatibility Impact
It is unlikely that a real-life application is broken because of this change. Automatic unserialization on stream wrapper functions is considered an unintended side-effect, which no longer happens in PHP 8.0 and later.
Note that the getMetadata
methods continue to call unserialize
automatically, and it is not necessary to manually call unserialize
function.
Any classes that extend and override Phar::getMetadata
and/or PharFileInfo::getMetadata
methods must update their signatures to accept the new parameters. On signature mismatches, PHP 8.0 and later throws a fatal error.