Soften the cookie check if no cookies are sent

When no cookies are sent it is not required to perform any check for the strict or lax cookie, it does not provide any significant security advantage.

It does however interfer with the Android client which requests thumbnails from the unofficial API at `/index.php/apps/files/api/v1/thumbnail/256/256/{filename}`. This endpoint expects the strict cookie to be existent to not leak the existence of files. The Android client authenticates against this endpoint using Basic Auth and without cookies in some cases at least. This will make these endpoints work again with such cases.

To test this issue the following cURL command once without the patch and once with:

> curl http://localhost/index.php/apps/files/api/v1/thumbnail/256/256/welcome.txt  -u admin -v

Without the patch the request is redirected (which the client does not obey) and with the patch the preview is returned.
This commit is contained in:
Lukas Reschke 2016-06-15 11:50:26 +02:00
parent 7a5093c43e
commit 202530f4f3
No known key found for this signature in database
GPG Key ID: 9AB0ADB949B6898C
3 changed files with 61 additions and 21 deletions

View File

@ -468,12 +468,16 @@ class Request implements \ArrayAccess, \Countable, IRequest {
}
/**
* Checks if the strict cookie has been sent with the request
* Checks if the strict cookie has been sent with the request if the request
* is including any cookies.
*
* @return bool
* @since 9.1.0
*/
public function passesStrictCookieCheck() {
if(count($this->cookies) === 0) {
return true;
}
if($this->getCookie('nc_sameSiteCookiestrict') === 'true'
&& $this->passesLaxCookieCheck()) {
return true;
@ -483,12 +487,17 @@ class Request implements \ArrayAccess, \Countable, IRequest {
}
/**
* Checks if the lax cookie has been sent with the request
* Checks if the lax cookie has been sent with the request if the request
* is including any cookies.
*
* @return bool
* @since 9.1.0
*/
public function passesLaxCookieCheck() {
if(count($this->cookies) === 0) {
return true;
}
if($this->getCookie('nc_sameSiteCookielax') === 'true') {
return true;
}

View File

@ -144,18 +144,20 @@ interface IRequest {
public function passesCSRFCheck();
/**
* Checks if the strict cookie has been sent with the request
*
* @return bool
* @since 9.0.0
*/
* Checks if the strict cookie has been sent with the request if the request
* is including any cookies.
*
* @return bool
* @since 9.0.0
*/
public function passesStrictCookieCheck();
/**
* Checks if the lax cookie has been sent with the request
* Checks if the lax cookie has been sent with the request if the request
* is including any cookies.
*
* @return bool
* @since 9.1.0
* @since 9.0.0
*/
public function passesLaxCookieCheck();

View File

@ -1404,7 +1404,7 @@ class RequestTest extends \Test\TestCase {
$this->assertTrue($request->passesCSRFCheck());
}
public function testFailsCSRFCheckWithGetAndWithoutCookies() {
public function testPassesCSRFCheckWithGetAndWithoutCookies() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
@ -1421,13 +1421,14 @@ class RequestTest extends \Test\TestCase {
])
->getMock();
$this->csrfTokenManager
->expects($this->never())
->method('isTokenValid');
->expects($this->once())
->method('isTokenValid')
->willReturn(true);
$this->assertFalse($request->passesCSRFCheck());
$this->assertTrue($request->passesCSRFCheck());
}
public function testFailsCSRFCheckWithPostAndWithoutCookies() {
public function testPassesCSRFCheckWithPostAndWithoutCookies() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
@ -1444,13 +1445,14 @@ class RequestTest extends \Test\TestCase {
])
->getMock();
$this->csrfTokenManager
->expects($this->never())
->method('isTokenValid');
->expects($this->once())
->method('isTokenValid')
->willReturn(true);
$this->assertFalse($request->passesCSRFCheck());
$this->assertTrue($request->passesCSRFCheck());
}
public function testFailsCSRFCheckWithHeaderAndWithoutCookies() {
public function testPassesCSRFCheckWithHeaderAndWithoutCookies() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
@ -1467,10 +1469,11 @@ class RequestTest extends \Test\TestCase {
])
->getMock();
$this->csrfTokenManager
->expects($this->never())
->method('isTokenValid');
->expects($this->once())
->method('isTokenValid')
->willReturn(true);
$this->assertFalse($request->passesCSRFCheck());
$this->assertTrue($request->passesCSRFCheck());
}
public function testFailsCSRFCheckWithHeaderAndNotAllChecksPassing() {
@ -1523,6 +1526,32 @@ class RequestTest extends \Test\TestCase {
$this->assertTrue($request->passesStrictCookieCheck());
}
public function testFailsSRFCheckWithPostAndWithCookies() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'post' => [
'requesttoken' => 'AAAHGxsTCTc3BgMQESAcNR0OAR0=:MyTotalSecretShareds',
],
'cookies' => [
'foo' => 'bar',
],
],
$this->secureRandom,
$this->config,
$this->csrfTokenManager,
$this->stream
])
->getMock();
$this->csrfTokenManager
->expects($this->never())
->method('isTokenValid');
$this->assertFalse($request->passesCSRFCheck());
}
public function testFailStrictCookieCheckWithOnlyLaxCookie() {
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')