This is an old revision of the document!
PHP RFC: Secure serialization by authentication code
- Version: 0.1
- Date: 2015-12-30
- Author: Yasuo Ohgaki yohgaki@php.net
- Status: Draft
- First Published at: http://wiki.php.net/rfc/secure_serialization
Introduction
PHP variable serialization was source of security issues. The root cause of issues is “crafted serialized data”. Crafted serialized data can be rejected by message authentication code using crypt-graphic hash function. This RFC proposes serialize/unserialize function that supports authentication code.
Recent vulnerability examples are Joomla! 3.4.6 and 3.4.7.
Making sure if serialized data is generated by the server/system before unserialization is mandatory for security. Even though this is possible in userland, but it's rarely implemented. Therefore, PHP is better to provide function for secure serialization/unserialization. Proposed secure serialization functions prevent crafted serialized data to be passed to php_unserialize(). Therefore, this RFC can also protect unknown serialize vulnerabilities even if they exist.
Proposal
- Add secure_serialize() and secure_unserialize() supports message authentication code generation/validation and expiration.
string secure_serialize(mixed $data_to_be_serialized , string $secret_key [, int $ttl=1800 [,bool $session_only=TRUE]]) mixed secure_unserialize(mixed $data_to_be_unserialized , string $secret_key='')
How secure_serialize() works
Pseudo code
function secure_serialize(string $data_to_be_serialized, string $secret_key, int $ttl, bool $session_only = TRUE) : string { if (strlen($secret_key) < 32) { trigger_error('Too short secret key'); return FALSE; } if ($ttl <= 0) { trigger_error('Invalid TTL'); return FALSE; } $ttl = time() + $ttl; $session_only = $session_only ? TRUE : FALSE; // Use random key to randomize $mac $key = sha256(random_bytes(64)); $serialized_data = serialize($data_to_be_serialized); if ($session_only && session_id()) { // Session ID is hashed by SHA256 to avoid session ID exposure. $mac = sha256($secret_key.$ttl.$key.sha256($secret_key.session_id()).$serialized_data); return serialize['mac'=>$mac, 'ttl'=>$ttl, 'key'=>$key, 'id'=>sha256($secret_key.session_id()), 'data'=>$serialized_data]; } else { $mac = sha256($secret_key.$ttl.$key.$serialized_data); return serialize['mac'=>$mac, 'ttl'=>$ttl, 'key'=>$key, 'data'=>$serialized_data]; } }
How secure_unserialize() works
Pseudo code
function secure_serialize(string $data_to_be_unserialized, string $secret_key) : mixed { if (strlen($secret_key) < 32) { trigger_error('Too short secret key'); return FALSE; } $tmp = unserialize($data_to_be_unserialized); if ($tmp['ttl'] < time() { // Serialized data is expired return FALSE; } if (isset($tmp['id'])) { // Old session ID may be used if session module store old IDs in internal data. // https://wiki.php.net/rfc/precise_session_management $mac = sha256($secret_key.$tmp['ttl'].$tmp['key'].sha256($secret_key.session_id()).$tmp['data']); } else { $mac = sha256($secret_key.$tmp['ttl'].$tmp['key'].$tmp['data']); } if ($mac !== $tmp['mac']) { return FALSE; } return $tmp['data']; }
Backward Incompatible Changes
None.
Proposed PHP Version(s)
PHP 7.1
RFC Impact
To SAPIs
None.
To Existing Extensions
None.
To Opcache
None.
New Constants
None.
php.ini Defaults
If there are any php.ini settings then list:
- hardcoded default values
- php.ini-development values
- php.ini-production values
No changes.
Open Issues
Make sure there are no open issues when the vote starts!
Unaffected PHP Functionality
List existing areas/features of PHP that will not be changed by the RFC.
This helps avoid any ambiguity, shows that you have thought deeply about the RFC's impact, and helps reduces mail list noise.
Future Scope
If session module stores old session ID, automatic fallback to old session ID may be supported.
Compatibility functions for older releases may be implemented as PHP script.
Proposed Voting Choices
50%+1 majority
Patches and Tests
TBD
Implementation
After the project is implemented, this section should contain
- the version(s) it was merged to
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
References
Links to external references, discussions or RFCs
Rejected Features
Keep this updated with features that were discussed on the mail lists.