1 # Source: upstream |
|
2 # https://github.com/php/php-src/commit/d735957cb5f8fee8d13ae68cf75300306c84374f.patch |
|
3 # https://bugs.php.net/bug.php?id=70284 |
|
4 # Security |
|
5 |
|
6 From d735957cb5f8fee8d13ae68cf75300306c84374f Mon Sep 17 00:00:00 2001 |
|
7 From: Stanislav Malyshev <[email protected]> |
|
8 Date: Sun, 23 Aug 2015 13:46:19 -0700 |
|
9 Subject: [PATCH] Fix bug ##70284 (Use after free vulnerability in |
|
10 unserialize() with GMP) |
|
11 |
|
12 --- |
|
13 ext/gmp/gmp.c | 10 ++++----- |
|
14 ext/gmp/tests/bug70284.phpt | 50 +++++++++++++++++++++++++++++++++++++++++++++ |
|
15 2 files changed, 55 insertions(+), 5 deletions(-) |
|
16 create mode 100644 ext/gmp/tests/bug70284.phpt |
|
17 |
|
18 diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c |
|
19 index 575dab8..c7cdef7 100644 |
|
20 --- a/ext/gmp/gmp.c |
|
21 +++ b/ext/gmp/gmp.c |
|
22 @@ -630,7 +630,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c |
|
23 { |
|
24 mpz_ptr gmpnum; |
|
25 const unsigned char *p, *max; |
|
26 - zval zv, *zv_ptr = &zv; |
|
27 + zval *zv_ptr; |
|
28 int retval = FAILURE; |
|
29 php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; |
|
30 |
|
31 @@ -640,7 +640,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c |
|
32 p = buf; |
|
33 max = buf + buf_len; |
|
34 |
|
35 - INIT_ZVAL(zv); |
|
36 + ALLOC_INIT_ZVAL(zv_ptr); |
|
37 if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC) |
|
38 || Z_TYPE_P(zv_ptr) != IS_STRING |
|
39 || convert_to_gmp(gmpnum, zv_ptr, 10 TSRMLS_CC) == FAILURE |
|
40 @@ -648,9 +648,9 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c |
|
41 zend_throw_exception(NULL, "Could not unserialize number", 0 TSRMLS_CC); |
|
42 goto exit; |
|
43 } |
|
44 - zval_dtor(&zv); |
|
45 + var_push_dtor_no_addref(&unserialize_data, &zv_ptr); |
|
46 |
|
47 - INIT_ZVAL(zv); |
|
48 + ALLOC_INIT_ZVAL(zv_ptr); |
|
49 if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC) |
|
50 || Z_TYPE_P(zv_ptr) != IS_ARRAY |
|
51 ) { |
|
52 @@ -667,7 +667,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c |
|
53 |
|
54 retval = SUCCESS; |
|
55 exit: |
|
56 - zval_dtor(&zv); |
|
57 + var_push_dtor_no_addref(&unserialize_data, &zv_ptr); |
|
58 PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); |
|
59 return retval; |
|
60 } |
|
61 diff --git a/ext/gmp/tests/bug70284.phpt b/ext/gmp/tests/bug70284.phpt |
|
62 new file mode 100644 |
|
63 index 0000000..ab17c0f |
|
64 --- /dev/null |
|
65 +++ b/ext/gmp/tests/bug70284.phpt |
|
66 @@ -0,0 +1,50 @@ |
|
67 +--TEST-- |
|
68 +Bug #70284 (Use after free vulnerability in unserialize() with GMP) |
|
69 +--SKIPIF-- |
|
70 +<?php if (!extension_loaded("gmp")) print "skip"; ?> |
|
71 +--FILE-- |
|
72 +<?php |
|
73 + |
|
74 +$inner = 'r:2;a:1:{i:0;a:1:{i:0;r:4;}}'; |
|
75 +$exploit = 'a:2:{i:0;s:1:"1";i:1;C:3:"GMP":'.strlen($inner).':{'.$inner.'}}'; |
|
76 + |
|
77 +$data = unserialize($exploit); |
|
78 + |
|
79 +$fakezval = ptr2str(1122334455); |
|
80 +$fakezval .= ptr2str(0); |
|
81 +$fakezval .= "\x00\x00\x00\x00"; |
|
82 +$fakezval .= "\x01"; |
|
83 +$fakezval .= "\x00"; |
|
84 +$fakezval .= "\x00\x00"; |
|
85 + |
|
86 +for ($i = 0; $i < 5; $i++) { |
|
87 + $v[$i] = $fakezval.$i; |
|
88 +} |
|
89 + |
|
90 +var_dump($data); |
|
91 + |
|
92 +function ptr2str($ptr) |
|
93 +{ |
|
94 +$out = ''; |
|
95 + for ($i = 0; $i < 8; $i++) { |
|
96 + $out .= chr($ptr & 0xff); |
|
97 + $ptr >>= 8; |
|
98 + } |
|
99 + return $out; |
|
100 +} |
|
101 +?> |
|
102 +--EXPECTF-- |
|
103 +array(2) { |
|
104 + [0]=> |
|
105 + string(1) "1" |
|
106 + [1]=> |
|
107 + object(GMP)#%d (2) { |
|
108 + [0]=> |
|
109 + array(1) { |
|
110 + [0]=> |
|
111 + NULL |
|
112 + } |
|
113 + ["num"]=> |
|
114 + string(1) "1" |
|
115 + } |
|
116 +} |
|
117 |
|