From 32847301899cf711659de441111cb7cd150604b6 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Tue, 14 Jan 2025 14:15:21 +0700 Subject: [PATCH] fix: ensure csrf token is string --- system/Security/Security.php | 2 +- tests/system/Security/SecurityTest.php | 45 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/system/Security/Security.php b/system/Security/Security.php index b6d2660295b9..9cb64561e0f3 100644 --- a/system/Security/Security.php +++ b/system/Security/Security.php @@ -307,7 +307,7 @@ private function getPostedToken(RequestInterface $request): ?string // Does the token exist in POST, HEADER or optionally php:://input - json data or PUT, DELETE, PATCH - raw data. if ($tokenValue = $request->getPost($this->config->tokenName)) { - return $tokenValue; + return is_string($tokenValue) ? $tokenValue : null; } if ($request->hasHeader($this->config->headerName) diff --git a/tests/system/Security/SecurityTest.php b/tests/system/Security/SecurityTest.php index f8799230e056..54115a4d843f 100644 --- a/tests/system/Security/SecurityTest.php +++ b/tests/system/Security/SecurityTest.php @@ -25,6 +25,8 @@ use Config\Security as SecurityConfig; use PHPUnit\Framework\Attributes\BackupGlobals; use PHPUnit\Framework\Attributes\Group; +use ReflectionClass; +use ReflectionMethod; /** * @internal @@ -49,6 +51,16 @@ private function createMockSecurity(?SecurityConfig $config = null): MockSecurit return new MockSecurity($config); } + private function getPostedTokenMethod(): ReflectionMethod + { + $reflection = new ReflectionClass(Security::class); + $method = $reflection->getMethod('getPostedToken'); + + $method->setAccessible(true); + + return $method; + } + public function testBasicConfigIsSaved(): void { $security = $this->createMockSecurity(); @@ -315,4 +327,37 @@ public function testGetters(): void $this->assertIsString($security->getCookieName()); $this->assertIsBool($security->shouldRedirect()); } + + public function testGetPostedTokenReturnsTokenWhenValid(): void + { + $method = $this->getPostedTokenMethod(); + $security = $this->createMockSecurity(); + + $_POST['csrf_test_name'] = '8b9218a55906f9dcc1dc263dce7f005a'; + $request = $this->createIncomingRequest(); + + $this->assertSame('8b9218a55906f9dcc1dc263dce7f005a', $method->invoke($security, $request)); + } + + public function testGetPostedTokenReturnsNullWhenEmpty(): void + { + $method = $this->getPostedTokenMethod(); + $security = $this->createMockSecurity(); + + $_POST = []; + $request = $this->createIncomingRequest(); + + $this->assertNull($method->invoke($security, $request)); + } + + public function testGetPostedTokenReturnsNullWhenMaliciousData(): void + { + $method = $this->getPostedTokenMethod(); + $security = $this->createMockSecurity(); + + $_POST['csrf_test_name'] = ['malicious' => 'data']; + $request = $this->createIncomingRequest(); + + $this->assertNull($method->invoke($security, $request)); + } }