From e2ed51f20a35966228a298be943757b727dd0360 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 16 Apr 2018 23:23:54 -0400 Subject: [PATCH] Fix mismatched URL comparisions in SecurityComponent. When SecurityComponent was updated to use new request methods, I forgot to take into account base URL paths. In order to get those applied, we can use Router::url(). This ensures we get the same urls that FormHelper creates. I've also fixed an issue where if the session hadn't already been started secured forms would fail as session_id() would return '' instead of the actual session id. Refs #11932 --- .../Component/SecurityComponent.php | 16 ++++++--- .../Component/SecurityComponentTest.php | 34 ++++++++++++++++++- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/Controller/Component/SecurityComponent.php b/src/Controller/Component/SecurityComponent.php index 4ebd65f31fa..db83f249418 100644 --- a/src/Controller/Component/SecurityComponent.php +++ b/src/Controller/Component/SecurityComponent.php @@ -22,6 +22,7 @@ use Cake\Event\Event; use Cake\Http\Exception\BadRequestException; use Cake\Http\ServerRequest; +use Cake\Routing\Router; use Cake\Utility\Hash; use Cake\Utility\Security; @@ -378,14 +379,21 @@ protected function _validToken(Controller $controller) */ protected function _hashParts(Controller $controller) { - $fieldList = $this->_fieldsList($controller->request->getData()); - $unlocked = $this->_sortedUnlocked($controller->request->getData()); + $request = $controller->getRequest(); + + // Start the session to ensure we get the correct session id. + $session = $request->getSession(); + $session->start(); + + $data = $request->getData(); + $fieldList = $this->_fieldsList($data); + $unlocked = $this->_sortedUnlocked($data); return [ - $controller->request->getRequestTarget(), + Router::url($request->getRequestTarget()), serialize($fieldList), $unlocked, - session_id(), + $session->id() ]; } diff --git a/tests/TestCase/Controller/Component/SecurityComponentTest.php b/tests/TestCase/Controller/Component/SecurityComponentTest.php index d5ea4f523eb..2971f31806d 100644 --- a/tests/TestCase/Controller/Component/SecurityComponentTest.php +++ b/tests/TestCase/Controller/Component/SecurityComponentTest.php @@ -21,6 +21,7 @@ use Cake\Event\Event; use Cake\Http\ServerRequest; use Cake\Http\Session; +use Cake\Routing\Router; use Cake\TestSuite\TestCase; use Cake\Utility\Security; @@ -189,7 +190,7 @@ public function tearDown() unset($this->Controller); } - public function validatePost($expectedException = null, $expectedExceptionMessage = null) + public function validatePost($expectedException = 'SecurityException', $expectedExceptionMessage = null) { try { return $this->Controller->Security->validatePost($this->Controller); @@ -744,6 +745,37 @@ public function testValidatePostSimple() $this->assertTrue($result); } + /** + * test validatePost uses full URL + * + * @return void + * @triggers Controller.startup $this->Controller + */ + public function testValidatePostSubdirectory() + { + // set the base path. + $this->Controller->request = $this->Controller->request + ->withAttribute('base', 'subdir') + ->withAttributE('webroot', 'subdir/'); + Router::pushRequest($this->Controller->request); + + $event = new Event('Controller.startup', $this->Controller); + $this->Security->startup($event); + + // Differs from testValidatePostSimple because of base url + $fields = 'cc9b6af3f33147235ae8f8037b0a71399a2425f2%3A'; + $unlocked = ''; + $debug = ''; + + $this->Controller->request = $this->Controller->request->withParsedBody([ + 'Model' => ['username' => '', 'password' => ''], + '_Token' => compact('fields', 'unlocked', 'debug') + ]); + + $result = $this->validatePost(); + $this->assertTrue($result); + } + /** * testValidatePostComplex method *