components/php/php56/patches/CVE-2015-6836.patch
changeset 6715 70440209f302
parent 6714 af94afe100ff
child 6716 6e7ab6702602
equal deleted inserted replaced
6714:af94afe100ff 6715:70440209f302
     1 # Source: upstream
       
     2 # http://git.php.net/?p=php-src.git;a=commit;h=e201f01ac17243a1e5fb6a3911ed8e21b1619ac1
       
     3 # https://bugs.php.net/bug.php?id=70388
       
     4 
       
     5 From e201f01ac17243a1e5fb6a3911ed8e21b1619ac1 Mon Sep 17 00:00:00 2001
       
     6 From: Stanislav Malyshev <[email protected]>
       
     7 Date: Mon, 31 Aug 2015 21:06:03 -0700
       
     8 Subject: [PATCH] Fix bug #70388 - SOAP serialize_function_call() type
       
     9  confusion
       
    10 
       
    11 ---
       
    12  ext/soap/soap.c              | 96 ++++++++++++++++++++++++--------------------
       
    13  ext/soap/tests/bug70388.phpt | 17 ++++++++
       
    14  2 files changed, 69 insertions(+), 44 deletions(-)
       
    15  create mode 100644 ext/soap/tests/bug70388.phpt
       
    16 
       
    17 diff --git a/ext/soap/soap.c b/ext/soap/soap.c
       
    18 index 1b8f545..a0e64a3 100644
       
    19 --- a/ext/soap/soap.c
       
    20 +++ b/ext/soap/soap.c
       
    21 @@ -989,7 +989,7 @@ static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
       
    22  	HashTable *ht2;
       
    23  	HashPosition pos1, pos2;
       
    24  	HashTable *typemap = NULL;
       
    25 -	
       
    26 +
       
    27  	zend_hash_internal_pointer_reset_ex(ht, &pos1);
       
    28  	while (zend_hash_get_current_data_ex(ht, (void**)&tmp, &pos1) == SUCCESS) {
       
    29  		char *type_name = NULL;
       
    30 @@ -1033,7 +1033,7 @@ static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
       
    31  				}
       
    32  			}
       
    33  			zend_hash_move_forward_ex(ht2, &pos2);
       
    34 -		}		
       
    35 +		}
       
    36  
       
    37  		if (type_name) {
       
    38  			smart_str nscat = {0};
       
    39 @@ -1063,7 +1063,7 @@ static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
       
    40  			new_enc->to_xml = enc->to_xml;
       
    41  			new_enc->to_zval = enc->to_zval;
       
    42  			new_enc->details.map = emalloc(sizeof(soapMapping));
       
    43 -			memset(new_enc->details.map, 0, sizeof(soapMapping));			
       
    44 +			memset(new_enc->details.map, 0, sizeof(soapMapping));
       
    45  			if (to_xml) {
       
    46  				zval_add_ref(&to_xml);
       
    47  				new_enc->details.map->to_xml = to_xml;
       
    48 @@ -1120,7 +1120,7 @@ PHP_METHOD(SoapServer, SoapServer)
       
    49  	if (Z_TYPE_P(wsdl) != IS_STRING && Z_TYPE_P(wsdl) != IS_NULL) {
       
    50  		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
       
    51  	}
       
    52 -	
       
    53 +
       
    54  	service = emalloc(sizeof(soapService));
       
    55  	memset(service, 0, sizeof(soapService));
       
    56  	service->send_errors = 1;
       
    57 @@ -1155,7 +1155,7 @@ PHP_METHOD(SoapServer, SoapServer)
       
    58  		if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
       
    59  		    Z_TYPE_PP(tmp) == IS_STRING) {
       
    60  			xmlCharEncodingHandlerPtr encoding;
       
    61 -		
       
    62 +
       
    63  			encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
       
    64  			if (encoding == NULL) {
       
    65  				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
       
    66 @@ -1215,7 +1215,7 @@ PHP_METHOD(SoapServer, SoapServer)
       
    67  			}
       
    68  		}
       
    69  	}
       
    70 -	
       
    71 +
       
    72  	if (typemap_ht) {
       
    73  		service->typemap = soap_create_typemap(service->sdl, typemap_ht TSRMLS_CC);
       
    74  	}
       
    75 @@ -1345,7 +1345,7 @@ PHP_METHOD(SoapServer, getFunctions)
       
    76  	if (zend_parse_parameters_none() == FAILURE) {
       
    77  		return;
       
    78  	}
       
    79 -	
       
    80 +
       
    81  	FETCH_THIS_SERVICE(service);
       
    82  
       
    83  	array_init(return_value);
       
    84 @@ -1505,7 +1505,7 @@ PHP_METHOD(SoapServer, handle)
       
    85  
       
    86  	FETCH_THIS_SERVICE(service);
       
    87  	SOAP_GLOBAL(soap_version) = service->version;
       
    88 -	
       
    89 +
       
    90  	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &arg, &arg_len) == FAILURE) {
       
    91  		return;
       
    92  	}
       
    93 @@ -1930,7 +1930,7 @@ PHP_METHOD(SoapServer, handle)
       
    94  
       
    95  		if (size == 0) {
       
    96  			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Dump memory failed");
       
    97 -		} 	
       
    98 +		}
       
    99  
       
   100  		if (soap_version == SOAP_1_2) {
       
   101  			sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
       
   102 @@ -2147,10 +2147,10 @@ static void soap_error_handler(int error_num, const char *error_filename, const
       
   103  		     use_exceptions = 1;
       
   104  		}
       
   105  
       
   106 -		if ((error_num == E_USER_ERROR || 
       
   107 -		     error_num == E_COMPILE_ERROR || 
       
   108 +		if ((error_num == E_USER_ERROR ||
       
   109 +		     error_num == E_COMPILE_ERROR ||
       
   110  		     error_num == E_CORE_ERROR ||
       
   111 -		     error_num == E_ERROR || 
       
   112 +		     error_num == E_ERROR ||
       
   113  		     error_num == E_PARSE) &&
       
   114  		    use_exceptions) {
       
   115  			zval *fault, *exception;
       
   116 @@ -2219,10 +2219,10 @@ static void soap_error_handler(int error_num, const char *error_filename, const
       
   117  		va_list argcopy;
       
   118  #endif
       
   119  
       
   120 -		if (error_num == E_USER_ERROR || 
       
   121 -		    error_num == E_COMPILE_ERROR || 
       
   122 +		if (error_num == E_USER_ERROR ||
       
   123 +		    error_num == E_COMPILE_ERROR ||
       
   124  		    error_num == E_CORE_ERROR ||
       
   125 -		    error_num == E_ERROR || 
       
   126 +		    error_num == E_ERROR ||
       
   127  		    error_num == E_PARSE) {
       
   128  
       
   129  			char* code = SOAP_GLOBAL(error_code);
       
   130 @@ -2452,13 +2452,13 @@ PHP_METHOD(SoapClient, SoapClient)
       
   131  		if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
       
   132  		    Z_TYPE_PP(tmp) == IS_STRING) {
       
   133  			xmlCharEncodingHandlerPtr encoding;
       
   134 -		
       
   135 +
       
   136  			encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
       
   137  			if (encoding == NULL) {
       
   138  				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
       
   139  			} else {
       
   140  				xmlCharEncCloseFunc(encoding);
       
   141 -				add_property_stringl(this_ptr, "_encoding", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);			
       
   142 +				add_property_stringl(this_ptr, "_encoding", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
       
   143  			}
       
   144  		}
       
   145  		if (zend_hash_find(ht, "classmap", sizeof("classmap"), (void**)&tmp) == SUCCESS &&
       
   146 @@ -2493,7 +2493,7 @@ PHP_METHOD(SoapClient, SoapClient)
       
   147  		if (context) {
       
   148  			add_property_resource(this_ptr, "_stream_context", context->rsrc_id);
       
   149  		}
       
   150 -	
       
   151 +
       
   152  		if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS &&
       
   153  		    Z_TYPE_PP(tmp) == IS_LONG) {
       
   154  			cache_wsdl = Z_LVAL_PP(tmp);
       
   155 @@ -2503,7 +2503,7 @@ PHP_METHOD(SoapClient, SoapClient)
       
   156  		    Z_TYPE_PP(tmp) == IS_STRING) {
       
   157  			add_property_stringl(this_ptr, "_user_agent", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
       
   158  		}
       
   159 -		
       
   160 +
       
   161  		if (zend_hash_find(ht, "keep_alive", sizeof("keep_alive"), (void**)&tmp) == SUCCESS &&
       
   162  				(Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) && Z_LVAL_PP(tmp) == 0) {
       
   163  			add_property_long(this_ptr, "_keep_alive", 0);
       
   164 @@ -2606,7 +2606,7 @@ static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *act
       
   165  	xmlFree(buf);
       
   166  	if (ret && zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
       
   167  	  return FALSE;
       
   168 -	}	  
       
   169 +	}
       
   170    return ret;
       
   171  }
       
   172  
       
   173 @@ -2903,8 +2903,10 @@ PHP_METHOD(SoapClient, __call)
       
   174  			}
       
   175  			zend_hash_internal_pointer_reset(default_headers);
       
   176  			while (zend_hash_get_current_data(default_headers, (void**)&tmp) == SUCCESS) {
       
   177 -				Z_ADDREF_PP(tmp);
       
   178 -				zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
       
   179 +				if(Z_TYPE_PP(tmp) == IS_OBJECT) {
       
   180 +					Z_ADDREF_PP(tmp);
       
   181 +					zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
       
   182 +				}
       
   183  				zend_hash_move_forward(default_headers);
       
   184  			}
       
   185  		} else {
       
   186 @@ -2912,7 +2914,7 @@ PHP_METHOD(SoapClient, __call)
       
   187  			free_soap_headers = 0;
       
   188  		}
       
   189  	}
       
   190 -	
       
   191 +
       
   192  	arg_count = zend_hash_num_elements(Z_ARRVAL_P(args));
       
   193  
       
   194  	if (arg_count > 0) {
       
   195 @@ -2978,7 +2980,7 @@ PHP_METHOD(SoapClient, __getTypes)
       
   196  	HashPosition pos;
       
   197  
       
   198  	FETCH_THIS_SDL(sdl);
       
   199 -	
       
   200 +
       
   201  	if (zend_parse_parameters_none() == FAILURE) {
       
   202  		return;
       
   203  	}
       
   204 @@ -3007,7 +3009,7 @@ PHP_METHOD(SoapClient, __getTypes)
       
   205  PHP_METHOD(SoapClient, __getLastRequest)
       
   206  {
       
   207  	zval **tmp;
       
   208 -	
       
   209 +
       
   210  	if (zend_parse_parameters_none() == FAILURE) {
       
   211  		return;
       
   212  	}
       
   213 @@ -3030,7 +3032,7 @@ PHP_METHOD(SoapClient, __getLastResponse)
       
   214  	if (zend_parse_parameters_none() == FAILURE) {
       
   215  		return;
       
   216  	}
       
   217 -	
       
   218 +
       
   219  	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_response", sizeof("__last_response"), (void **)&tmp) == SUCCESS &&
       
   220  	    Z_TYPE_PP(tmp) == IS_STRING) {
       
   221  		RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
       
   222 @@ -3045,11 +3047,11 @@ PHP_METHOD(SoapClient, __getLastResponse)
       
   223  PHP_METHOD(SoapClient, __getLastRequestHeaders)
       
   224  {
       
   225  	zval **tmp;
       
   226 -	
       
   227 +
       
   228  	if (zend_parse_parameters_none() == FAILURE) {
       
   229  		return;
       
   230  	}
       
   231 -	
       
   232 +
       
   233  	if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_request_headers", sizeof("__last_request_headers"), (void **)&tmp) == SUCCESS &&
       
   234  	    Z_TYPE_PP(tmp) == IS_STRING) {
       
   235  		RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
       
   236 @@ -3064,7 +3066,7 @@ PHP_METHOD(SoapClient, __getLastRequestHeaders)
       
   237  PHP_METHOD(SoapClient, __getLastResponseHeaders)
       
   238  {
       
   239  	zval **tmp;
       
   240 -	
       
   241 +
       
   242  	if (zend_parse_parameters_none() == FAILURE) {
       
   243  		return;
       
   244  	}
       
   245 @@ -3209,10 +3211,10 @@ PHP_METHOD(SoapClient, __setSoapHeaders)
       
   246  
       
   247  
       
   248  /* {{{ proto string SoapClient::__setLocation([string new_location])
       
   249 -   Sets the location option (the endpoint URL that will be touched by the 
       
   250 +   Sets the location option (the endpoint URL that will be touched by the
       
   251     following SOAP requests).
       
   252     If new_location is not specified or null then SoapClient will use endpoint
       
   253 -   from WSDL file. 
       
   254 +   from WSDL file.
       
   255     The function returns old value of location options. */
       
   256  PHP_METHOD(SoapClient, __setLocation)
       
   257  {
       
   258 @@ -3261,10 +3263,10 @@ static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, cha
       
   259  	if (Z_TYPE_P(obj) != IS_OBJECT) {
       
   260  		object_init_ex(obj, soap_fault_class_entry);
       
   261  	}
       
   262 -	
       
   263 +
       
   264  	add_property_string(obj, "faultstring", fault_string ? fault_string : "", 1);
       
   265  	zend_update_property_string(zend_exception_get_default(TSRMLS_C), obj, "message", sizeof("message")-1, (fault_string ? fault_string : "") TSRMLS_CC);
       
   266 -	
       
   267 +
       
   268  	if (fault_code != NULL) {
       
   269  		int soap_version = SOAP_GLOBAL(soap_version);
       
   270  
       
   271 @@ -3689,7 +3691,7 @@ ignore_header:
       
   272  		func = func->children;
       
   273  	}
       
   274  	deserialize_parameters(func, function, num_params, parameters TSRMLS_CC);
       
   275 -	
       
   276 +
       
   277  	encode_finish();
       
   278  
       
   279  	return function;
       
   280 @@ -3971,8 +3973,8 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
       
   281  		}
       
   282  
       
   283  		if (fault_ns == NULL &&
       
   284 -		    fault && 
       
   285 -		    fault->details && 
       
   286 +		    fault &&
       
   287 +		    fault->details &&
       
   288  		    zend_hash_num_elements(fault->details) == 1) {
       
   289  			sdlParamPtr sparam;
       
   290  
       
   291 @@ -3996,7 +3998,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
       
   292  					xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
       
   293  					xmlNodeSetContent(node, code);
       
   294  					xmlFree(code);
       
   295 -				} else {	
       
   296 +				} else {
       
   297  					xmlNodeSetContentLen(node, BAD_CAST(str), (int)new_len);
       
   298  				}
       
   299  				efree(str);
       
   300 @@ -4022,7 +4024,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
       
   301  					xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
       
   302  					xmlNodeSetContent(node, code);
       
   303  					xmlFree(code);
       
   304 -				} else {	
       
   305 +				} else {
       
   306  					xmlNodeSetContentLen(node, BAD_CAST(str), (int)new_len);
       
   307  				}
       
   308  				efree(str);
       
   309 @@ -4194,7 +4196,7 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
       
   310  
       
   311  	encode_finish();
       
   312  
       
   313 -	if (function && function->responseName == NULL && 
       
   314 +	if (function && function->responseName == NULL &&
       
   315  	    body->children == NULL && head == NULL) {
       
   316  		xmlFreeDoc(doc);
       
   317  		return NULL;
       
   318 @@ -4328,11 +4330,18 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
       
   319  	if (head) {
       
   320  		zval** header;
       
   321  
       
   322 -		zend_hash_internal_pointer_reset(soap_headers);
       
   323 -		while (zend_hash_get_current_data(soap_headers,(void**)&header) == SUCCESS) {
       
   324 -			HashTable *ht = Z_OBJPROP_PP(header);
       
   325 +		for(zend_hash_internal_pointer_reset(soap_headers);
       
   326 +				zend_hash_get_current_data(soap_headers,(void**)&header) == SUCCESS;
       
   327 +				zend_hash_move_forward(soap_headers)
       
   328 +			) {
       
   329 +			HashTable *ht;
       
   330  			zval **name, **ns, **tmp;
       
   331  
       
   332 +			if (Z_TYPE_PP(header) != IS_OBJECT) {
       
   333 +				continue;
       
   334 +			}
       
   335 +
       
   336 +			ht = Z_OBJPROP_PP(header);
       
   337  			if (zend_hash_find(ht, "name", sizeof("name"), (void**)&name) == SUCCESS &&
       
   338  			    Z_TYPE_PP(name) == IS_STRING &&
       
   339  			    zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&ns) == SUCCESS &&
       
   340 @@ -4371,7 +4380,6 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
       
   341  				xmlSetNs(h, nsptr);
       
   342  				set_soap_header_attributes(h, ht, version);
       
   343  			}
       
   344 -			zend_hash_move_forward(soap_headers);
       
   345  		}
       
   346  	}
       
   347  
       
   348 @@ -4482,7 +4490,7 @@ static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int inde
       
   349  			return *tmp;
       
   350  		} else {
       
   351  			HashPosition pos;
       
   352 -		
       
   353 +
       
   354  			zend_hash_internal_pointer_reset_ex(ht, &pos);
       
   355  			while (zend_hash_get_current_data_ex(ht, (void **)&tmp, &pos) != FAILURE) {
       
   356  				if ((*tmp)->paramName && strcmp(param_name, (*tmp)->paramName) == 0) {
       
   357 diff --git a/ext/soap/tests/bug70388.phpt b/ext/soap/tests/bug70388.phpt
       
   358 new file mode 100644
       
   359 index 0000000..49a8efc
       
   360 --- /dev/null
       
   361 +++ b/ext/soap/tests/bug70388.phpt
       
   362 @@ -0,0 +1,17 @@
       
   363 +--TEST--
       
   364 +Bug #70388 (SOAP serialize_function_call() type confusion / RCE)
       
   365 +--SKIPIF--
       
   366 +<?php require_once('skipif.inc'); ?>
       
   367 +--FILE--
       
   368 +<?php
       
   369 +$dummy = unserialize('O:10:"SoapClient":3:{s:3:"uri";s:1:"X";s:8:"location";s:22:"http://localhost/a.xml";s:17:"__default_headers";a:1:{i:1;s:1337:"'.str_repeat("X", 1337).'";}}');
       
   370 +try {
       
   371 +	var_dump($dummy->notexisting());
       
   372 +} catch(Exception $e) {
       
   373 +	var_dump($e->getMessage());
       
   374 +	var_dump(get_class($e));
       
   375 +}
       
   376 +?>
       
   377 +--EXPECTF--
       
   378 +string(%d) "%s"
       
   379 +string(9) "SoapFault"
       
   380 \ No newline at end of file
       
   381 -- 
       
   382 2.1.4
       
   383 
       
   384