php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Sec Bug #72533 locale_accept_from_http out-of-bounds access
Submitted: 2016-07-03 04:03 UTC Modified: 2016-07-25 15:19 UTC
From: fernando at null-life dot com Assigned: stas (profile)
Status: Closed Package: intl (PECL)
PHP Version: 7.0.8 OS: *
Private report: No CVE-ID: 2016-6294
 [2016-07-03 04:03 UTC] fernando at null-life dot com
Description:
------------
Calling to uloc_acceptLanguageFromHTTP with parameter size "httpAcceptLanguage" equal or greater than ULOC_FULLNAME_CAPACITY + 1, the local variable "tmp" might leave unterminated.

uloc_acceptLanguageFromHTTP doesn’t check status result after call to uloc_canonicalize. This might cause stack data leak. 

This bug is inside libicu but it can be mitigated from PHP checking the user input length (HTTP Accept-Language Header), similar to bug67397-patch 

https://bugs.php.net/patch-display.php?bug_id=67397&patch=bug67397-patch&revision=latest 


if (http_accept_len > ULOC_FULLNAME_CAPACITY) {
  //return an error or maybe truncate the input
}

Since locale_accept_from_http is supposed to accept external user input we believe this should be treated as a security issue. 


Source code

https://github.com/php/php-src/blob/master/ext/intl/locale/locale_methods.c#L1585

PHP_FUNCTION(locale_accept_from_http)
{
	UEnumeration *available;
	char *http_accept = NULL;
	size_t http_accept_len;
	UErrorCode status = 0;
	int len;
	char resultLocale[INTL_MAX_LOCALE_LEN+1];
	UAcceptResult outResult;

	if(zend_parse_parameters( ZEND_NUM_ARGS(), "s", &http_accept, &http_accept_len) == FAILURE)
	{
		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
		"locale_accept_from_http: unable to parse input parameters", 0 );
		RETURN_FALSE;
	}

	available = ures_openAvailableLocales(NULL, &status);
	INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to retrieve locale list");
	len = uloc_acceptLanguageFromHTTP(resultLocale, INTL_MAX_LOCALE_LEN,
						&outResult, http_accept, available, &status);
	uenum_close(available);
	INTL_CHECK_STATUS(status, "locale_accept_from_http: failed to find acceptable locale");
	if (len < 0 || outResult == ULOC_ACCEPT_FAILED) {
		RETURN_FALSE;
	}
	RETURN_STRINGL(resultLocale, len);
}

Test script:
---------------
<?php

$var1=str_repeat("a", 200);
locale_accept_from_http($var1);


Expected result:
----------------
No crash

Actual result:
--------------
 LD_LIBRARY_PATH=/usr/local/icu-57-gcc-asan/lib USE_ZEND_ALLOC=0 ASAN_OPTIONS=detect_leaks=0 /ram/php-fuzz/phuzzer/php-70/sapi/cli/php -n -dextension=/ram/php-fuzz/phuzzer/php-70/modules/intl.so phuzzer2.php
=================================================================
==4186==ERROR: AddressSanitizer: stack-buffer-overflow on address 0xffa09b6e at pc 0xf72198a1 bp 0xffa097d8 sp 0xffa093ac
READ of size 159 at 0xffa09b6e thread T0
    #0 0xf72198a0  (/usr/lib/i386-linux-gnu/libasan.so.2+0x408a0)
    #1 0xf08d0089 in uloc_acceptLanguageFromHTTP /home/user/icu-release-57-1/source/common/uloc.cpp:2353
    #2 0xf119a433 in zif_locale_accept_from_http /home/user/php/php-70-asan/ext/intl/locale/locale_methods.c:1604
    #3 0x9a388ac in ZEND_DO_ICALL_SPEC_HANDLER /home/user/php/php-70-asan/Zend/zend_vm_execute.h:586
    #4 0x980d06f in execute_ex /home/user/php/php-70-asan/Zend/zend_vm_execute.h:414
    #5 0x9b287c5 in zend_execute /home/user/php/php-70-asan/Zend/zend_vm_execute.h:458
    #6 0x95e4c3c in zend_execute_scripts /home/user/php/php-70-asan/Zend/zend.c:1427
    #7 0x932d58b in php_execute_script /home/user/php/php-70-asan/main/main.c:2494
    #8 0x9b31004 in do_cli /home/user/php/php-70-asan/sapi/cli/php_cli.c:974
    #9 0x80a6e78 in main /home/user/php/php-70-asan/sapi/cli/php_cli.c:1344
    #10 0xf6c70636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
    #11 0x80a755a  (/ram/php-fuzz/phuzzer/php-70-asan/sapi/cli/php+0x80a755a)

Address 0xffa09b6e is located in stack of thread T0 at offset 798 in frame
    #0 0xf08cf9f7 in uloc_acceptLanguageFromHTTP /home/user/icu-release-57-1/source/common/uloc.cpp:2290

  This frame has 5 object(s):
    [32, 36) 'myEnd'
    [96, 456) 'smallBuffer'
    [512, 517) 'rep'
    [576, 606) 'buf'
    [640, 798) 'tmp' <== Memory access at offset 798 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow ??:0 ??

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-07-13 05:39 UTC] stas@php.net
-Assigned To: +Assigned To: stas
 [2016-07-13 05:39 UTC] stas@php.net
Fixed in security repo as aa82e99ed8003c01f1ef4f0940e56b85c5b032d4 and in https://gist.github.com/8986d33e2df4ad5b919f21cb7270a7e6
 [2016-07-19 07:47 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=aa82e99ed8003c01f1ef4f0940e56b85c5b032d4
Log: Fix bug #72533 (locale_accept_from_http out-of-bounds access)
 [2016-07-19 07:47 UTC] stas@php.net
-Status: Assigned +Status: Closed
 [2016-07-19 07:53 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=aa82e99ed8003c01f1ef4f0940e56b85c5b032d4
Log: Fix bug #72533 (locale_accept_from_http out-of-bounds access)
 [2016-07-19 08:39 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=aa82e99ed8003c01f1ef4f0940e56b85c5b032d4
Log: Fix bug #72533 (locale_accept_from_http out-of-bounds access)
 [2016-07-19 08:55 UTC] stas@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=aa82e99ed8003c01f1ef4f0940e56b85c5b032d4
Log: Fix bug #72533 (locale_accept_from_http out-of-bounds access)
 [2016-07-25 15:19 UTC] remi@php.net
-CVE-ID: +CVE-ID: 2016-6294
 [2016-10-17 10:11 UTC] bwoebi@php.net
Automatic comment on behalf of stas
Revision: http://git.php.net/?p=php-src.git;a=commit;h=aa82e99ed8003c01f1ef4f0940e56b85c5b032d4
Log: Fix bug #72533 (locale_accept_from_http out-of-bounds access)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC