core icon indicating copy to clipboard operation
core copied to clipboard

GET parameters are parsed incorrectly when base64 string is passed through GET

Open mumnik opened this issue 7 years ago • 19 comments

Latest core update disabled some my one process. While investigating the issue I've discovered that $_GET is being overwritten in Input_Instance class, uri(). When param contains + or may be some other special characters parse_str performs incorrect by replacing + with space. For now i've disabled GET overwriting but guess this needs to be fixed.

mumnik avatar Nov 25 '18 00:11 mumnik

You need to urlencode() your URL parameters, a + is not allowed in a URL as it is the placeholder for a space.

WanWizard avatar Nov 25 '18 09:11 WanWizard

Params are coming urlencoded

mumnik avatar Nov 25 '18 14:11 mumnik

If that is the cause, then a + is correctly translated into a space.

If not, please provide an example of a URL.

WanWizard avatar Nov 26 '18 12:11 WanWizard

I have to hide some parts because there is sensitive data, bet the problem part is unchanged, it's the "VK_MAC" param GET /site/cart/callback?VK_SERVICE=1101&VK_VERSION=008&VK_SND_ID=HP&VK_REC_ID=FRT&VK_STAMP=131239&VK_T_NO=279&VK_AMOUNT=21.4&VK_CURR=EUR&VK_REC_ACC=LV41HABA0551035980071&VK_REC_NAME=TECHNOLOGY+SIA&VK_SND_ACC=LV&VK_SND_NAME=KIS&VK_REF=131239&VK_MSG=p.l%2C+Pas%C5%ABt%C4%ABjuma+numurs%3A+00131239&VK_T_DATE=25.11.2018&VK_LANG=LAT&VK_AUTO=Y&VK_MAC=Hjr3N%2Fuwt27m9Sy0ncdECEu%2FyJycWoZXEH%2FX4vdkz%2Bs9jaG1cvK56SgEZ%2BB1EqJ2bShX4v%2FkG%2BYG4UgJWOAqMKTukvmeMLouV1CQ0GParFguu81THO7YVhe0PZxEKVxmPdI6pVm35c%2F99d8acDipznrruZOAH8d7S7ta00G5jNU%3D&VK_ENCODING=UTF-8

mumnik avatar Nov 26 '18 19:11 mumnik

That decodes to

array(19) {
  'VK_SERVICE' =>
  string(4) "1101"
  'VK_VERSION' =>
  string(3) "008"
  'VK_SND_ID' =>
  string(2) "HP"
  'VK_REC_ID' =>
  string(3) "FRT"
  'VK_STAMP' =>
  string(6) "131239"
  'VK_T_NO' =>
  string(3) "279"
  'VK_AMOUNT' =>
  string(4) "21.4"
  'VK_CURR' =>
  string(3) "EUR"
  'VK_REC_ACC' =>
  string(21) "LV41HABA0551035980071"
  'VK_REC_NAME' =>
  string(14) "TECHNOLOGY SIA"
  'VK_SND_ACC' =>
  string(2) "LV"
  'VK_SND_NAME' =>
  string(3) "KIS"
  'VK_REF' =>
  string(6) "131239"
  'VK_MSG' =>
  string(34) "p.l, Pasūtījuma numurs: 00131239"
  'VK_T_DATE' =>
  string(10) "25.11.2018"
  'VK_LANG' =>
  string(3) "LAT"
  'VK_AUTO' =>
  string(1) "Y"
  'VK_MAC' =>
  string(172) "Hjr3N/uwt27m9Sy0ncdECEu/yJycWoZXEH/X4vdkz+s9jaG1cvK56SgEZ+B1EqJ2bShX4v/kG+YG4UgJWOAqMKTukvmeMLouV1CQ0GParFguu81THO7YVhe0PZxEKVxmPdI6pVm35c/99d8acDipznrruZOAH8d7S7ta00G5jNU="
  'VK_ENCODING' =>
  string(5) "UTF-8"
}

which look fine to me?

WanWizard avatar Nov 26 '18 20:11 WanWizard

somehow i get "Hjr3N/uwt27m9Sy0ncdECEu/yJycWoZXEH/X4vdkz s9jaG1cvK56SgEZ B1EqJ2bShX4v/kG YG4UgJWOAqMKTukvmeMLouV1CQ0GParFguu81THO7YVhe0PZxEKVxmPdI6pVm35c/99d8acDipznrruZOAH8d7S7ta00G5jNU=" instead

mumnik avatar Nov 26 '18 20:11 mumnik

That smells like double decoding. I'll see if I can find the time to create a small debug app tomorrow.

WanWizard avatar Nov 26 '18 20:11 WanWizard

i bet it happens here:

