From b780c4f504555e5ae2d3861f8772f87ab20e016e Mon Sep 17 00:00:00 2001 From: Maxime Rainville Date: Thu, 9 Jul 2020 13:33:43 +1200 Subject: [PATCH 1/8] BUG Tweak DBHTMLText::Plain to avoid treating some chinese characters as line breaks. --- src/ORM/FieldType/DBHTMLText.php | 2 +- tests/php/ORM/DBHTMLTextTest.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ORM/FieldType/DBHTMLText.php b/src/ORM/FieldType/DBHTMLText.php index 8145281b0..262f0a3cb 100644 --- a/src/ORM/FieldType/DBHTMLText.php +++ b/src/ORM/FieldType/DBHTMLText.php @@ -228,7 +228,7 @@ class DBHTMLText extends DBText $text = strip_tags($text); // Implode >3 consecutive linebreaks into 2 - $text = preg_replace('~(\R){2,}~', "\n\n", $text); + $text = preg_replace('~(\R){2,}~u', "\n\n", $text); // Decode HTML entities back to plain text return trim(Convert::xml2raw($text)); diff --git a/tests/php/ORM/DBHTMLTextTest.php b/tests/php/ORM/DBHTMLTextTest.php index 068951707..55f3ecd8f 100644 --- a/tests/php/ORM/DBHTMLTextTest.php +++ b/tests/php/ORM/DBHTMLTextTest.php @@ -265,6 +265,10 @@ class DBHTMLTextTest extends SapphireTest [ '

Collapses

Excessive


Newlines

