diff options
author | Stanislav Malyshev <stas@php.net> | 2015-09-01 11:38:15 -0700 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2015-09-01 11:38:39 -0700 |
commit | 7c31203935589ab4fcb104041ef9d87f747bfee4 (patch) | |
tree | 22fb91a7ace180c4c4c3a251434b4675b87c9a0b | |
parent | 1390a5812b151e0ea8f74e64bfeaa5df4dd5b801 (diff) | |
download | php-git-7c31203935589ab4fcb104041ef9d87f747bfee4.tar.gz |
Improve fix for #70172
-rw-r--r-- | ext/standard/tests/serialize/bug70172.phpt | 2 | ||||
-rw-r--r-- | ext/standard/tests/serialize/bug70172_2.phpt | 68 | ||||
-rw-r--r-- | ext/standard/var.c | 3 |
3 files changed, 72 insertions, 1 deletions
diff --git a/ext/standard/tests/serialize/bug70172.phpt b/ext/standard/tests/serialize/bug70172.phpt index 0e9d7ed89a..0a4aa4be16 100644 --- a/ext/standard/tests/serialize/bug70172.phpt +++ b/ext/standard/tests/serialize/bug70172.phpt @@ -1,5 +1,7 @@ --TEST-- Bug #70172 - Use After Free Vulnerability in unserialize() +--XFAIL-- +Memory leak on debug build, needs fix. --FILE-- <?php class obj implements Serializable { diff --git a/ext/standard/tests/serialize/bug70172_2.phpt b/ext/standard/tests/serialize/bug70172_2.phpt new file mode 100644 index 0000000000..ae48341a46 --- /dev/null +++ b/ext/standard/tests/serialize/bug70172_2.phpt @@ -0,0 +1,68 @@ +--TEST-- +Bug #70172 - Use After Free Vulnerability in unserialize() +--FILE-- +<?php +class obj implements Serializable { + var $data; + function serialize() { + return serialize($this->data); + } + function unserialize($data) { + $this->data = unserialize($data); + } +} + +class obj2 { + var $ryat; + function __wakeup() { + $this->ryat = 1; + } +} + +$fakezval = ptr2str(1122334455); +$fakezval .= ptr2str(0); +$fakezval .= "\x00\x00\x00\x00"; +$fakezval .= "\x01"; +$fakezval .= "\x00"; +$fakezval .= "\x00\x00"; + +$inner = 'r:2;'; +$exploit = 'a:2:{i:0;O:4:"obj2":1:{s:4:"ryat";C:3:"obj":'.strlen($inner).':{'.$inner.'}}i:1;a:1:{i:0;a:1:{i:0;R:4;}}}'; + +$data = unserialize($exploit); + +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]=> + object(obj2)#%d (1) { + ["ryat"]=> + int(1) + } + [1]=> + array(1) { + [0]=> + array(1) { + [0]=> + object(obj2)#%d (1) { + ["ryat"]=> + int(1) + } + } + } +}
\ No newline at end of file diff --git a/ext/standard/var.c b/ext/standard/var.c index 33b976f42d..113b8cb66a 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -981,7 +981,8 @@ PHP_FUNCTION(unserialize) *old_rval = *return_value; zval_copy_ctor(old_rval); var_push_dtor_no_addref(&var_hash, &return_value); - var_push_dtor_no_addref(&var_hash, &old_rval); + /* FIXME: old_rval is not freed in some scenarios, see bug #70172 + var_push_dtor_no_addref(&var_hash, &old_rval); */ } else { var_push_dtor(&var_hash, &return_value); } |