Sec Bug->Bug #78322 [Opn]: Integer overflow in mb_strpos allows to bypass security related checks

From: Date: Mon, 22 Jul 2019 19:48:17 +0000
Subject: Sec Bug->Bug #78322 [Opn]: Integer overflow in mb_strpos allows to bypass security related checks
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-221897@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=78322&edit=1 ID: 78322 Updated by: stas@php.net Reported by: contact at scannell-infosec dot net Summary: Integer overflow in mb_strpos allows to bypass security related checks Status: Open -Type: Security +Type: Bug Package: mbstring related Operating System: N/A PHP Version: 7.2.20 Block user comment: N Private report: Y New Comment: Looks like a contrived example, requiring special settings to reproduce. Per https://wiki.php.net/security not a security issue. Previous Comments: ------------------------------------------------------------------------ [2019-07-22 19:24:42] contact at scannell-infosec dot net Description: ------------ The PHP function mb_strpos returns the index of the needle within the haystack. PHP_FUNCTION(mb_strpos) { ... n = mbfl_strpos(&haystack, &needle, offset, reverse); if (n >= 0) { RETVAL_LONG(n); } else { switch (-n) { case 1: break; case 2: php_error_docref(NULL, E_WARNING, "Needle has not positive length"); break; case 4: php_error_docref(NULL, E_WARNING, "Unknown encoding or conversion error"); break; case 8: php_error_docref(NULL, E_NOTICE, "Argument is empty"); break; default: php_error_docref(NULL, E_WARNING, "Unknown error in mb_strpos"); int(1073741824) PHP Warning: mb_strpos(): Unknown error in mb_strpos in /tmp/testscript.php on line 4 bool(false) break; } RETVAL_FALSE; } depending on the return value of mbfl_strpos, either the index is returned if it positive or if it is negative, false is returned. It is possible to force mb_strpos to always return false. This is due to an integer overflow in mbfl_strpos. int mbfl_strpos( mbfl_string *haystack, mbfl_string *needle, int offset, int reverse) { int result; This is because the resulting index is stored in a signed 32 bit integer. If the index of the needle is outside of the range 2^31, the result is negative, thus false is returned. This makes it possible to hide dangerous values that are searched for with mb_strpos, eg. PHP code or invalid characters Test script: --------------- <?php ini_set("memory_limit", -1); var_dump(mb_strpos(str_repeat('A', pow(2, 30)) . 'B', 'B')); var_dump(mb_strpos(str_repeat('A', pow(2, 31)) . 'B', 'B')); Expected result: ---------------- int(1073741824) int(2147483649) Actual result: -------------- int(1073741824) PHP Warning: mb_strpos(): Unknown error in mb_strpos in /tmp/testscript.php on line 4 bool(false) ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=78322&edit=1

« previous php.bugs (#221897) next »