', "Collapses\n\nExcessive\n\nNewlines", + ], + 'Unicode character that could be confused for a line break' =>[ + '充美好实的一天', + '充美好实的一天' ] ]; } From 107706c12cd9cf4d1b8b96b6a6e223633209d851 Mon Sep 17 00:00:00 2001 From: Maxime Rainville Date: Tue, 12 May 2020 10:58:30 +1200 Subject: [PATCH 2/8] [CVE-2019-19326] Stop honouring X-HTTP-Method-Override header, X-Original-Url header and _method POST variable. Add SS_HTTPRequest::setHttpMethod() --- src/Control/HTTPRequest.php | 45 ++++++++---- src/Control/HTTPRequestBuilder.php | 10 --- tests/php/Control/HTTPRequestTest.php | 101 ++++++++++++++++++++------ 3 files changed, 107 insertions(+), 49 deletions(-) diff --git a/src/Control/HTTPRequest.php b/src/Control/HTTPRequest.php index 150bcb733..86a7e273b 100644 --- a/src/Control/HTTPRequest.php +++ b/src/Control/HTTPRequest.php @@ -18,9 +18,6 @@ use SilverStripe\ORM\ArrayLib; * The intention is that a single HTTPRequest object can be passed from one object to another, each object calling * match() to get the information that they need out of the URL. This is generally handled by * {@link RequestHandler::handleRequest()}. - * - * @todo Accept X_HTTP_METHOD_OVERRIDE http header and $_REQUEST['_method'] to override request types (useful for - * webclients not supporting PUT and DELETE) */ class HTTPRequest implements ArrayAccess { @@ -156,7 +153,7 @@ class HTTPRequest implements ArrayAccess */ public function __construct($httpMethod, $url, $getVars = array(), $postVars = array(), $body = null) { - $this->httpMethod = strtoupper(self::detect_method($httpMethod, $postVars)); + $this->httpMethod = strtoupper($httpMethod); $this->setUrl($url); $this->getVars = (array) $getVars; $this->postVars = (array) $postVars; @@ -830,6 +827,21 @@ class HTTPRequest implements ArrayAccess return $this->httpMethod; } + /** + * Explicitly set the HTTP method for this request. + * @param string $method + * @return $this + */ + public function setHttpMethod($method) + { + if (!self::isValidHttpMethod($method)) { + user_error('HTTPRequest::setHttpMethod: Invalid HTTP method', E_USER_ERROR); + } + + $this->httpMethod = strtoupper($method); + return $this; + } + /** * Return the URL scheme (e.g. "http" or "https"). * Equivalent to PSR-7 getUri()->getScheme() @@ -855,25 +867,28 @@ class HTTPRequest implements ArrayAccess } /** - * Gets the "real" HTTP method for a request. - * - * Used to work around browser limitations of form - * submissions to GET and POST, by overriding the HTTP method - * with a POST parameter called "_method" for PUT, DELETE, HEAD. - * Using GET for the "_method" override is not supported, - * as GET should never carry out state changes. - * Alternatively you can use a custom HTTP header 'X-HTTP-Method-Override' - * to override the original method. - * The '_method' POST parameter overrules the custom HTTP header. + * @param string $method + * @return bool + */ + private static function isValidHttpMethod($method) + { + return in_array(strtoupper($method), ['GET','POST','PUT','DELETE','HEAD']); + } + + /** + * Gets the "real" HTTP method for a request. This method is no longer used to mitigate the risk of web cache + * poisoning. * + * @see https://www.silverstripe.org/download/security-releases/CVE-2019-19326 * @param string $origMethod Original HTTP method from the browser request * @param array $postVars * @return string HTTP method (all uppercase) + * @deprecated 4.4.7 */ public static function detect_method($origMethod, $postVars) { if (isset($postVars['_method'])) { - if (!in_array(strtoupper($postVars['_method']), array('GET','POST','PUT','DELETE','HEAD'))) { + if (!self::isValidHttpMethod($postVars['_method'])) { user_error('HTTPRequest::detect_method(): Invalid "_method" parameter', E_USER_ERROR); } return strtoupper($postVars['_method']); diff --git a/src/Control/HTTPRequestBuilder.php b/src/Control/HTTPRequestBuilder.php index 8ccd07aaa..5a2359d50 100644 --- a/src/Control/HTTPRequestBuilder.php +++ b/src/Control/HTTPRequestBuilder.php @@ -135,16 +135,6 @@ class HTTPRequestBuilder */ public static function cleanEnvironment(array $variables) { - // IIS will sometimes generate this. - if (!empty($variables['_SERVER']['HTTP_X_ORIGINAL_URL'])) { - $variables['_SERVER']['REQUEST_URI'] = $variables['_SERVER']['HTTP_X_ORIGINAL_URL']; - } - - // Override REQUEST_METHOD - if (isset($variables['_SERVER']['X-HTTP-Method-Override'])) { - $variables['_SERVER']['REQUEST_METHOD'] = $variables['_SERVER']['X-HTTP-Method-Override']; - } - // Merge $_FILES into $_POST $variables['_POST'] = array_merge((array)$variables['_POST'], (array)$variables['_FILES']); diff --git a/tests/php/Control/HTTPRequestTest.php b/tests/php/Control/HTTPRequestTest.php index bade456b5..fc5b6451f 100644 --- a/tests/php/Control/HTTPRequestTest.php +++ b/tests/php/Control/HTTPRequestTest.php @@ -60,9 +60,15 @@ class HTTPRequestTest extends SapphireTest array(), array('_method' => 'DELETE') ); + $this->assertTrue( + $request->isPOST(), + '_method override is no longer honored' + ); + + $this->assertFalse( $request->isDELETE(), - 'POST with valid method override to DELETE' + 'DELETE _method override is not honored' ); $request = new HTTPRequest( @@ -71,9 +77,9 @@ class HTTPRequestTest extends SapphireTest array(), array('_method' => 'put') ); - $this->assertTrue( + $this->assertFalse( $request->isPUT(), - 'POST with valid method override to PUT' + 'PUT _method override is not honored' ); $request = new HTTPRequest( @@ -82,31 +88,78 @@ class HTTPRequestTest extends SapphireTest array(), array('_method' => 'head') ); - $this->assertTrue( + $this->assertFalse( $request->isHEAD(), - 'POST with valid method override to HEAD ' + 'HEAD _method override is not honored' ); + } - $request = new HTTPRequest( - 'POST', - 'admin/crm', - array(), - array('_method' => 'head') - ); - $this->assertTrue( - $request->isHEAD(), - 'POST with valid method override to HEAD' - ); + public function detectMethodDataProvider() + { + return [ + 'Plain POST request' => ['POST', [], 'POST'], + 'Plain GET request' => ['GET', [], 'GET'], + 'Plain DELETE request' => ['DELETE', [], 'DELETE'], + 'Plain PUT request' => ['PUT', [], 'PUT'], + 'Plain HEAD request' => ['HEAD', [], 'HEAD'], - $request = new HTTPRequest( - 'POST', - 'admin/crm', - array('_method' => 'head') - ); - $this->assertTrue( - $request->isPOST(), - 'POST with invalid method override by GET parameters to HEAD' - ); + 'Request with GET method override' => ['POST', ['_method' => 'GET'], 'GET'], + 'Request with HEAD method override' => ['POST', ['_method' => 'HEAD'], 'HEAD'], + 'Request with DELETE method override' => ['POST', ['_method' => 'DELETE'], 'DELETE'], + 'Request with PUT method override' => ['POST', ['_method' => 'PUT'], 'PUT'], + 'Request with POST method override' => ['POST', ['_method' => 'POST'], 'POST'], + + 'Request with mixed case method override' => ['POST', ['_method' => 'gEt'], 'GET'] + ]; + } + + /** + * @dataProvider detectMethodDataProvider + */ + public function testDetectMethod($realMethod, $post, $expected) + { + $actual = HTTPRequest::detect_method($realMethod, $post); + $this->assertEquals($expected, $actual); + } + + /** + * @expectedException PHPUnit_Framework_Error + */ + public function testBadDetectMethod() + { + HTTPRequest::detect_method('POST', ['_method' => 'Boom']); + } + + public function setHttpMethodDataProvider() + { + return [ + 'POST request' => ['POST','POST'], + 'GET request' => ['GET', 'GET'], + 'DELETE request' => ['DELETE', 'DELETE'], + 'PUT request' => ['PUT', 'PUT'], + 'HEAD request' => ['HEAD', 'HEAD'], + 'Mixed case POST' => ['gEt', 'GET'], + ]; + } + + /** + * @dataProvider setHttpMethodDataProvider + */ + public function testSetHttpMethod($method, $expected) + { + $request = new HTTPRequest('GET', '/hello'); + $returnedRequest = $request->setHttpMethod($method); + $this->assertEquals($expected, $request->httpMethod()); + $this->assertEquals($request, $returnedRequest); + } + + /** + * @expectedException PHPUnit_Framework_Error + */ + public function testBadSetHttpMethod() + { + $request = new HTTPRequest('GET', '/hello'); + $request->setHttpMethod('boom'); } public function testRequestVars() From 91d30db88f68b9b87980ef9a59e208a81980b72c Mon Sep 17 00:00:00 2001 From: Maxime Rainville Date: Wed, 13 May 2020 16:54:02 +1200 Subject: [PATCH 3/8] [CVE-2020-6164] Remove/deprecate unused controllers that can potentially give away some information about the underlying project. --- .upgrade.yml | 10 +++- _config/routes.yml | 4 -- src/Dev/InstallerTest.php | 1 + src/Dev/SapphireInfo.php | 1 + src/Dev/SapphireREPL.php | 110 -------------------------------------- 5 files changed, 10 insertions(+), 116 deletions(-) delete mode 100644 src/Dev/SapphireREPL.php diff --git a/.upgrade.yml b/.upgrade.yml index a2d4baa0e..09f6ed7e0 100644 --- a/.upgrade.yml +++ b/.upgrade.yml @@ -205,8 +205,6 @@ mappings: FunctionalTest: SilverStripe\Dev\FunctionalTest InstallerTest: SilverStripe\Dev\InstallerTest MigrationTask: SilverStripe\Dev\MigrationTask - SapphireInfo: SilverStripe\Dev\SapphireInfo - SapphireREPL: SilverStripe\Dev\SapphireREPL SapphireTest: SilverStripe\Dev\SapphireTest TaskRunner: SilverStripe\Dev\TaskRunner TestMailer: SilverStripe\Dev\TestMailer @@ -1018,6 +1016,14 @@ warnings: message: 'Use SilverStripe\CMS\BatchActions\CMSBatchAction_Archive instead' 'EncryptAllPasswordsTask': message: 'Removed' + 'SapphireInfo': + message: 'Removed' + 'SilverStripe\Dev\SapphireREPL': + message: 'Removed' + 'SilverStripe\Dev\SapphireInfo': + message: 'Deprecated' + 'SilverStripe\Dev\InstallerTest': + message: 'Deprecated' methods: 'SilverStripe\Security\Authenticator::register()': message: 'Custom authenticators work differently now' diff --git a/_config/routes.yml b/_config/routes.yml index 6d1368c95..990b68551 100644 --- a/_config/routes.yml +++ b/_config/routes.yml @@ -14,10 +14,6 @@ SilverStripe\Control\Director: 'Security//$Action/$ID/$OtherID': SilverStripe\Security\Security 'CMSSecurity//$Action/$ID/$OtherID': SilverStripe\Security\CMSSecurity 'dev': SilverStripe\Dev\DevelopmentAdmin - 'interactive': SilverStripe\Dev\SapphireREPL - 'InstallerTest//$Action/$ID/$OtherID': SilverStripe\Dev\InstallerTest - 'SapphireInfo//$Action/$ID/$OtherID': SilverStripe\Dev\SapphireInfo - 'SapphireREPL//$Action/$ID/$OtherID': SilverStripe\Dev\SapphireREPL --- Name: security-limited After: diff --git a/src/Dev/InstallerTest.php b/src/Dev/InstallerTest.php index ba9b1b871..76f349cb8 100644 --- a/src/Dev/InstallerTest.php +++ b/src/Dev/InstallerTest.php @@ -6,6 +6,7 @@ use SilverStripe\Control\Controller; /** * Simple controller that the installer uses to test that URL rewriting is working. + * @deprecated 4.4.7 This class will be removed in Silverstripe Framework 5. */ class InstallerTest extends Controller { diff --git a/src/Dev/SapphireInfo.php b/src/Dev/SapphireInfo.php index f915749ee..3b5868288 100644 --- a/src/Dev/SapphireInfo.php +++ b/src/Dev/SapphireInfo.php @@ -9,6 +9,7 @@ use SilverStripe\Security\Security; /** * Returns information about the current site instance. + * @deprecated 4.4.7 This class will be removed in Silverstripe Framework 5. */ class SapphireInfo extends Controller { diff --git a/src/Dev/SapphireREPL.php b/src/Dev/SapphireREPL.php deleted file mode 100644 index 5b181fcb5..000000000 --- a/src/Dev/SapphireREPL.php +++ /dev/null @@ -1,110 +0,0 @@ - ", "cyan"); - echo CLI::start_colour("yellow"); - $command = trim(fgets(STDIN, 4096)); - echo CLI::end_colour(); - - if ($command == 'help' || $command == '?') { - print "help or ? to exit\n" ; - print "quit or \q to exit\n" ; - print "install PHP_Shell for a more advanced interface with" - . " auto-completion and readline support\n\n" ; - continue ; - } - - if ($command == 'quit' || $command == '\q') { - break ; - } - - // Simple command processing - if (substr($command, -1) == ';') { - $command = substr($command, 0, -1); - } - $is_print = preg_match('/^\s*print/i', $command); - $is_return = preg_match('/^\s*return/i', $command); - if (!$is_print && !$is_return) { - $command = "return ($command)"; - } - $command .= ";"; - - try { - $result = eval($command); - if (!$is_print) { - print_r($result); - } - echo "\n"; - } catch (Exception $__repl_exception) { - echo CLI::start_colour("red"); - printf( - '%s (code: %d) got thrown' . PHP_EOL, - get_class($__repl_exception), - $__repl_exception->getCode() - ); - print $__repl_exception; - echo "\n"; - } - } - } - } -} From 8518987cbd1eaca71b65dd4a4b35591db941509a Mon Sep 17 00:00:00 2001 From: Maxime Rainville Date: Tue, 12 May 2020 10:58:30 +1200 Subject: [PATCH 4/8] [CVE-2019-19326] Stop honouring X-HTTP-Method-Override header, X-Original-Url header and _method POST variable. Add SS_HTTPRequest::setHttpMethod() --- src/Control/HTTPRequest.php | 45 ++++++++---- src/Control/HTTPRequestBuilder.php | 10 --- tests/php/Control/HTTPRequestTest.php | 101 ++++++++++++++++++++------ 3 files changed, 107 insertions(+), 49 deletions(-) diff --git a/src/Control/HTTPRequest.php b/src/Control/HTTPRequest.php index c3d5da5e7..6f213f127 100644 --- a/src/Control/HTTPRequest.php +++ b/src/Control/HTTPRequest.php @@ -18,9 +18,6 @@ use SilverStripe\ORM\ArrayLib; * The intention is that a single HTTPRequest object can be passed from one object to another, each object calling * match() to get the information that they need out of the URL. This is generally handled by * {@link RequestHandler::handleRequest()}. - * - * @todo Accept X_HTTP_METHOD_OVERRIDE http header and $_REQUEST['_method'] to override request types (useful for - * webclients not supporting PUT and DELETE) */ class HTTPRequest implements ArrayAccess { @@ -156,7 +153,7 @@ class HTTPRequest implements ArrayAccess */ public function __construct($httpMethod, $url, $getVars = array(), $postVars = array(), $body = null) { - $this->httpMethod = strtoupper(self::detect_method($httpMethod, $postVars)); + $this->httpMethod = strtoupper($httpMethod); $this->setUrl($url); $this->getVars = (array) $getVars; $this->postVars = (array) $postVars; @@ -830,6 +827,21 @@ class HTTPRequest implements ArrayAccess return $this->httpMethod; } + /** + * Explicitly set the HTTP method for this request. + * @param string $method + * @return $this + */ + public function setHttpMethod($method) + { + if (!self::isValidHttpMethod($method)) { + user_error('HTTPRequest::setHttpMethod: Invalid HTTP method', E_USER_ERROR); + } + + $this->httpMethod = strtoupper($method); + return $this; + } + /** * Return the URL scheme (e.g. "http" or "https"). * Equivalent to PSR-7 getUri()->getScheme() @@ -855,25 +867,28 @@ class HTTPRequest implements ArrayAccess } /** - * Gets the "real" HTTP method for a request. - * - * Used to work around browser limitations of form - * submissions to GET and POST, by overriding the HTTP method - * with a POST parameter called "_method" for PUT, DELETE, HEAD. - * Using GET for the "_method" override is not supported, - * as GET should never carry out state changes. - * Alternatively you can use a custom HTTP header 'X-HTTP-Method-Override' - * to override the original method. - * The '_method' POST parameter overrules the custom HTTP header. + * @param string $method + * @return bool + */ + private static function isValidHttpMethod($method) + { + return in_array(strtoupper($method), ['GET','POST','PUT','DELETE','HEAD']); + } + + /** + * Gets the "real" HTTP method for a request. This method is no longer used to mitigate the risk of web cache + * poisoning. * + * @see https://www.silverstripe.org/download/security-releases/CVE-2019-19326 * @param string $origMethod Original HTTP method from the browser request * @param array $postVars * @return string HTTP method (all uppercase) + * @deprecated 4.4.7 */ public static function detect_method($origMethod, $postVars) { if (isset($postVars['_method'])) { - if (!in_array(strtoupper($postVars['_method']), array('GET','POST','PUT','DELETE','HEAD'))) { + if (!self::isValidHttpMethod($postVars['_method'])) { user_error('HTTPRequest::detect_method(): Invalid "_method" parameter', E_USER_ERROR); } return strtoupper($postVars['_method']); diff --git a/src/Control/HTTPRequestBuilder.php b/src/Control/HTTPRequestBuilder.php index 8ccd07aaa..5a2359d50 100644 --- a/src/Control/HTTPRequestBuilder.php +++ b/src/Control/HTTPRequestBuilder.php @@ -135,16 +135,6 @@ class HTTPRequestBuilder */ public static function cleanEnvironment(array $variables) { - // IIS will sometimes generate this. - if (!empty($variables['_SERVER']['HTTP_X_ORIGINAL_URL'])) { - $variables['_SERVER']['REQUEST_URI'] = $variables['_SERVER']['HTTP_X_ORIGINAL_URL']; - } - - // Override REQUEST_METHOD - if (isset($variables['_SERVER']['X-HTTP-Method-Override'])) { - $variables['_SERVER']['REQUEST_METHOD'] = $variables['_SERVER']['X-HTTP-Method-Override']; - } - // Merge $_FILES into $_POST $variables['_POST'] = array_merge((array)$variables['_POST'], (array)$variables['_FILES']); diff --git a/tests/php/Control/HTTPRequestTest.php b/tests/php/Control/HTTPRequestTest.php index 2b2cf49ad..986132ef7 100644 --- a/tests/php/Control/HTTPRequestTest.php +++ b/tests/php/Control/HTTPRequestTest.php @@ -61,9 +61,15 @@ class HTTPRequestTest extends SapphireTest array(), array('_method' => 'DELETE') ); + $this->assertTrue( + $request->isPOST(), + '_method override is no longer honored' + ); + + $this->assertFalse( $request->isDELETE(), - 'POST with valid method override to DELETE' + 'DELETE _method override is not honored' ); $request = new HTTPRequest( @@ -72,9 +78,9 @@ class HTTPRequestTest extends SapphireTest array(), array('_method' => 'put') ); - $this->assertTrue( + $this->assertFalse( $request->isPUT(), - 'POST with valid method override to PUT' + 'PUT _method override is not honored' ); $request = new HTTPRequest( @@ -83,31 +89,78 @@ class HTTPRequestTest extends SapphireTest array(), array('_method' => 'head') ); - $this->assertTrue( + $this->assertFalse( $request->isHEAD(), - 'POST with valid method override to HEAD ' + 'HEAD _method override is not honored' ); + } - $request = new HTTPRequest( - 'POST', - 'admin/crm', - array(), - array('_method' => 'head') - ); - $this->assertTrue( - $request->isHEAD(), - 'POST with valid method override to HEAD' - ); + public function detectMethodDataProvider() + { + return [ + 'Plain POST request' => ['POST', [], 'POST'], + 'Plain GET request' => ['GET', [], 'GET'], + 'Plain DELETE request' => ['DELETE', [], 'DELETE'], + 'Plain PUT request' => ['PUT', [], 'PUT'], + 'Plain HEAD request' => ['HEAD', [], 'HEAD'], - $request = new HTTPRequest( - 'POST', - 'admin/crm', - array('_method' => 'head') - ); - $this->assertTrue( - $request->isPOST(), - 'POST with invalid method override by GET parameters to HEAD' - ); + 'Request with GET method override' => ['POST', ['_method' => 'GET'], 'GET'], + 'Request with HEAD method override' => ['POST', ['_method' => 'HEAD'], 'HEAD'], + 'Request with DELETE method override' => ['POST', ['_method' => 'DELETE'], 'DELETE'], + 'Request with PUT method override' => ['POST', ['_method' => 'PUT'], 'PUT'], + 'Request with POST method override' => ['POST', ['_method' => 'POST'], 'POST'], + + 'Request with mixed case method override' => ['POST', ['_method' => 'gEt'], 'GET'] + ]; + } + + /** + * @dataProvider detectMethodDataProvider + */ + public function testDetectMethod($realMethod, $post, $expected) + { + $actual = HTTPRequest::detect_method($realMethod, $post); + $this->assertEquals($expected, $actual); + } + + /** + * @expectedException PHPUnit_Framework_Error + */ + public function testBadDetectMethod() + { + HTTPRequest::detect_method('POST', ['_method' => 'Boom']); + } + + public function setHttpMethodDataProvider() + { + return [ + 'POST request' => ['POST','POST'], + 'GET request' => ['GET', 'GET'], + 'DELETE request' => ['DELETE', 'DELETE'], + 'PUT request' => ['PUT', 'PUT'], + 'HEAD request' => ['HEAD', 'HEAD'], + 'Mixed case POST' => ['gEt', 'GET'], + ]; + } + + /** + * @dataProvider setHttpMethodDataProvider + */ + public function testSetHttpMethod($method, $expected) + { + $request = new HTTPRequest('GET', '/hello'); + $returnedRequest = $request->setHttpMethod($method); + $this->assertEquals($expected, $request->httpMethod()); + $this->assertEquals($request, $returnedRequest); + } + + /** + * @expectedException PHPUnit_Framework_Error + */ + public function testBadSetHttpMethod() + { + $request = new HTTPRequest('GET', '/hello'); + $request->setHttpMethod('boom'); } public function testRequestVars() From cce2b1630937895aa28c2914837651e7cd56d74b Mon Sep 17 00:00:00 2001 From: Maxime Rainville Date: Wed, 13 May 2020 16:54:02 +1200 Subject: [PATCH 5/8] [CVE-2020-6164] Remove/deprecate unused controllers that can potentially give away some information about the underlying project. --- .upgrade.yml | 10 +++- _config/routes.yml | 4 -- src/Dev/InstallerTest.php | 1 + src/Dev/SapphireInfo.php | 1 + src/Dev/SapphireREPL.php | 110 -------------------------------------- 5 files changed, 10 insertions(+), 116 deletions(-) delete mode 100644 src/Dev/SapphireREPL.php diff --git a/.upgrade.yml b/.upgrade.yml index 8e9407635..a71ae6987 100644 --- a/.upgrade.yml +++ b/.upgrade.yml @@ -205,8 +205,6 @@ mappings: FunctionalTest: SilverStripe\Dev\FunctionalTest InstallerTest: SilverStripe\Dev\InstallerTest MigrationTask: SilverStripe\Dev\MigrationTask - SapphireInfo: SilverStripe\Dev\SapphireInfo - SapphireREPL: SilverStripe\Dev\SapphireREPL SapphireTest: SilverStripe\Dev\SapphireTest TaskRunner: SilverStripe\Dev\TaskRunner TestMailer: SilverStripe\Dev\TestMailer @@ -1016,6 +1014,14 @@ warnings: message: 'Use SilverStripe\CMS\BatchActions\CMSBatchAction_Archive instead' 'EncryptAllPasswordsTask': message: 'Removed' + 'SapphireInfo': + message: 'Removed' + 'SilverStripe\Dev\SapphireREPL': + message: 'Removed' + 'SilverStripe\Dev\SapphireInfo': + message: 'Deprecated' + 'SilverStripe\Dev\InstallerTest': + message: 'Deprecated' methods: 'SilverStripe\Security\Authenticator::register()': message: 'Custom authenticators work differently now' diff --git a/_config/routes.yml b/_config/routes.yml index 6d1368c95..990b68551 100644 --- a/_config/routes.yml +++ b/_config/routes.yml @@ -14,10 +14,6 @@ SilverStripe\Control\Director: 'Security//$Action/$ID/$OtherID': SilverStripe\Security\Security 'CMSSecurity//$Action/$ID/$OtherID': SilverStripe\Security\CMSSecurity 'dev': SilverStripe\Dev\DevelopmentAdmin - 'interactive': SilverStripe\Dev\SapphireREPL - 'InstallerTest//$Action/$ID/$OtherID': SilverStripe\Dev\InstallerTest - 'SapphireInfo//$Action/$ID/$OtherID': SilverStripe\Dev\SapphireInfo - 'SapphireREPL//$Action/$ID/$OtherID': SilverStripe\Dev\SapphireREPL --- Name: security-limited After: diff --git a/src/Dev/InstallerTest.php b/src/Dev/InstallerTest.php index ba9b1b871..76f349cb8 100644 --- a/src/Dev/InstallerTest.php +++ b/src/Dev/InstallerTest.php @@ -6,6 +6,7 @@ use SilverStripe\Control\Controller; /** * Simple controller that the installer uses to test that URL rewriting is working. + * @deprecated 4.4.7 This class will be removed in Silverstripe Framework 5. */ class InstallerTest extends Controller { diff --git a/src/Dev/SapphireInfo.php b/src/Dev/SapphireInfo.php index f915749ee..3b5868288 100644 --- a/src/Dev/SapphireInfo.php +++ b/src/Dev/SapphireInfo.php @@ -9,6 +9,7 @@ use SilverStripe\Security\Security; /** * Returns information about the current site instance. + * @deprecated 4.4.7 This class will be removed in Silverstripe Framework 5. */ class SapphireInfo extends Controller { diff --git a/src/Dev/SapphireREPL.php b/src/Dev/SapphireREPL.php deleted file mode 100644 index 5b181fcb5..000000000 --- a/src/Dev/SapphireREPL.php +++ /dev/null @@ -1,110 +0,0 @@ - ", "cyan"); - echo CLI::start_colour("yellow"); - $command = trim(fgets(STDIN, 4096)); - echo CLI::end_colour(); - - if ($command == 'help' || $command == '?') { - print "help or ? to exit\n" ; - print "quit or \q to exit\n" ; - print "install PHP_Shell for a more advanced interface with" - . " auto-completion and readline support\n\n" ; - continue ; - } - - if ($command == 'quit' || $command == '\q') { - break ; - } - - // Simple command processing - if (substr($command, -1) == ';') { - $command = substr($command, 0, -1); - } - $is_print = preg_match('/^\s*print/i', $command); - $is_return = preg_match('/^\s*return/i', $command); - if (!$is_print && !$is_return) { - $command = "return ($command)"; - } - $command .= ";"; - - try { - $result = eval($command); - if (!$is_print) { - print_r($result); - } - echo "\n"; - } catch (Exception $__repl_exception) { - echo CLI::start_colour("red"); - printf( - '%s (code: %d) got thrown' . PHP_EOL, - get_class($__repl_exception), - $__repl_exception->getCode() - ); - print $__repl_exception; - echo "\n"; - } - } - } - } -} From 0eb476916d487ff646625d9e8baff76c0116623d Mon Sep 17 00:00:00 2001 From: Maxime Rainville Date: Tue, 25 Feb 2020 18:36:31 +1300 Subject: [PATCH 6/8] DOC Explain how to implement a custom QueryPermissionChecker --- .../01_Verifying_CanView_Permission.md | 159 ++++++++++++++++++ .../02_Developer_Guides/19_GraphQL/index.md | 20 +++ 2 files changed, 179 insertions(+) create mode 100644 docs/en/02_Developer_Guides/19_GraphQL/01_Verifying_CanView_Permission.md create mode 100644 docs/en/02_Developer_Guides/19_GraphQL/index.md diff --git a/docs/en/02_Developer_Guides/19_GraphQL/01_Verifying_CanView_Permission.md b/docs/en/02_Developer_Guides/19_GraphQL/01_Verifying_CanView_Permission.md new file mode 100644 index 000000000..6c27b1982 --- /dev/null +++ b/docs/en/02_Developer_Guides/19_GraphQL/01_Verifying_CanView_Permission.md @@ -0,0 +1,159 @@ +--- +title: Controlling CanView access to DataObjects returned by GraphQL +summary: Your GraphQL service should honour the CanView permission when fetching DataObjects. Learn how to customise this access control check. +icon: cookie-bite +--- + +# Controlling who can view results in a GraphQL result set + +The [Silverstripe ORM provides methods to control permissions on DataObject](Developer_Guides/Model/Permissions). In +most cases, you'll want to extend this permission model to any GraphQL service you implement that returns a DataObject. + +## The QueryPermissionChecker interface + +The GraphQL module includes a `QueryPermissionChecker` interface. This interface can be used to specify how GraphQL +services should validate that users have access to the DataObjects they are requesting. + +The default implementation of `QueryPermissionChecker` is `CanViewPermissionChecker`. `CanViewPermissionChecker` directly calls the `CanView` method of each DataObject in your result set and filters out the entries not visible to the current user. + +Out of the box, the `CanView` permission of your DataObjects are honoured when Scaffolding GraphQL queries. + +## Customising how the results are filtered + +`CanViewPermissionChecker` has some limitations. It's rather simplistic and will load each entry in your results set to perform a CanView call on it. It will also convert the results set to an `ArrayList` which can be inconvenient if you need to alter the underlying query after the _CanView_ check. + +Depending on your exact use case, you may want to implement your own `QueryPermissionChecker` instead of relying +on `CanViewPermissionChecker`. + +Some of the reasons you might consider this are: +* the access permissions on your GraphQL service differ from the ones implemented directly on your DataObject +* you want to speed up your request by filtering out results the user doesn't have access to directly in the query +* you would rather have a `DataList` be returned. + +### Implementing your own QueryPermissionChecker class + +The `QueryPermissionChecker` requires your class to implement two methods: +* `applyToList` which filters a `Filterable` list based on whether a provided `Member` can view the results +* `checkItem` which checks if a provided object can be viewed by a specific `Member`. + +#### Filtering results based on the user's permissions + +In some context, whether a user can view an object is entirely determined on their permissions. When that's the +case, you don't even need to get results to know if the user will be able to see them or not. + +```php +filter('OwnerID', $member ? $member->ID : -1); + } + + public function checkItem($item, Member $member = null) + { + return $member && $item->OwnerID === $member->ID; + } +} +``` + +### Using a custom QueryPermissionChecker implementation + +There's three classes that expect a `QueryPermissionChecker`: +* `SilverStripe\GraphQL\Scaffolding\Scaffolders\ItemQueryScaffolder` +* `SilverStripe\GraphQL\Scaffolding\Scaffolders\ListQueryScaffolder` +* `SilverStripe\GraphQL\Pagination\Connection` + +Those classes all implement the `SilverStripe\GraphQL\Permission\PermissionCheckerAware` and receive the default +`QueryPermissionChecker` from the Injector. They also have a `setPermissionChecker` method that can be use to provide a custom `QueryPermissionChecker`. + +#### Scaffolding types with a custom QueryPermissionChecker implementation + +There's not any elegant way of defining a custom `QueryPermissionChecker` when scaffolding types at this time. If +you need the ability to use a custom `QueryPermissionChecker`, you'll have to build your query manually. + +#### Overriding the QueryPermissionChecker for a class extending ListQueryScaffolder + +If you've created a GraphQL query by creating a subclass of `ListQueryScaffolder`, you can use the injector to +override `QueryPermissionChecker`. + +```yaml +--- +Name: custom-graphqlconfig +After: graphqlconfig +--- +SilverStripe\Core\Injector\Injector: + SilverStripe\GraphQL\Permission\QueryPermissionChecker.my-custom: + class: App\Project\CustomQueryPermissionChecker + App\Project\CustomListQueryScaffolder: + properties: + permissionChecker: '%$SilverStripe\GraphQL\Permission\QueryPermissionChecker.my-custom' +``` + +#### Manually specifying a QueryPermissionChecker on a Connection + +If you're manually instantiating an instance of `SilverStripe\GraphQL\Pagination\Connection` to resolve your results, +you can pass an instance of your own custom `QueryPermissionChecker`. + +```php +$childrenConnection = Connection::create('Children') + ->setConnectionType($this->manager->getType('Children')) + ->setSortableFields([ + 'id' => 'ID', + 'title' => 'Title', + 'created' => 'Created', + 'lastEdited' => 'LastEdited', + ]) + ->setPermissionChecker(new CustomQueryPermissionChecker()); +``` + +## API Documentation + +* [CanViewPermissionChecker](api:SilverStripe\GraphQL\Permission\CanViewPermissionChecker) +* [Connection](api:SilverStripe\GraphQL\Pagination\Connection) +* [ItemQueryScaffolder](api:SilverStripe\GraphQL\Scaffolding\Scaffolders\ItemQueryScaffolder) +* [ListQueryScaffolder](api:SilverStripe\GraphQL\Scaffolding\Scaffolders\ListQueryScaffolder) +* [PermissionCheckerAware](api:SilverStripe\GraphQL\Permission\PermissionCheckerAware) +* [QueryPermissionChecker](api:SilverStripe\GraphQL\Permission\QueryPermissionChecker) diff --git a/docs/en/02_Developer_Guides/19_GraphQL/index.md b/docs/en/02_Developer_Guides/19_GraphQL/index.md new file mode 100644 index 000000000..217d1dfb7 --- /dev/null +++ b/docs/en/02_Developer_Guides/19_GraphQL/index.md @@ -0,0 +1,20 @@ +--- +title: GraphQL +summary: Learn how to create and customise GraphQL services on your Silverstripe CMS project. +introduction: Learn how to create and customise GraphQL services on your Silverstripe CMS project. +icon: cookie +--- + +[CHILDREN] + +## Additional documentation + +A substantial part of the GraphQL documentation for Silverstripe CMS still +reside on the GraphQL module's _Readme_ file. We are in the process of folding +this information back into the main Silverstripe CMS documentation. + +* [silverstripe/graphql](https://github.com/silverstripe/silverstripe-graphql/) + +## API Documentation + +* [GraphQL](api:SilverStripe\GraphQL) From 1726cd1f9757ec2ea503a116064d87441950abfc Mon Sep 17 00:00:00 2001 From: Garion Herman Date: Fri, 10 Jul 2020 18:02:10 +1200 Subject: [PATCH 7/8] Added 4.5.3 changelog --- docs/en/04_Changelogs/4.5.3.md | 176 +++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 docs/en/04_Changelogs/4.5.3.md diff --git a/docs/en/04_Changelogs/4.5.3.md b/docs/en/04_Changelogs/4.5.3.md new file mode 100644 index 000000000..7731e6054 --- /dev/null +++ b/docs/en/04_Changelogs/4.5.3.md @@ -0,0 +1,176 @@ +# 4.5.3 + +## Security patches + +This release contains security patches. Some of those patches might require some updates to your project. + +* [CVE-2020-9309 Script execution on protected files](https://www.silverstripe.org/download/security-releases/CVE-2020-9309) +* [CVE-2019-19326 Web Cache Poisoning](https://www.silverstripe.org/download/security-releases/CVE-2019-19326) +* [CVE-2020-6164 Information disclosure on /interactive URL path](https://www.silverstripe.org/download/security-releases/CVE-2020-6164) +* [CVE-2020-6165 Limited queries break CanViewPermissionChecker](https://www.silverstripe.org/download/security-releases/CVE-2020-6165) + + +### CVE-2020-9309 Script execution on protected files {#CVE-2020-9309} + +Silverstripe can be susceptible to script execution from malicious upload contents under allowed file extensions (for example HTML code in a TXT file). When these files are stored as protected or draft files, the MIME detection can cause browsers to execute the file contents. + +#### Risk factors + +If your project already includes the `silverstripe/mimevalidator` module, it's already protected. CWP projects are already protected. + +If your project includes the `silverstripe/userforms` module or allows anonymous users to upload files, it's at a higher risk because malicious users can create files without requiring a CMS access. + +#### Actions you need to take + +If your project already includes the `silverstripe/mimevalidator` module, you do not need to do anything. To check if the `silverstripe/mimevalidator` module is installed in your project, run this command from your project root. + +```sh +composer show silverstripe/mimevalidator +``` + +If you get an error, the module is not installed. + +**Upgrading to `silverstripe/recipe-cms` 4.5.3 will NOT automatically install `silverstripe/mimevalidator`**. You need to manually install the module `silverstripe/mimevalidator`. To add `silverstripe/mimevalidator` to your project, run this command. + +```sh +composer require silverstripe/mimevalidator +``` + +After installing the `mimevalidator` module, you need to enable it by adding this code snippet to your YML configuration. + +```yml +SilverStripe\Core\Injector\Injector: + SilverStripe\Assets\Upload_Validator: + class: SilverStripe\MimeValidator\MimeUploadValidator +``` + +If your project overrides the defaults allowed file types, it's important that you take the time to review your configuration and adjust it as need be to work with `silverstripe/mimevalidator`. + +Read the [Allowed file types](/Developer_Guides/Files/Allowed_file_types) documentation for more details on controling the type of files that can be stored in your Silverstrip CMS Project. + +#### Special consideration when upgrading Userforms + +The `silverstripe/userforms` module now also includes `silverstripe/mimevalidator` in its dependencies. Upgrading to the following versions of userforms will automatically install `silverstripe/mimevalidator`: + +* 5.4.3 or later +* 5.5.3 or later +* 5.6.0 or later (requires CMS 4.6.0) + +Userforms that include a file upload field will automatically use the`MimeUploadValidator`. Beware that this will NOT change the default upload validator for other file upload fields in the CMS. You'll need to update your YML configuration for the `MimeUploadValidator` to be used everywhere. + +### CVE-2019-19326 Web Cache Poisoning {#CVE-2019-19326} + +Silverstripe sites using HTTP cache headers and HTTP caching proxies (e.g. CDNs) can be susceptible to web cache poisoning through the: +* `X-Original-Url` HTTP header +* `X-HTTP-Method-Override` HTTP header +* `_method` POST variable. + +In order to remedy this vulnerability, Silverstripe Framework 4.5.3 removes native support for these features. While this is technically a semantic versioning breakage, these features are inherently insecure and date back to a time when browsers didn't natively support the full range of HTTP methods. Sites who still require these features will have highly unusual requirements that are best served by a tailored solution. + +### Re-enabling the support for removed features + +These features are best implemented by defining a `Middleware`. + +The following example illustrates how to implement an `HTTPMiddleware` that restores support for the `X-Original-Url` header and the `_method` POST parameter for requests originating from a trusted proxy. + +```php +getHeader('X-Original-Url'); + if ($originalUrl) { + $_SERVER['REQUEST_URI'] = $originalUrl; + $request->setUrl($originalUrl); + } + $methodOverride = $request->postVar('_method'); + $validMethods = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']; + if ($methodOverride && in_array(strtoupper($methodOverride), $validMethods)) { + $request->setHttpMethod($methodOverride); + } + } + return $delegate($request); + } +} +``` + +To learn more about re-implementing support for the disabled features: +* read [how to configure trusted proxies](/developer_guides/security/secure_coding/#request-hostname-forgery) on the Silverstripe documentation. +* read the [documentation about HTTP Middlewares](/developer_guides/controllers/middlewares/). + +### CVE-2020-6164 Information disclosure on /interactive URL path + +A specific URL path configured by default through the silverstripe/framework module can be used to disclose the fact that a domain is hosting a Silverstripe application. There is no disclosure of the specific version. The functionality on this URL path is limited to execution in a CLI context, and is not known to present a vulnerability through web-based access. As a side-effect, this preconfigured path also blocks the creation of other resources on this path (e.g. a page). + +### CVE-2020-6165 Limited queries break CanViewPermissionChecker + +The automatic permission checking mechanism in the silverstripe/graphql module does not provide complete protection against lists that are limited (e.g. through pagination), resulting in records that should fail the permission check being added to the final result set. + +If your project implements custom GraphQL queries using the `CanViewPermissionChecker`, you should validate that they still work as expected after the upgrade. + +Read [Controlling who can view results in a GraphQL result set](/Developer_Guides/GraphQL/Verifying_CanView_Permission) +for more information on updating your GraphQL queries. + + + +## Change Log + +### Security + + * 2020-05-13 [cce2b1630](https://github.com/silverstripe/silverstripe-framework/commit/cce2b1630937895aa28c2914837651e7cd56d74b) Remove/deprecate unused controllers that can potentially give away some information about the underlying project. (Maxime Rainville) - See [cve-2020-6164](https://www.silverstripe.org/download/security-releases/cve-2020-6164) + * 2020-05-11 [8518987cb](https://github.com/silverstripe/silverstripe-framework/commit/8518987cbd1eaca71b65dd4a4b35591db941509a) Stop honouring X-HTTP-Method-Override header, X-Original-Url header and _method POST variable. Add SS_HTTPRequest::setHttpMethod() (Maxime Rainville) - See [cve-2019-19326](https://www.silverstripe.org/download/security-releases/cve-2019-19326) + * 2020-02-17 [d3968ad](https://github.com/silverstripe/silverstripe-asset-admin/commit/d3968adcbdb759cb20571865af3b6356c8922cde) Move the query resolution after the DataListQuery has been altered (Maxime Rainville) - See [cve-2020-6165](https://www.silverstripe.org/download/security-releases/cve-2020-6165) + * 2020-02-11 [107e6c9](https://github.com/silverstripe/silverstripe-graphql/commit/107e6c918bb6a6a536dd9e3d8f5c74b4acdfd852) Ensure canView() check is run on items (Steve Boyd) - See [cve-2020-6165](https://www.silverstripe.org/download/security-releases/cve-2020-6165) + +### API Changes + + * 2020-06-30 [ec83959f2](https://github.com/silverstripe/silverstripe-framework/commit/ec83959f2c3ff7784fdd9503601732b5d006de13) Remove UpgradeBootstrap (not part of our official API) (Maxime Rainville) + +### Features and Enhancements + + * 2020-04-15 [daa80d8](https://github.com/silverstripe/silverstripe-admin/commit/daa80d8d2c2a5eabf75cfd23bb40d5a4b0fab02a) Add secure icons (Sacha Judd) + +### Bugfixes + + * 2020-07-09 [b780c4f50](https://github.com/silverstripe/silverstripe-framework/commit/b780c4f504555e5ae2d3861f8772f87ab20e016e) Tweak DBHTMLText::Plain to avoid treating some chinese characters as line breaks. (Maxime Rainville) + * 2020-06-23 [e033f26](https://github.com/silverstripe/silverstripe-admin/commit/e033f26d16527c04fb09c9ae3c1582367cf1dcaf) Fix external link setting text to `undefined` on text (#1059) (Andre Kiste) + * 2020-06-01 [3df2222](https://github.com/silverstripe/silverstripe-asset-admin/commit/3df222203ee563fac840e5e0727c75ddfe244886) Prevent react-selectable from interfering with pagination (Maxime Rainville) + * 2020-05-26 [3e52b1a](https://github.com/silverstripe/silverstripe-admin/commit/3e52b1ae3e5fd45dfde05913fe2fc0edd7309d82) Vertically align form description contents (including icons) (bergice) + * 2020-05-26 [09d2061](https://github.com/silverstripe/silverstripe-asset-admin/commit/09d20617620571650509b2b250117c295d58d5bb) Asset revision timestamps are no longer underlined in asset admin history tabs (Robbie Averill) + * 2020-05-19 [b9de9e6](https://github.com/silverstripe/silverstripe-asset-admin/commit/b9de9e6d608aa2b7f6d01e9c609369998d3ab0d8) Remove direct descendant selector to apply correct margins (Sacha Judd) + * 2020-05-11 [9dcc030](https://github.com/silverstripe/silverstripe-admin/commit/9dcc030aa8c2c3dab4c6a4206f883cb40e6a1458) Resize address-card-warning (Sacha Judd) + * 2020-05-08 [afc1759](https://github.com/silverstripe/silverstripe-admin/commit/afc1759f6cc74ce58be68bfb167bf52c1e972915) Page search form layout overflow issue (Mojmir Fendek) + * 2020-05-05 [2cc037b](https://github.com/silverstripe/silverstripe-versioned/commit/2cc037b2d305ed98056a9232587351949e59561f) Fix merge conflict in Travis configuration (Robbie Averill) + * 2020-05-01 [b1f6e52](https://github.com/silverstripe/silverstripe-asset-admin/commit/b1f6e521aac9bc17ee400593724e4a9290678938) Remove grid view sorting hack to correct initial state (Garion Herman) + * 2020-05-01 [891f0682](https://github.com/silverstripe/silverstripe-cms/commit/891f068202a3c7926a813c994b2802eacb7847f0) Correct placement of 'Page location' field title (Garion Herman) + * 2020-04-30 [fff806ca](https://github.com/silverstripe/silverstripe-cms/commit/fff806ca33cf6cdfd17c073f736e0faba42964a3) Prevent Treeview from always reloading (Maxime Rainville) + * 2020-04-18 [216989165](https://github.com/silverstripe/silverstripe-framework/commit/2169891651aded4defe33a1d08e1b07f79b9f086) Ensure realpath returns a string for stripos (mattclegg) + * 2020-04-15 [be80813](https://github.com/silverstripe/silverstripe-asset-admin/commit/be80813eaa8f5005b63978a53da2162c88645173) Campaign admin permission fix (Mojmir Fendek) + * 2020-04-15 [d7c76bdb](https://github.com/silverstripe/silverstripe-cms/commit/d7c76bdbba0af815d61146a1cbfc2529b3b2fe55) Published pages filter correction (missing default filter) (Mojmir Fendek) + * 2020-04-14 [e2a6281](https://github.com/silverstripe/silverstripe-asset-admin/commit/e2a6281305f23bd43d43a23adaa6807a54263f61) Legacy max upload size setting removal (Mojmir Fendek) + * 2020-03-23 [5002f514b](https://github.com/silverstripe/silverstripe-framework/commit/5002f514b3fde8e4ef75a72c964d649f46ab31f0) Capitalisation fixes in welcome back message (#9439) (Robbie Averill) + * 2020-03-23 [e5aa94c](https://github.com/silverstripe/silverstripe-admin/commit/e5aa94cfdd4fadcc87db3eee127f2f4f751ef6a7) "My profile" title in CMS is now vertical centered as other LeftAndMain screens are (Robbie Averill) + * 2020-03-20 [14fd29a](https://github.com/silverstripe/silverstripe-admin/commit/14fd29ad2c607951eff1bab65921748916a6c72e) Switch incorrect modified and draft state indicator colours (Sacha Judd) + * 2020-03-17 [7ad5f1bb1](https://github.com/silverstripe/silverstripe-framework/commit/7ad5f1bb14814bd05c6fe97e11b94c9f34936b15) Ensure diff arrays are one-dimensional (Aaron Carlino) + * 2020-03-08 [b269d8749](https://github.com/silverstripe/silverstripe-framework/commit/b269d874909cd70bb60c1a2974ea5446b43b0436) Register new sub tasks to fix files affected by CVE-2020-9280 and CVE-2019-12245 (Serge Latyntcev) + * 2020-03-04 [12ea7cd](https://github.com/silverstripe/silverstripe-assets/commit/12ea7cd2037bebcb3196dd5e3aaa72e6dbc7c7b2) Create NormaliseAccessMigrationHelper to fix files affected by CVE-2019-12245 (Maxime Rainville) + * 2020-02-24 [bba0f2f72](https://github.com/silverstripe/silverstripe-framework/commit/bba0f2f72fa2e631dbf60357a908d5d57d4467ee) Fixed issue where TimeField_Readonly would only show "(not set)" instead of the value (UndefinedOffset) + * 2020-02-20 [ff417ca](https://github.com/silverstripe/silverstripe-asset-admin/commit/ff417ca53405a4022c4fece82d50638e72940d4f) Fix last file upload showing as errored when uploading multiple files. (bergice) + * 2020-02-19 [7455d14](https://github.com/silverstripe/silverstripe-asset-admin/commit/7455d141aa6340e33674f72516e0e6b97d6d6232) Handle case where provided $context is null (Garion Herman) + * 2020-02-19 [8402966](https://github.com/silverstripe/silverstripe-assets/commit/84029664c21ba54d895aac8fa036a9c4277e56a0) Correct deprecated implode syntax for PHP 7.4 compat (Garion Herman) + * 2020-02-18 [9900d07](https://github.com/silverstripe/silverstripe-asset-admin/commit/9900d07eeb41a9c5c9dac758ee56f9397301bbdb) Tweak UsedOnTableTest ti dynamically switch protocol (Maxime Rainville) + * 2020-02-05 [c92e3b9d](https://github.com/silverstripe/silverstripe-cms/commit/c92e3b9d7967142ce59c918916441fce796c9fd8) Prioritise same-level pages in OldPageRedirector (Klemen Dolinšek) + * 2019-10-17 [b62288cc9](https://github.com/silverstripe/silverstripe-framework/commit/b62288cc92bd7e58182e1b02b083eeb474366d52) Disabled the UpgradeBootstrap upgrader doctor task (Maxime Rainville) + * 2019-09-02 [6d8a4bc](https://github.com/silverstripe/silverstripe-assets/commit/6d8a4bc4f4178c0b56ede1b01f87b162066d550a) Make AbsoluteLink work with manipulated images (fixes #322) (Loz Calver) + From f2d9150755aef32f7bc7aa6b5321d966f6540af7 Mon Sep 17 00:00:00 2001 From: Garion Herman Date: Fri, 10 Jul 2020 10:47:29 +1200 Subject: [PATCH 8/8] Added 4.4.7 changelog --- docs/en/04_Changelogs/4.4.7.md | 131 +++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 docs/en/04_Changelogs/4.4.7.md diff --git a/docs/en/04_Changelogs/4.4.7.md b/docs/en/04_Changelogs/4.4.7.md new file mode 100644 index 000000000..712a9a1c9 --- /dev/null +++ b/docs/en/04_Changelogs/4.4.7.md @@ -0,0 +1,131 @@ +# 4.4.7 + +## Security patches + +This release contains security patches. Some of those patches might require some updates to your project. + +* [CVE-2020-9309 Script execution on protected files](https://www.silverstripe.org/download/security-releases/CVE-2020-9309) +* [CVE-2019-19326 Web Cache Poisoning](https://www.silverstripe.org/download/security-releases/CVE-2019-19326) +* [CVE-2020-6164 Information disclosure on /interactive URL path](https://www.silverstripe.org/download/security-releases/CVE-2020-6164) + + +### CVE-2020-9309 Script execution on protected files {#CVE-2020-9309} + +Silverstripe can be susceptible to script execution from malicious upload contents under allowed file extensions (for example HTML code in a TXT file). When these files are stored as protected or draft files, the MIME detection can cause browsers to execute the file contents. + +#### Risk factors + +If your project already includes the `silverstripe/mimevalidator` module, it's already protected. CWP projects are already protected. + +If your project includes the `silverstripe/userforms` module or allows anonymous users to upload files, it's at a higher risk because malicious users can create files without requiring a CMS access. + +#### Actions you need to take + +If your project already includes the `silverstripe/mimevalidator` module, you do not need to do anything. To check if the `silverstripe/mimevalidator` module is installed in your project, run this command from your project root. + +```sh +composer show silverstripe/mimevalidator +``` + +If you get an error, the module is not installed. + +**Upgrading to `silverstripe/recipe-cms` 4.4.7 will NOT automatically install `silverstripe/mimevalidator`**. You need to manually install the module `silverstripe/mimevalidator`. To add `silverstripe/mimevalidator` to your project, run this command. + +```sh +composer require silverstripe/mimevalidator +``` + +After installing the `mimevalidator` module, you need to enable it by adding this code snippet to your YML configuration. + +```yml +SilverStripe\Core\Injector\Injector: + SilverStripe\Assets\Upload_Validator: + class: SilverStripe\MimeValidator\MimeUploadValidator +``` + +If your project overrides the defaults allowed file types, it's important that you take the time to review your configuration and adjust it as need be to work with `silverstripe/mimevalidator`. + +Read the [Allowed file types](/Developer_Guides/Files/Allowed_file_types) documentation for more details on controling the type of files that can be stored in your Silverstrip CMS Project. + +#### Special consideration when upgrading Userforms + +The `silverstripe/userforms` module now also includes `silverstripe/mimevalidator` in its dependencies. Upgrading to the following versions of userforms will automatically install `silverstripe/mimevalidator`: + +* 5.4.3 or later +* 5.5.3 or later +* 5.6.0 or later (requires CMS 4.6.0) + +Userforms that include a file upload field will automatically use the`MimeUploadValidator`. Beware that this will NOT change the default upload validator for other file upload fields in the CMS. You'll need to update your YML configuration for the `MimeUploadValidator` to be used everywhere. + +### CVE-2019-19326 Web Cache Poisoning {#CVE-2019-19326} + +Silverstripe sites using HTTP cache headers and HTTP caching proxies (e.g. CDNs) can be susceptible to web cache poisoning through the: +* `X-Original-Url` HTTP header +* `X-HTTP-Method-Override` HTTP header +* `_method` POST variable. + +In order to remedy this vulnerability, Silverstripe Framework 4.4.7 removes native support for these features. While this is technically a semantic versioning breakage, these features are inherently insecure and date back to a time when browsers didn't natively support the full range of HTTP methods. Sites who still require these features will have highly unusual requirements that are best served by a tailored solution. + +### Re-enabling the support for removed features + +These features are best implemented by defining a `Middleware`. + +The following example illustrates how to implement an `HTTPMiddleware` that restores support for the `X-Original-Url` header and the `_method` POST parameter for requests originating from a trusted proxy. + +```php +getHeader('X-Original-Url'); + if ($originalUrl) { + $_SERVER['REQUEST_URI'] = $originalUrl; + $request->setUrl($originalUrl); + } + $methodOverride = $request->postVar('_method'); + $validMethods = ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']; + if ($methodOverride && in_array(strtoupper($methodOverride), $validMethods)) { + $request->setHttpMethod($methodOverride); + } + } + return $delegate($request); + } +} +``` + +To learn more about re-implementing support for the disabled features: +* read [how to configure trusted proxies](/developer_guides/security/secure_coding/#request-hostname-forgery) on the Silverstripe documentation. +* read the [documentation about HTTP Middlewares](/developer_guides/controllers/middlewares/). + +### CVE-2020-6164 Information disclosure on /interactive URL path + +A specific URL path configured by default through the silverstripe/framework module can be used to disclose the fact that a domain is hosting a Silverstripe application. There is no disclosure of the specific version. The functionality on this URL path is limited to execution in a CLI context, and is not known to present a vulnerability through web-based access. As a side-effect, this preconfigured path also blocks the creation of other resources on this path (e.g. a page). + + + +## Change Log + +### Security + + * 2020-05-13 [91d30db88](https://github.com/silverstripe/silverstripe-framework/commit/91d30db88f68b9b87980ef9a59e208a81980b72c) Remove/deprecate unused controllers that can potentially give away some information about the underlying project. (Maxime Rainville) - See [cve-2020-6164](https://www.silverstripe.org/download/security-releases/cve-2020-6164) + * 2020-05-11 [107706c12](https://github.com/silverstripe/silverstripe-framework/commit/107706c12cd9cf4d1b8b96b6a6e223633209d851) Stop honouring X-HTTP-Method-Override header, X-Original-Url header and _method POST variable. Add SS_HTTPRequest::setHttpMethod() (Maxime Rainville) - See [cve-2019-19326](https://www.silverstripe.org/download/security-releases/cve-2019-19326) + +### Bugfixes + + * 2020-06-01 [3df2222](https://github.com/silverstripe/silverstripe-asset-admin/commit/3df222203ee563fac840e5e0727c75ddfe244886) Prevent react-selectable from interfering with pagination (Maxime Rainville) + * 2020-05-05 [2cc037b](https://github.com/silverstripe/silverstripe-versioned/commit/2cc037b2d305ed98056a9232587351949e59561f) Fix merge conflict in Travis configuration (Robbie Averill) + * 2020-02-24 [bba0f2f72](https://github.com/silverstripe/silverstripe-framework/commit/bba0f2f72fa2e631dbf60357a908d5d57d4467ee) Fixed issue where TimeField_Readonly would only show "(not set)" instead of the value (UndefinedOffset) + * 2020-02-18 [e0de15f](https://github.com/silverstripe/silverstripe-errorpage/commit/e0de15f85a09ac848cb110f49cef58624d1e892f) Fix broken test when FulltextSearchable is enabled (Maxime Rainville) + * 2019-09-02 [6d8a4bc](https://github.com/silverstripe/silverstripe-assets/commit/6d8a4bc4f4178c0b56ede1b01f87b162066d550a) Make AbsoluteLink work with manipulated images (fixes #322) (Loz Calver) +