Skip to content

Commit

Permalink
[SECURITY] Encode child node variables in f:asset.css view helper
Browse files Browse the repository at this point in the history
Variables in child nodes like `<f:asset.css>{value}</f:asset.css>`
were not encoded and allow cross-site scripting. In case values shall
be taken as is, corresponding `f:format.raw` instruction has to be used.

Resolves: #97900
Releases: main, 11.5, 10.4
Change-Id: Id843a41c42bbe1f74cdc4efbc117b24d20026b97
Security-Bulletin: TYPO3-CORE-SA-2022-010
Security-References: CVE-2022-36108
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75713
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
  • Loading branch information
ohader committed Sep 13, 2022
1 parent 5462084 commit c62e16f
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
Expand Up @@ -51,7 +51,7 @@ class CssViewHelper extends AbstractTagBasedViewHelper
*
* @var bool
*/
protected $escapeChildren = false;
protected $escapeChildren = true;

/**
* @var AssetCollector
Expand Down
Expand Up @@ -18,6 +18,8 @@
namespace TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Asset;

use TYPO3\CMS\Core\Page\AssetCollector;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
use TYPO3\CMS\Fluid\ViewHelpers\Asset\CssViewHelper;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;

Expand Down Expand Up @@ -82,4 +84,76 @@ public function booleanAttributesAreProperlyConverted(): void
self::assertSame($collectedJavaScripts['test']['source'], 'my.css');
self::assertSame($collectedJavaScripts['test']['attributes'], ['disabled' => 'disabled']);
}

public static function childNodeRenderingIsCorrectDataProvider(): array
{
return [
// Double quotes
'variable with double quotes is encoded' => [
'</style>/* " ', // variable value
'body { color: #{color}; }', // inner template source
'body { color: #&lt;/style&gt;/* &quot; ; }', // expectation
],
'variable with double quotes is encoded in single quotes' => [
'</style>/* " ', // variable value
'body { color: \'#{color}\'; }', // inner template source
'body { color: \'#&lt;/style&gt;/* &quot; \'; }', // expectation
],
'variable with double quotes is encoded in double quotes' => [
'</style>/* " ', // variable value
'body { color: "#{color}"; }', // inner template source
'body { color: "#&lt;/style&gt;/* &quot; "; }', // expectation
],
// Single quotes
'variable with single quotes is encoded' => [
'</style>/* \' ', // variable value
'body { color: #{color}; }', // inner template source
'body { color: #&lt;/style&gt;/* &#039; ; }', // expectation
],
'variable with single quotes is encoded in single quotes' => [
'</style>/* \' ', // variable value
'body { color: \'#{color}\'; }', // inner template source
'body { color: \'#&lt;/style&gt;/* &#039; \'; }', // expectation
],
'variable with single quotes is encoded in double quotes' => [
'</style>/* \' ', // variable value
'body { color: "#{color}"; }', // inner template source
'body { color: "#&lt;/style&gt;/* &#039; "; }', // expectation
],
// Raw instruction
'raw instruction is passed' => [
'</style>/* " ',
'body { color: #{color -> f:format.raw()}; }',
'body { color: #</style>/* " ; }',
],
'raw instruction is passed in sigle quotes' => [
'</style>/* " ',
'body { color: \'#{color -> f:format.raw()}\'; }',
'body { color: \'#</style>/* " \'; }',
],
'raw instruction is passed in double quotes' => [
'</style>/* " ',
'body { color: "#{color -> f:format.raw()}"; }',
'body { color: "#</style>/* " "; }',
],
];
}

/**
* @test
* @dataProvider childNodeRenderingIsCorrectDataProvider
*/
public function childNodeRenderingIsCorrect(string $value, string $source, string $expectation): void
{
$assetCollector = new AssetCollector();
GeneralUtility::setSingletonInstance(AssetCollector::class, $assetCollector);

$view = new StandaloneView();
$view->setTemplateSource(sprintf('<f:asset.css identifier="test">%s</f:asset.css>', $source));
$view->assign('color', $value);
$view->render();
GeneralUtility::removeSingletonInstance(AssetCollector::class, $assetCollector);

self::assertSame($expectation, $assetCollector->getInlineStyleSheets()['test']['source']);
}
}

0 comments on commit c62e16f

Please sign in to comment.