From 1ac59345738675308fd5a1e47ae56ea15e44750b Mon Sep 17 00:00:00 2001 From: Hash Lin Date: Mon, 25 Mar 2019 22:59:32 +0800 Subject: [PATCH] Dont serialize or unserialize csrf cookie / header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reference: https://github.com/laravel/framework/pull/25121 https://github.com/laravel/framework/commit/9725a8e7d0555474114f5cad9249fe8fe556836c 由於 Laravel 5.1 上游已經沒有再 maintain 了,短時間要升級上去有點困難 故自己將這個 patch 上去,自己來 maintain 這個 5.1 的 security issue hard code `XSRF-TOKEN` 不進行 serialize or unserialize 動作 --- .../Contracts/Encryption/Encrypter.php | 6 +++-- .../Cookie/Middleware/EncryptCookies.php | 22 ++++++++++++++----- src/Illuminate/Encryption/Encrypter.php | 13 +++++++---- .../Http/Middleware/VerifyCsrfToken.php | 2 +- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/Illuminate/Contracts/Encryption/Encrypter.php b/src/Illuminate/Contracts/Encryption/Encrypter.php index 004dfe9a9416..35f7ab084482 100644 --- a/src/Illuminate/Contracts/Encryption/Encrypter.php +++ b/src/Illuminate/Contracts/Encryption/Encrypter.php @@ -8,15 +8,17 @@ interface Encrypter * Encrypt the given value. * * @param string $value + * @param bool $serialize * @return string */ - public function encrypt($value); + public function encrypt($value, $serialize = true); /** * Decrypt the given value. * * @param string $payload + * @param bool $unserialize * @return string */ - public function decrypt($payload); + public function decrypt($payload, $unserialize = false); } diff --git a/src/Illuminate/Cookie/Middleware/EncryptCookies.php b/src/Illuminate/Cookie/Middleware/EncryptCookies.php index c30d38ce9f73..f8a5ed8c82f0 100644 --- a/src/Illuminate/Cookie/Middleware/EncryptCookies.php +++ b/src/Illuminate/Cookie/Middleware/EncryptCookies.php @@ -25,6 +25,15 @@ class EncryptCookies */ protected $except = []; + /** + * The cookies that should not be serialized. + * + * @var array + */ + protected $serialization = [ + 'XSRF-TOKEN' => false, + ]; + /** * Create a new CookieGuard instance. * @@ -73,7 +82,7 @@ protected function decrypt(Request $request) } try { - $request->cookies->set($key, $this->decryptCookie($c)); + $request->cookies->set($key, $this->decryptCookie($key, $c)); } catch (DecryptException $e) { $request->cookies->set($key, null); } @@ -85,14 +94,15 @@ protected function decrypt(Request $request) /** * Decrypt the given cookie and return the value. * + * @param string $name * @param string|array $cookie * @return string|array */ - protected function decryptCookie($cookie) + protected function decryptCookie($name, $cookie) { return is_array($cookie) ? $this->decryptArray($cookie) - : $this->encrypter->decrypt($cookie); + : $this->encrypter->decrypt($cookie, $this->serialization[$name] ?? true); } /** @@ -107,7 +117,7 @@ protected function decryptArray(array $cookie) foreach ($cookie as $key => $value) { if (is_string($value)) { - $decrypted[$key] = $this->encrypter->decrypt($value); + $decrypted[$key] = $this->encrypter->decrypt($value, $this->serialization[$key] ?? true); } } @@ -127,8 +137,10 @@ protected function encrypt(Response $response) continue; } + $serialize = $this->serialization[$cookie->getName()] ?? true; + $response->headers->setCookie($this->duplicate( - $cookie, $this->encrypter->encrypt($cookie->getValue()) + $cookie, $this->encrypter->encrypt($cookie->getValue(), $serialize) )); } diff --git a/src/Illuminate/Encryption/Encrypter.php b/src/Illuminate/Encryption/Encrypter.php index 71a0ddcf4bb6..cd24cfaf9495 100755 --- a/src/Illuminate/Encryption/Encrypter.php +++ b/src/Illuminate/Encryption/Encrypter.php @@ -56,15 +56,19 @@ public static function supported($key, $cipher) * Encrypt the given value. * * @param string $value + * @param bool $serialize * @return string * * @throws \Illuminate\Contracts\Encryption\EncryptException */ - public function encrypt($value) + public function encrypt($value, $serialize = true) { $iv = Str::randomBytes($this->getIvSize()); - $value = \openssl_encrypt(serialize($value), $this->cipher, $this->key, 0, $iv); + $value = \openssl_encrypt( + $serialize ? serialize($value) : $value, + $this->cipher, $this->key, 0, $iv + ); if ($value === false) { throw new EncryptException('Could not encrypt the data.'); @@ -88,11 +92,12 @@ public function encrypt($value) * Decrypt the given value. * * @param string $payload + * @param bool $unserialize * @return string * * @throws \Illuminate\Contracts\Encryption\DecryptException */ - public function decrypt($payload) + public function decrypt($payload, $unserialize = true) { $payload = $this->getJsonPayload($payload); @@ -104,7 +109,7 @@ public function decrypt($payload) throw new DecryptException('Could not decrypt the data.'); } - return unserialize($decrypted); + return $unserialize ? unserialize($decrypted) : $decrypted; } /** diff --git a/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php b/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php index 9caf7fc17b9b..ab4a86f4dd0e 100644 --- a/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php +++ b/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php @@ -87,7 +87,7 @@ protected function tokensMatch($request) $token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN'); if (! $token && $header = $request->header('X-XSRF-TOKEN')) { - $token = $this->encrypter->decrypt($header); + $token = $this->encrypter->decrypt($header, false); } if (! is_string($sessionToken) || ! is_string($token)) {