]> granicus.if.org Git - php/commitdiff
More fixes for bug #70219
authorStanislav Malyshev <stas@php.net>
Sat, 29 Aug 2015 04:50:21 +0000 (21:50 -0700)
committerStanislav Malyshev <stas@php.net>
Sat, 29 Aug 2015 04:50:21 +0000 (21:50 -0700)
ext/session/session.c
ext/standard/tests/serialize/bug70219_1.phpt [new file with mode: 0644]

index 247f9b27f7590023d6fd434294f1dbfd8fd48107..f5439ea79c5b94b9c68adf8a1c5a77e8c318cf24 100644 (file)
@@ -863,7 +863,10 @@ PS_SERIALIZER_DECODE_FUNC(php_serialize) /* {{{ */
 
        PHP_VAR_UNSERIALIZE_INIT(var_hash);
        ALLOC_INIT_ZVAL(session_vars);
-       php_var_unserialize(&session_vars, &val, endptr, &var_hash TSRMLS_CC);
+       if (php_var_unserialize(&session_vars, &val, endptr, &var_hash TSRMLS_CC)) {
+               var_push_dtor(&var_hash, &session_vars);
+       }
+       
        PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
        if (PS(http_session_vars)) {
                zval_ptr_dtor(&PS(http_session_vars));
@@ -872,7 +875,7 @@ PS_SERIALIZER_DECODE_FUNC(php_serialize) /* {{{ */
                array_init(session_vars);
        }
        PS(http_session_vars) = session_vars;
-       ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), 2, 1);
+       ZEND_SET_GLOBAL_VAR_WITH_LENGTH("_SESSION", sizeof("_SESSION"), PS(http_session_vars), Z_REFCOUNT_P(PS(http_session_vars)) + 1, 1);
        return SUCCESS;
 }
 /* }}} */
diff --git a/ext/standard/tests/serialize/bug70219_1.phpt b/ext/standard/tests/serialize/bug70219_1.phpt
new file mode 100644 (file)
index 0000000..f9c4c67
--- /dev/null
@@ -0,0 +1,46 @@
+--TEST--
+Bug #70219 Use after free vulnerability in session deserializer
+--FILE--
+<?php
+ini_set('session.serialize_handler', 'php_serialize');
+session_start();
+
+class obj implements Serializable {
+    var $data;
+    function serialize() {
+        return serialize($this->data);
+    }
+    function unserialize($data) {
+        session_decode($data);
+    }
+}
+
+$inner = 'r:2;';
+$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;C:3:"obj":'.strlen($inner).':{'.$inner.'}}';
+
+$data = unserialize($exploit);
+
+for ($i = 0; $i < 5; $i++) {
+    $v[$i] = 'hi'.$i;
+}
+
+var_dump($data);
+var_dump($_SESSION);
+?>
+--EXPECTF--
+array(2) {
+  [0]=>
+  &object(obj)#%d (1) {
+    ["data"]=>
+    NULL
+  }
+  [1]=>
+  object(obj)#%d (1) {
+    ["data"]=>
+    NULL
+  }
+}
+object(obj)#1 (1) {
+  ["data"]=>
+  NULL
+}
\ No newline at end of file