Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion lib/base.php
Original file line number Diff line number Diff line change
Expand Up @@ -506,8 +506,22 @@ private static function sendSameSiteCookies() {
* also we can't directly interfere with PHP's session mechanism.
*/
private static function performSameSiteCookieProtection() {
$request = \OC::$server->getRequest();

// Some user agents are notorious and don't really properly follow HTTP
// specifications. For those, have an automated opt-out. Since the protection
// for remote.php is applied in base.php as starting point we need to opt out
// here.
$incompatibleUserAgents = [
// OS X Finder
'/^WebDAVFS/',
];
if($request->isUserAgent($incompatibleUserAgents)) {
return;
}


if(count($_COOKIE) > 0) {
$request = \OC::$server->getRequest();
$requestUri = $request->getScriptName();
$processingScript = explode('/', $requestUri);
$processingScript = $processingScript[count($processingScript)-1];
Expand Down
17 changes: 15 additions & 2 deletions lib/private/AppFramework/Http/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,19 @@ public function passesCSRFCheck() {
return $this->csrfTokenManager->isTokenValid($token);
}

/**
* Whether the cookie checks are required
*
* @return bool
*/
private function cookieCheckRequired() {
if($this->getCookie(session_name()) === null && $this->getCookie('oc_token') === null) {
return false;
}

return true;
}

/**
* Checks if the strict cookie has been sent with the request if the request
* is including any cookies.
Expand All @@ -493,7 +506,7 @@ public function passesCSRFCheck() {
* @since 9.1.0
*/
public function passesStrictCookieCheck() {
if(count($this->cookies) === 0) {
if(!$this->cookieCheckRequired()) {
return true;
}
if($this->getCookie('nc_sameSiteCookiestrict') === 'true'
Expand All @@ -511,7 +524,7 @@ public function passesStrictCookieCheck() {
* @since 9.1.0
*/
public function passesLaxCookieCheck() {
if(count($this->cookies) === 0) {
if(!$this->cookieCheckRequired()) {
return true;
}
if($this->getCookie('nc_sameSiteCookielax') === 'true') {
Expand Down
78 changes: 77 additions & 1 deletion tests/lib/AppFramework/Http/RequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1469,6 +1469,7 @@ public function testFailsCSRFCheckWithHeaderAndNotAllChecksPassing() {
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
session_name() => 'asdf',
'nc_sameSiteCookiestrict' => 'true',
],
],
Expand All @@ -1495,6 +1496,7 @@ public function testPassesStrictCookieCheckWithAllCookies() {
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
session_name() => 'asdf',
'nc_sameSiteCookiestrict' => 'true',
'nc_sameSiteCookielax' => 'true',
],
Expand All @@ -1509,7 +1511,76 @@ public function testPassesStrictCookieCheckWithAllCookies() {
$this->assertTrue($request->passesStrictCookieCheck());
}

public function testFailsSRFCheckWithPostAndWithCookies() {
public function testPassesStrictCookieCheckWithRandomCookies() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'RandomCookie' => 'asdf',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();

$this->assertTrue($request->passesStrictCookieCheck());
}

public function testFailsStrictCookieCheckWithSessionCookie() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
session_name() => 'asdf',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();

$this->assertFalse($request->passesStrictCookieCheck());
}

public function testFailsStrictCookieCheckWithRememberMeCookie() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'oc_token' => 'asdf',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();

$this->assertFalse($request->passesStrictCookieCheck());
}

public function testFailsCSRFCheckWithPostAndWithCookies() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
Expand All @@ -1519,6 +1590,7 @@ public function testFailsSRFCheckWithPostAndWithCookies() {
'requesttoken' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
session_name() => 'asdf',
'foo' => 'bar',
],
],
Expand All @@ -1545,6 +1617,7 @@ public function testFailStrictCookieCheckWithOnlyLaxCookie() {
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
session_name() => 'asdf',
'nc_sameSiteCookielax' => 'true',
],
],
Expand All @@ -1568,6 +1641,7 @@ public function testFailStrictCookieCheckWithOnlyStrictCookie() {
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
session_name() => 'asdf',
'nc_sameSiteCookiestrict' => 'true',
],
],
Expand All @@ -1591,6 +1665,7 @@ public function testPassesLaxCookieCheck() {
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
session_name() => 'asdf',
'nc_sameSiteCookielax' => 'true',
],
],
Expand All @@ -1614,6 +1689,7 @@ public function testFailsLaxCookieCheckWithOnlyStrictCookie() {
'HTTP_REQUESTTOKEN' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
session_name() => 'asdf',
'nc_sameSiteCookiestrict' => 'true',
],
],
Expand Down