php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73900 Use After Free in unserialize() SplFixedArray
Submitted: 2017-01-09 21:42 UTC Modified: 2017-04-04 19:50 UTC
From: rossa dot milan at gmail dot com Assigned: nikic (profile)
Status: Closed Package: SPL related
PHP Version: 7.* OS: ALL
Private report: No CVE-ID: None
 [2017-01-09 21:42 UTC] rossa dot milan at gmail dot com
Description:
------------
Use After Free in unserialize() with SplFixedArray. It is possible to leak memory and create gadgets to gain full memory read/write access. Demo of memory leak in script bellow.


Test script:
---------------
<?php
for ($i=0; $i<1000; $i++)
$z[$i] = str_repeat('A', 10);

$s = 'O:13:"SplFixedArray":2:{i:0;s:10:"1234567890";i:1;r:2;}';
$o = unserialize($s);
$b = &$o[1];
$o[1] = 0xbaad;

for ($i=0; $i<4000; $i++) {
  echo(bin2hex($o[0][$i]));
}
echo("\n");

Expected result:
----------------
31323334353637383930

Actual result:
--------------
31743d5554462d3800300061790000000100000006000000000000000a00000031323334353637383930006179000000001147b50d0000000614000000000000adba00001ab9ffbf0400000000000000801147b5000000...0000000000000000000000000201f47b500000000000000000000000000000000000000000000000000000000401f47b500000000000000000000000000000000000000000000000000000000601f47b500000000000000000000000000000000000000000000000000000000801f47b500000000000000000000000000000000000000000000000000000000a01f47b500000000000000000000000000000000000000000000000000000000c01f47b500000000000000000000000000000000000000000000000000000000e01f47b50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000006000000000000000a000000414141414141414141410000000000000100000006000000000000000a000000414141414141414141410000000000000100000006000000000000000a000000414141414141414141410000000000000100000006000000000000000a000000414141414141414141410000000000000100000006000000000000000a000000414141414141414141410000000000000100000006000000000000000a000000

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-01-12 12:01 UTC] rossa dot milan at gmail dot com
-PHP Version: 7.1.0 +PHP Version: 7.*
 [2017-01-12 12:01 UTC] rossa dot milan at gmail dot com
Also tested on 7.0.14 with success.
 [2017-01-16 07:54 UTC] stas@php.net
-Assigned To: +Assigned To: nikic
 [2017-01-16 07:54 UTC] stas@php.net
Nikita, could you take a look? Looks like both elements of SplFixedArray point to the same str, but it is freed prematurely instead of being separated when assignment is made. The refcount is correct 2 when leaving unserialize but then is decreased to 1 in ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER.
 [2017-03-30 20:29 UTC] nikic@php.net
The use of unserialize() here is a red herring -- what is actually causing the memory errors is the attempt to acquire a reference into the SplFixedArray. A reduced reproduce script is the following (run under valgrind):

<?php
$a = new stdClass;
$b = new SplFixedArray(1);
$b[0] = $a;
$c = &$b[0];

As such, I do not believe this qualifies as a security issue under https://wiki.php.net/security: The issue cannot be triggered through user input. Instead, what triggers the issue is specific and atypical local code, namely the "$c = &$b[0]" line (it is atypical because ArrayAccess objects do not support references).

I believe the cause of this issue is the code at https://github.com/php/php-src/blob/f07e4c033cf4edda8dcbf14c5a964e4d283fa8a8/Zend/zend_execute.c#L1637, which seems to assume that result is already in retval (which happens to be the case for non-internal implementations of offsetGet()).
 [2017-03-30 20:42 UTC] nikic@php.net
Here is a patch against master which fixes the issue: https://gist.github.com/nikic/79b9b55d325373d4b39903a82027064e
 [2017-03-31 23:57 UTC] stas@php.net
If it's not related to unserialize I assume it's not a security issue?
 [2017-04-02 11:56 UTC] zeev@php.net
Stas - the reverse is actually true :)
(if it's related to unserialize, then it's not a security issue!)
 [2017-04-03 21:11 UTC] stas@php.net
Well, in both cases it requires specially crafted code, so unless I hear objections soon I will reclassify it.
 [2017-04-04 19:50 UTC] stas@php.net
-Type: Security +Type: Bug
 [2017-06-25 17:49 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=2fddc4a7f1588239939a509781706c084939e09f
Log: Fixed bug #73900
 [2017-06-25 17:49 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sat Nov 18 08:03:32 2017 UTC