Despite providing class whitelisting [1] and documentation about warnings
about security impacts [2], we continue to see vulnerable uses of
unserialize() in Drupal modules [3] and partially effective attempts to
mitigate vulnerabilities from user-supplied, serialized data [4].

Whitelisting legal classes for unserializing data is, unfortunately, not
seeing widespread uptake in community-created code that I review. It also
doesn't push us toward more secure defaults shipping with OS packages and
on PHP-supporting platforms. An additional option that would generally work
with existing, legitimate use but would also block use for exploits could
turn that tide.

I propose adding a new key to the $options parameter for unserialize(). The
new key would be "exception_on_side_effects", have a Boolean value, and
would (if true) cause unserialization to halt (and an exception to be
thrown) if any of the data being unserialized contains objects with magic
methods that will automatically execute on object wakeup, destruction, or
other events that the PHP interpreter (almost) always triggers.

To help push toward better defaults, I also suggest adding a related
configuration option:

Name: unserialize_side_effect_protection
Default: 0
Changeable: PHP_INI_ALL

If enabled, it would cause "exception_on_side_effects" to be enabled by
default on all unserialize() calls that don't specify "allowed_classes" or
override the default. By making it PHP_INI_ALL, frameworks could lock down
usage during bootstrap (or at least before reading request data).

I am a member of the Drupal Security Team and would also be the implementer
of this feature. My username on the wiki is "dts", and I'm requesting RFC
karma.

[1] https://wiki.php.net/rfc/secure_unserialize
[2] https://secure.php.net/manual/en/function.unserialize.php
[3] https://www.ambionics.io/blog/drupal-services-module-rce
[4]
https://github.com/WordPress/WordPress/blob/efab6e06cae3ed14c6b681570dfd5f81917d9f9c/wp-includes/functions.php#L341-L394

Reply via email to