oss-sec mailing list archives

CVE Request: PHP with Zend OPCache code permission/sensitive data protection vulnerabilities


From: php-dev () coydogsoftware net
Date: Sat, 05 Nov 2016 03:30:41 -0500

Hello,

I did not discover this, but to my knowledge no CVE has been requested to date. The PHP project was informed of this vulnerability over 2 years ago and has not fixed it. I am hoping more public discussion with a CVE will help to motivate
them.

SUMMARY:

Affects PHP with Zend OPCache enabled, PHP5 <= 5.6.27 and PHP7 <= 7.0.12
(http://php.net)

Zend OPCache has code permission and sensitive data protection vulnerabilities
when deployed on shared hosting web servers.

BACKGROUND:

OPCache uses shared memory to cache compiled PHP "opcode" between HTTP requests for reuse. A single shared memory object is opened and initialized in a parent process, and child processes inherit its file descriptor. Due to this design, OPCache is intended for use with a SAPI with a peristent parent process, for example php-fpm with its master process, or apache2handler where initialization
occurs in the Apache parent process.

Cache keys for compiled scripts have two modes of operation, simple
filenames and a "use_cwd" mode which includes additional information such as parent script and working directory in cache keys. The "use_cwd" behavior only occurs when scripts are invoked via relative paths, rare in practice in a web server environment with common web applications. In most circumstances the
cache uses a simple filesystem path as a cache key for a cached script's
compiled form.

On shared servers PHP is often deployed so that it will switch to a local user account before running a script, for example using mod_ruid2 if deployed as an
Apache module, or using "pools" if deployed as php-fpm. In these
configurations, users expect that they can protect sensitive information in PHP
scripts with filesystem permissions.

VULNERABILITY DESCRIPTION:

The single shared OPCache circumvents filesystem permissions. For example, when
user alice's WordPress site is requested, PHP runs as user alice and
wp-config.php is read, compiled, and cached, including constants for database credentials, API auth keys, and hash salts. User bob can then include alice's wp-config.php script via the persistent OPCache, regardless of the original script's file permissions. User bob only has to know the filesystem path of the
script.

PHP's open_basedir setting is also circumvented; with a restrictive
open_basedir, a nonfatal error occurs, but a cached script outside of
open_basedir will still load and run.

If PHP is running in chroots, unintentional cross-user script execution can occur due to filename hash key collisions. This might be considered a separate
bug, but both stem from the simplistic design of opcache keys.

With a default configuration (other than the zend_extension directive to load OPCache, which is not loaded by default) opcache_get_status() can be used to
enumerate cached scripts, making exploitation even easier.

The software's documentation does not mention the issue, so most users would
see no reason not to enable OPCache on a shared server:
http://php.net/manual/en/book.opcache.php

Original reporter in bug #67481 closed his bug report stating "It turns out this is not a bug, it is the behaviour that is expected when opcache.use_cwd is set to zero," but the same behavior occurs when opcache.use_cwd is enabled unless scripts are invoked with relative paths. Absolute paths are typically
used by web servers and web applications.

I've proposed a fix in bug #69090 with patch linked below.

I have point-and-click proof of concept exploit scripts but I plan to give
the PHP project a few more days to patch the issue.

REFERENCES:

https://bugs.php.net/bug.php?id=67481
https://bugs.php.net/bug.php?id=69090
https://bugs.php.net/patch-display.php?bug_id=69090&patch=opcache_bug69090_user_id_keys&revision=latest
http://marc.info/?l=php-internals&m=147825816026557&w=2

In PHP 5.6, the problem is in cache key construction in
accel_make_persistent_key_ex():
https://raw.githubusercontent.com/php/php-src/php-5.6.27/ext/opcache/ZendAccelerator.c

In PHP 7.0, equivalent code is in accel_make_persistent_key():
https://raw.githubusercontent.com/php/php-src/php-7.0.12/ext/opcache/ZendAccelerator.c

Please let me know if more details are needed.

--
- php-dev () coydogsoftware net


Current thread: