diff options
author | Stanislav Malyshev <stas@php.net> | 2015-09-01 12:05:02 -0700 |
---|---|---|
committer | Ferenc Kovacs <tyrael@php.net> | 2015-09-03 01:51:19 +0200 |
commit | 4d7bb43b9f399d20af45124906384d82afbd10f7 (patch) | |
tree | d80c74e887736e2d7decf845c27c49e252e00371 | |
parent | 55ddcbca0f8c95e28a8a828ec4635cbc792d9807 (diff) | |
download | php-git-4d7bb43b9f399d20af45124906384d82afbd10f7.tar.gz |
Merge branch '70284' into PHP-5.6
* 70284:
Fix bug ##70284 (Use after free vulnerability in unserialize() with GMP)
-rw-r--r-- | ext/gmp/gmp.c | 10 | ||||
-rw-r--r-- | ext/gmp/tests/bug70284.phpt | 50 |
2 files changed, 55 insertions, 5 deletions
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 575dab8a5b..c7cdef736f 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -630,7 +630,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c { mpz_ptr gmpnum; const unsigned char *p, *max; - zval zv, *zv_ptr = &zv; + zval *zv_ptr; int retval = FAILURE; php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data; @@ -640,7 +640,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c p = buf; max = buf + buf_len; - INIT_ZVAL(zv); + ALLOC_INIT_ZVAL(zv_ptr); if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC) || Z_TYPE_P(zv_ptr) != IS_STRING || convert_to_gmp(gmpnum, zv_ptr, 10 TSRMLS_CC) == FAILURE @@ -648,9 +648,9 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c zend_throw_exception(NULL, "Could not unserialize number", 0 TSRMLS_CC); goto exit; } - zval_dtor(&zv); + var_push_dtor_no_addref(&unserialize_data, &zv_ptr); - INIT_ZVAL(zv); + ALLOC_INIT_ZVAL(zv_ptr); if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC) || Z_TYPE_P(zv_ptr) != IS_ARRAY ) { @@ -667,7 +667,7 @@ static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned c retval = SUCCESS; exit: - zval_dtor(&zv); + var_push_dtor_no_addref(&unserialize_data, &zv_ptr); PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data); return retval; } diff --git a/ext/gmp/tests/bug70284.phpt b/ext/gmp/tests/bug70284.phpt new file mode 100644 index 0000000000..ab17c0fc1c --- /dev/null +++ b/ext/gmp/tests/bug70284.phpt @@ -0,0 +1,50 @@ +--TEST-- +Bug #70284 (Use after free vulnerability in unserialize() with GMP) +--SKIPIF-- +<?php if (!extension_loaded("gmp")) print "skip"; ?> +--FILE-- +<?php + +$inner = 'r:2;a:1:{i:0;a:1:{i:0;r:4;}}'; +$exploit = 'a:2:{i:0;s:1:"1";i:1;C:3:"GMP":'.strlen($inner).':{'.$inner.'}}'; + +$data = unserialize($exploit); + +$fakezval = ptr2str(1122334455); +$fakezval .= ptr2str(0); +$fakezval .= "\x00\x00\x00\x00"; +$fakezval .= "\x01"; +$fakezval .= "\x00"; +$fakezval .= "\x00\x00"; + +for ($i = 0; $i < 5; $i++) { + $v[$i] = $fakezval.$i; +} + +var_dump($data); + +function ptr2str($ptr) +{ +$out = ''; + for ($i = 0; $i < 8; $i++) { + $out .= chr($ptr & 0xff); + $ptr >>= 8; + } + return $out; +} +?> +--EXPECTF-- +array(2) { + [0]=> + string(1) "1" + [1]=> + object(GMP)#%d (2) { + [0]=> + array(1) { + [0]=> + NULL + } + ["num"]=> + string(1) "1" + } +} |