php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74844 Type confusion when unserializing a crafted ArrayObject
Submitted: 2017-07-02 16:11 UTC Modified: 2017-08-12 18:47 UTC
From: admin at stickman dot hu Assigned: nikic (profile)
Status: Closed Package: SPL related
PHP Version: 7.1.6 OS:
Private report: No CVE-ID: None
 [2017-07-02 16:11 UTC] admin at stickman dot hu
Description:
------------
This bug is related to #73029.

When ArrayObject gets unserialized, it checks for the unserialized internal "array" variable to be either an array or an object. However, when it unserializes the additional properties, the already unserialized array may still turn into a reference.
Then this internal array (now a reference) is cast to, and used as Z_OBJ, in spl_array_get_hash_table_ptr, when the object is used.

The bug can be triggered both with a crafted serialized string, or simply serializing and unserializing a crafted object, e.g. by putting it into $_SESSION, or shared memory.

It can also be triggered with a simple property read, if the ARRAY_AS_PROPS flags is set in a crafted serialized string.

I think the error is both unserializing to a reference, and the absolutely unconditional "else" in spl_array_get_hash_table_ptr.
- unserialize should make a defensive copy of 'array', like gmp does.
- spl_array_get_hash_table_ptr should check if the array field is actually an object.

Test script:
---------------
class A{};
$a = new A();
$ao = new ArrayObject($a);
$ao->reference_field = &$a;
$ao_corrupted = unserialize(serialize($ao));
$ao_corrupted['x'];

Expected result:
----------------
The code should not crash.

Actual result:
--------------
It throws segmentation fault with the following backtrace:

#0  rebuild_object_properties (zobj=0x7ffff6477078) at /home/alex/projects/php/php-src/Zend/zend_object_handlers.c:80
#1  0x00000000004935be in spl_array_get_hash_table_ptr (intern=<optimized out>) at /home/alex/projects/php/php-src/ext/spl/spl_array.c:100
#2  spl_array_get_hash_table (intern=<optimized out>) at /home/alex/projects/php/php-src/ext/spl/spl_array.c:113
#3  spl_array_get_dimension_ptr (check_inherited=0, intern=<optimized out>, offset=0x7ffff646f1c0, type=<optimized out>) at /home/alex/projects/php/php-src/ext/spl/spl_array.c:296
#4  0x000000000048f56b in spl_array_read_dimension_ex (check_inherited=<optimized out>, object=0x7ffff64140a0, offset=0x7ffff646f1c0, type=0, rv=0x7ffff6414180)
    at /home/alex/projects/php/php-src/ext/spl/spl_array.c:430
#5  0x0000000000608fdb in zend_fetch_dimension_address_read (container=0x7ffff64140a0, dim=0x7ffff646f1c0, dim_type=16, type=0, support_strings=1, slow=1, result=<optimized out>)
    at /home/alex/projects/php/php-src/Zend/zend_execute.c:1880
#6  zend_fetch_dimension_address_read_R_slow (result=0x7ffff6414180, container=0x7ffff64140a0, dim=<optimized out>) at /home/alex/projects/php/php-src/Zend/zend_execute.c:1909
#7  0x00000000005d11f7 in ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER (execute_data=0x7ffff6414030) at /home/alex/projects/php/php-src/Zend/zend_vm_execute.h:38121
#8  0x00000000005b0338 in execute_ex (ex=0x7ffff6414030) at /home/alex/projects/php/php-src/Zend/zend_vm_execute.h:432
#9  0x00000000005b05bb in zend_execute (op_array=0x7ffff6481000, return_value=<optimized out>) at /home/alex/projects/php/php-src/Zend/zend_vm_execute.h:474
#10 0x000000000056e0a4 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/alex/projects/php/php-src/Zend/zend.c:1476
#11 0x000000000050f72e in php_execute_script (primary_file=0x7fffffffcb60) at /home/alex/projects/php/php-src/main/main.c:2537
#12 0x00000000006112e0 in do_cli (argc=2, argv=<optimized out>) at /home/alex/projects/php/php-src/sapi/cli/php_cli.c:993
#13 0x00000000006104a6 in main (argc=2, argv=0xa04480) at /home/alex/projects/php/php-src/sapi/cli/php_cli.c:1381


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-08-12 18:05 UTC] admin at stickman dot hu
I read that unserialize bugs are no longer considered security bugs.

Easy to "secure" your software by labeling everything "not security", very professional, gg no re.
 [2017-08-12 18:13 UTC] stas@php.net
-Type: Security +Type: Bug
 [2017-08-12 18:13 UTC] stas@php.net
Thanks for the note, yes, this bug should be reclassified.

Please also note bug system is not a forum. If you want to discuss matters not pertaining to the particular bugs, please use mailing lists or other venues.
 [2017-08-12 18:47 UTC] nikic@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: nikic
 [2017-08-12 18:47 UTC] nikic@php.net
This has already been fixed by bug #74669.
 
PHP Copyright © 2001-2018 The PHP Group
All rights reserved.
Last updated: Fri Sep 21 17:01:26 2018 UTC