Skip to content

Commit 3f627e5

Browse files
committed
Fixed ##72433: Use After Free Vulnerability in PHP's GC algorithm and unserialize
1 parent b9ec171 commit 3f627e5

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

Diff for: Zend/tests/gc_024.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ var_dump(gc_collect_cycles());
1313
echo "ok\n";
1414
?>
1515
--EXPECT--
16-
int(1)
16+
int(2)
1717
ok

Diff for: ext/spl/spl_array.c

+11
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,16 @@ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /*
831831
}
832832
/* }}} */
833833

834+
static HashTable *spl_array_get_gc(zval *object, zval ***gc_data, int *gc_data_count TSRMLS_DC) /* {{{ */
835+
{
836+
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
837+
838+
*gc_data = &intern->array;
839+
*gc_data_count = 1;
840+
return zend_std_get_properties(object);
841+
}
842+
/* }}} */
843+
834844
static zval *spl_array_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
835845
{
836846
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
@@ -1961,6 +1971,7 @@ PHP_MINIT_FUNCTION(spl_array)
19611971

19621972
spl_handler_ArrayObject.get_properties = spl_array_get_properties;
19631973
spl_handler_ArrayObject.get_debug_info = spl_array_get_debug_info;
1974+
spl_handler_ArrayObject.get_gc = spl_array_get_gc;
19641975
spl_handler_ArrayObject.read_property = spl_array_read_property;
19651976
spl_handler_ArrayObject.write_property = spl_array_write_property;
19661977
spl_handler_ArrayObject.get_property_ptr_ptr = spl_array_get_property_ptr_ptr;

Diff for: ext/standard/tests/strings/bug72433.phpt

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Bug #72433: Use After Free Vulnerability in PHP's GC algorithm and unserialize
3+
--FILE--
4+
<?php
5+
// Fill any potential freed spaces until now.
6+
$filler = array();
7+
for($i = 0; $i < 100; $i++)
8+
$filler[] = "";
9+
// Create our payload and unserialize it.
10+
$serialized_payload = 'a:3:{i:0;r:1;i:1;r:1;i:2;C:11:"ArrayObject":19:{x:i:0;r:1;;m:a:0:{}}}';
11+
$free_me = unserialize($serialized_payload);
12+
// We need to increment the reference counter of our ArrayObject s.t. all reference counters of our unserialized array become 0.
13+
$inc_ref_by_one = $free_me[2];
14+
// The call to gc_collect_cycles will free '$free_me'.
15+
gc_collect_cycles();
16+
// We now have multiple freed spaces. Fill all of them.
17+
$fill_freed_space_1 = "filler_zval_1";
18+
$fill_freed_space_2 = "filler_zval_2";
19+
var_dump($free_me);
20+
?>
21+
--EXPECTF--
22+
array(3) {
23+
[0]=>
24+
*RECURSION*
25+
[1]=>
26+
*RECURSION*
27+
[2]=>
28+
object(ArrayObject)#%d (1) {
29+
["storage":"ArrayObject":private]=>
30+
*RECURSION*
31+
}
32+
}

0 commit comments

Comments
 (0)