if (strpos($uri, '?') !== false)
		{
			// log this issue
			\Log::write(\Fuel::L_DEBUG, 'Your rewrite rules are incorrect, change "index.php?/$1 [QSA,L]" to "index.php/$1 [L]"!');

			// reset $_GET
			//$_GET = array();

			// lets split the URI up in case it contains a ?.  This would
			// indicate the server requires 'index.php?'
			preg_match('#(.*?)\?(.*)#i', $uri, $matches);

			// If there are matches then lets set everything correctly
			if ( ! empty($matches))
			{
				// first bit is the real uri
				$uri = $matches[1];

				// second bit is the real query string
				$_SERVER['QUERY_STRING'] = $matches[2];
			//	parse_str($matches[2], $_GET);

				// update GET variables
				$_GET = \Security::clean($_GET);

				$this->input_get = $_GET;
			}

		}

You can see $_GET overwriting commented out

mumnik avatar Nov 26 '18 20:11 mumnik

Contents of $_GET is always url decoded, so that's fine. Do you you manually decode again in your app?

WanWizard avatar Nov 26 '18 20:11 WanWizard

no, i event put debug directly in this segment to check

mumnik avatar Nov 26 '18 20:11 mumnik

I can reproduce it, how about:

			// lets split the URI up in case it contains a ?.  This would
			// indicate the server requires 'index.php?'
			preg_match('#(.*?)\?(.*)#i', $uri, $matches);

			// If there are matches then lets set everything correctly
			if ( ! empty($matches))
			{
				// first bit is the real uri
				$uri = $matches[1];

				// second bit is the real query string
				$_SERVER['QUERY_STRING'] = urlencode($matches[2]);

				// update GET variables
				parse_str($_SERVER['QUERY_STRING'], $_GET);
				$_GET = \Security::clean($_GET);
				$this->input_get = $_GET;
			}

let me know if this fixes it for you?

WanWizard avatar Nov 27 '18 18:11 WanWizard

I am having this problem as well it would seem, here is an example parameter:

url?Auth=DBUW1Dc%2bKwPn7eE%2bZuxzg2fnlww%3d

It seems to be properly URL Encoded when I receive it, however, Input::get('Auth') returns:

AUTH: DBUW1Dc KwPn7eE Zuxzg2fnlww=

So it seems to be double URL decoding somehow.

I have tried your last suggestion on November 27th, but that did not fix the issue. Ultimately since I know this is a BASE64 encoded parameter, I am using:

$auth = str_replace(' ', '+', Input::get('Auth', 0));

But that won't work in any other case.

nickhagen avatar Jan 02 '19 13:01 nickhagen

@nickhagen can you try this?

It handles both your example and the one above without issues here.

WanWizard avatar Jan 02 '19 14:01 WanWizard

p.s. (and that is to all), it might be a better idea to do that the DEBUG log entry at the beginning of that code bit says, and fix your rewrite rule, as that code is only executed if your rewriting is wrong.

WanWizard avatar Jan 02 '19 14:01 WanWizard

Well ... the plus signs are definitely correctly interpreted now, however, the equal sign at the end is still url encoded:

DBUW1Dc+KwPn7eE+Zuxzg2fnlww%3D

I tried updating my htaccess file in my public directory to change the rewrite rules as suggested but that didn't seem to change anything.

RewriteRule ^(.*)$ index.php?/$1 [L]

nickhagen avatar Jan 02 '19 15:01 nickhagen

Great. Not.

The problem is that in the QUERY_STRING, the first "=" is also URL encoded. I don't know if this is a bug in PHP or something that has changed, but it didn't used to be the case.

Back to the drawing board...

As to the rewrite rule, if yu use the default htaccess, you have to make sure you change the correct rewrite for your PHP version and type.

WanWizard avatar Jan 02 '19 15:01 WanWizard

Attempt two.

I used this URL for testing:

http://19develop.dev/welcome/index/a%20space/a+plus/?Auth=DBUW1Dc%2bKwPn7eE%2bZuxzg2fnlww%3d&date=2013-10-17T22%3A09%3A24%2B00%3A00

resulting in thse URI segments:

array (size=4)
  0 => string 'welcome' (length=7)
  1 => string 'index' (length=5)
  2 => string 'a space' (length=7)
  3 => string 'a+plus' (length=6)

and these arguments:

array (size=3)
  'Auth' => string 'DBUW1Dc+KwPn7eE+Zuxzg2fnlww=' (length=28)
  'date' => string '2013-10-17T22:09:24+00:00' (length=25)

WanWizard avatar Jan 02 '19 16:01 WanWizard

BAM! That seems to fix it, are there any potential problems that I should look out for with removing that processing line?

nickhagen avatar Jan 02 '19 16:01 nickhagen

It shouldn't. I went through the commit history, appearently the decoding/encoding was added to address some nginx quirk. But the examples given are handled buy this code as well.

I'm closing this issue, let me know if you still find issues.

WanWizard avatar Jan 02 '19 17:01 WanWizard