From c3c1dc62ad73ccac0440cf2a1c0234df0c192267 Mon Sep 17 00:00:00 2001 From: Eugeniu David Date: Thu, 18 Nov 2021 12:24:31 +0100 Subject: [PATCH] SECURITY-5146: encode plus sign only when content-type set to application/x-www-form-urlencoded Co-authored-by: David Szigecsan --- src/Escher/RequestCanonicalizer.php | 16 +++++++++------ test/unit/RequestCanonicalizerTest.php | 28 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 test/unit/RequestCanonicalizerTest.php diff --git a/src/Escher/RequestCanonicalizer.php b/src/Escher/RequestCanonicalizer.php index 1109ce9..5c212fb 100644 --- a/src/Escher/RequestCanonicalizer.php +++ b/src/Escher/RequestCanonicalizer.php @@ -11,7 +11,7 @@ public static function canonicalize($method, $requestUri, $payload, $rawHeaders, $lines = array(); $lines[] = strtoupper($method); $lines[] = self::normalizePath($path); - $lines[] = self::urlEncodeQueryString($query); + $lines[] = self::urlEncodeQueryString($query, $rawHeaders); sort($headersToSign); $lines = array_merge($lines, self::canonicalizeHeaders($rawHeaders, $headersToSign)); @@ -24,7 +24,7 @@ public static function canonicalize($method, $requestUri, $payload, $rawHeaders, return implode("\n", $lines); } - public static function urlEncodeQueryString($query) + public static function urlEncodeQueryString($query, $headers) { if (empty($query)) { return ''; @@ -40,8 +40,8 @@ public static function urlEncodeQueryString($query) $keyValues[0] = urldecode($keyValues[0]); $keyValues[1] = urldecode($keyValues[1]); $encodedParts[] = implode('=', array( - self::rawUrlEncode(str_replace('+', ' ', $keyValues[0])), - self::rawUrlEncode(str_replace('+', ' ', $keyValues[1])), + self::rawUrlEncode($keyValues[0], $headers), + self::rawUrlEncode($keyValues[1], $headers), )); } sort($encodedParts); @@ -93,9 +93,13 @@ private static function canonicalizeHeaders($rawHeaders, array $headersToSign) return $result; } - private static function rawUrlEncode($urlComponent) + private static function rawUrlEncode($urlComponent, $headers) { - $result = rawurlencode($urlComponent); + if(strpos($headers, "application/x-www-form-urlencoded")) { + $result = rawurlencode(str_replace('+', ' ', $urlComponent)); + } else { + $result = rawurlencode($urlComponent); + } if (version_compare(PHP_VERSION, '5.3.4') === -1) { $result = str_replace('%7E', '~', $result); } diff --git a/test/unit/RequestCanonicalizerTest.php b/test/unit/RequestCanonicalizerTest.php new file mode 100644 index 0000000..9b7517e --- /dev/null +++ b/test/unit/RequestCanonicalizerTest.php @@ -0,0 +1,28 @@ +assertEquals($query, $result); + } + + /** + * @test + */ + public function urlEncodeQueryStringShouldReplacePlusSignWithSplace() + { + $query = "email=test%2Bbayxd%40gmail.com"; + $expected = "email=test%20bayxd%40gmail.com"; + $result = RequestCanonicalizer::urlEncodeQueryString($query, "application/x-www-form-urlencoded"); + $this->assertEquals($expected, $result); + } +} \ No newline at end of file