|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull Requests
Pull requests:
HistoryAllCommentsChangesGit/SVN commits
[2014-02-12 17:21 UTC] tyrael@php.net
[2014-02-12 21:26 UTC] stas@php.net
[2014-02-17 05:17 UTC] chealer at gmail dot com
[2014-06-09 05:35 UTC] stas@php.net
-Type: Security
+Type: Feature/Change Request
[2024-07-09 09:59 UTC] Jon791Ralph at outlook dot com
|
|||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Nov 01 04:00:02 2025 UTC |
Description: ------------ The procedural serialization offered via the built-in unserialize() and serialize() built-in functions has architectural issues that violate encapsulation and can cause vulnerabilities in certain cases. This wide report documents these and problems in unserialize()'s documentation, but remedies may not involve only documentation changes. First, unserialize()'s documentation is very unclear: unserialize — Creates a PHP value from a stored representation Description mixed unserialize ( string $str ) unserialize() takes a single serialized variable and converts it back into a PHP value. str The serialized string. If the variable being unserialized is an object, after successfully reconstructing the object PHP will automatically attempt to call the __wakeup() member function (if it exists). [...] The converted value is returned, and can be a boolean, integer, float, string, array or object. In case the passed string is not unserializeable, FALSE is returned and E_NOTICE is issued. http://ca.php.net/manual/en/function.unserialize.php None of this explains the format expected. The description simply assumes the string passed is "a single serialized variable". This does not even explain that the format is generated by serialize(), which is not referred to until the See also section. This assumption hides the fact that the string given may not represent a valid instance of a class. unserialize() may create an object that a corresponding call to serialize() could never have serialized, since the deserialization simply imports data members bypassing class methods without validation. Equally grave, the type of the value created by unserialize() is embedded in its input string. There is no other way to specify the expected type, which means that calling unserialize() on entirely untrusted data can lead to the creation of a value of any defined type, including all classes. Therefore, even though the description says unserialize() "creates a value", calling it can result in user code execution via the __wakeup() magic method, and indirectly via __destruct(). The combination of these issues makes unserialize() an attack vector, which - as shown in slides 32-45 from http://www.suspekt.org/downloads/POC2009-ShockingNewsInPHPExploitation.pdf - is not simply theoretical. This is not a request to document the serialization format. Although this format should probably be changed, the magical approach is fine as long as it is properly documented. Serialization is mainly used with arrays and objects. For objects, PHP 5.1 offers a modern alternative in Serializable. However, I do not see a real equivalent for native arrays at first sight. In my uninformed opinion, the current procedural mechanism should probably be replaced/eliminated. If there are no plans for this already, I would recommend having a project discussion. In the short term: The examples of serialize() and unserialize() make no sense on their own. They should be grouped on the Object Serialization page: http://ca.php.net/manual/en/language.oop5.serialization.php That page already has one example. It should be the place to explain how serialize() and unserialize() can be used safely. unserialize()'s documentation should have warnings. As things stand, even a reader looking for security issues would likely not realize the problems. Currently, unserialize()'s documentation page doesn't directly link to Object Serialization. unserialize() takes a single serialized variable and converts it back into a PHP value. should read: unserialize() takes a string representing a serialized value and converts it back into a PHP value. The serialized string. should read: The string representing a serialized value.