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

From: Date: Mon, 22 Jul 2019 20:02:16 +0000
Subject: Bug #78322 [Opn->Csd]: 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-221898@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:         nikic@php.net
 Reported by:        contact at scannell-infosec dot net
 Summary:            Integer overflow in mb_strpos allows to bypass
                     security related checks
-Status:             Open
+Status:             Closed
 Type:               Bug
 Package:            mbstring related
 Operating System:   N/A
 PHP Version:        7.2.20
-Assigned To:        
+Assigned To:        nikic
 Block user comment: N
 Private report:     N

 New Comment:

This is already fixed in PHP 7.3, where libmbfl was migrated to use size_t.


Previous Comments:
------------------------------------------------------------------------
[2019-07-22 19:48:17] stas@php.net

Looks like a contrived example, requiring special settings to reproduce. Per https://wiki.php.net/security not a security issue.

------------------------------------------------------------------------
[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


Thread (1 message)

  • nikic@php.net
  • Unknown Message
    • nikic@php.net
« previous php.bugs (#221898) next »