rfc:phar_stop_autoloading_metadata

This is an old revision of the document!


PHP RFC: Don't automatically unserialize Phar metadata outside getMetadata()

Introduction

In 2018, various vulnerabilities were found in php web frameworks due to the phar stream wrappers. A call such as file_exists("phar://...somepath.extension/file/within/phar.ext") will lead to unserializing the metadata found in the phar. As https://php.net/unserialize notes, “unserialization can result in code being loaded and executed due to object instantiation and autoloading, and a malicious user may be able to exploit this.”

Various blog posts have been written explaining the resulting vulnerabilities, such as https://www.ixiacom.com/company/blog/exploiting-php-phar-deserialization-vulnerabilities-part-1

Proposal

Don't unserialize the metadata automatically when a phar is opened by php. Only unserialize the metadata if Phar->getMetadata() or PharFile->getMetadata() is called directly.

Additionally, add an $allowed_classes parameter to both getMetadata() implementations, defaulting to the current behavior of allowing any classes (true). This will be passed to the call to unserialize() performed internally.

This implements one possible solution for https://bugs.php.net/bug.php?id=76774

Backward Incompatible Changes

Any side effects from __wakeup(), __destruct(), etc. that were triggered during/after unserialization of metadata when the phar is loaded will stop happening, and will only happen when getMetadata() is directly called.

Eliminating the side effects is the goal of this RFC, for security reasons. Typical phars use scalars and associative arrays for any metadata, and many phars don't need metadata at all.

Proposed PHP Version(s)

8.0

RFC Impact

To SAPIs

This affects stream wrapper calls such as file_exists(), as well as direct calls to Phar->getMetadata() Describe the impact to CLI, Development web server, embedded PHP etc.

php.ini Defaults

If there are any php.ini settings then list:

  • hardcoded default values: On
  • php.ini-development values: On
  • php.ini-production values: On

Proposed Voting Choices

Yes/No, requiring 2/3 majority to stop automatically unserializing metadata.

References

https://externals.io/message/110856 'Including “Disable the ability to use concrete types in PHAR metadata” in PHP 8.0?'

https://externals.io/message/105271 'PHP deserialization techniques offer rich pickings for security researchers'

https://bugs.php.net/bug.php?id=76774

Rejected Features

I'd considered continuing to call unserialize() all of the time to validate phars earlier, but with allowed_classes=[] instead (controlled by an ini setting). This seemed like an unnecessary ini setting that could be avoided by just not automatically loading the metadata.

Changelog

0.2: Link to implementation.

rfc/phar_stop_autoloading_metadata.1594771813.txt.gz · Last modified: 2020/07/15 00:10 by tandre