From 4380d7d1552f498f43ff3bb6d6056b2cd7a6bce4 Mon Sep 17 00:00:00 2001 From: Maxime Rainville Date: Tue, 6 Aug 2019 22:00:01 +1200 Subject: [PATCH] API Add option to disable user-agent header session validation --- .../18_Cookies_And_Sessions/02_Sessions.md | 13 ++++++++++ src/Control/Session.php | 10 ++++++- tests/php/Control/SessionTest.php | 26 ++++++++++++++++++- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/docs/en/02_Developer_Guides/18_Cookies_And_Sessions/02_Sessions.md b/docs/en/02_Developer_Guides/18_Cookies_And_Sessions/02_Sessions.md index 2301394e3..fc2ac257f 100644 --- a/docs/en/02_Developer_Guides/18_Cookies_And_Sessions/02_Sessions.md +++ b/docs/en/02_Developer_Guides/18_Cookies_And_Sessions/02_Sessions.md @@ -110,6 +110,19 @@ SilverStripe\Control\Session: This uses the session_name `SECSESSID` for `https` connections instead of the default `PHPSESSID`. Doing so adds an extra layer of security to your session cookie since you no longer share `http` and `https` sessions. +## Relaxing checks around user agent strings + +Out of the box, SilverStripe will invalidate a user's session if the `User-Agent` header changes. This provides some supplemental protection against session high-jacking attacks. + +It is possible to disable the user agent header session validation. However, it is not recommended. + +To disable the user agent session check, add the following code snippet to your project's YML configuration. + +```yml +SilverStripe\Control\Session: + strict_user_agent_check: false +``` + ## API Documentation diff --git a/src/Control/Session.php b/src/Control/Session.php index f0761c80e..24858d4bf 100644 --- a/src/Control/Session.php +++ b/src/Control/Session.php @@ -144,6 +144,14 @@ class Session */ private static $sessionCacheLimiter = ''; + /** + * Invalidate the session if user agent header changes between request. Defaults to true. Disabling this checks is + * not recommended. + * @var bool + * @config + */ + private static $strict_user_agent_check = true; + /** * Session data. * Will be null if session has not been started @@ -223,7 +231,7 @@ class Session } // Funny business detected! - if (isset($this->data['HTTP_USER_AGENT'])) { + if (self::config()->get('strict_user_agent_check') && isset($this->data['HTTP_USER_AGENT'])) { if ($this->data['HTTP_USER_AGENT'] !== $this->userAgent($request)) { $this->clearAll(); $this->destroy(); diff --git a/tests/php/Control/SessionTest.php b/tests/php/Control/SessionTest.php index 6020df9a3..79c74d682 100644 --- a/tests/php/Control/SessionTest.php +++ b/tests/php/Control/SessionTest.php @@ -285,7 +285,31 @@ class SessionTest extends SapphireTest // Verify the new session reset our values $s2 = new Session($s); $s2->init($req2); - $this->assertNotEquals($s2->get('val'), 123); + $this->assertEmpty($s2->get('val')); + } + + public function testDisabledUserAgentLockout() + { + Session::config()->set('strict_user_agent_check', false); + + // Set a user agent + $req1 = new HTTPRequest('GET', '/'); + $req1->addHeader('User-Agent', 'Test Agent'); + + // Generate our session + $s = new Session([]); + $s->init($req1); + $s->set('val', 123); + $s->finalize($req1); + + // Change our UA + $req2 = new HTTPRequest('GET', '/'); + $req2->addHeader('User-Agent', 'Fake Agent'); + + // Verify the new session reset our values + $s2 = new Session($s); + $s2->init($req2); + $this->assertEquals($s2->get('val'), 123); } public function testSave()