‪TYPO3CMS  9.5
SecurityTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
26 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\ActionService;
27 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
28 
32 class ‪SecurityTest extends FunctionalTestCase
33 {
37  private ‪$backendUser;
38 
42  private ‪$actionService;
43 
47  protected ‪$coreExtensionsToLoad = ['rte_ckeditor'];
48 
49  protected function ‪setUp(): void
50  {
51  parent::setUp();
52  $this->importDataSet('PACKAGE:typo3/testing-framework/Resources/Core/Functional/Fixtures/pages.xml');
53  $this->backendUser = $this->setUpBackendUserFromFixture(1);
54  $this->backendUser->workspace = 0;
55  GeneralUtility::makeInstance(Context::class)
56  ->setAspect('workspace', new ‪WorkspaceAspect(0));
58 
59  $this->actionService = GeneralUtility::makeInstance(ActionService::class);
60  }
61 
62  public function ‪crossSiteScriptingDataProvider(): array
63  {
64  return [
65  [
66  'The "test" value might be =< x or > y...', // submitted payload
67  [
68  // @todo issue in `masterminds/html5`, first `<` should be parsed and encoded to `&lt;`
69  'The "test" value might be = x or &gt; y...', // default processing, HTML Sanitizer enabled
70  'The "test" value might be =< x or > y...', // default processing, HTML Sanitizer disabled
71  ],
72  ],
73  [
74  '<p undefined="<not-allowed>"></p>',
75  [
76  '<p></p>',
77  '<p></p>',
78  ],
79  ],
80  [
81  '<p undefined=<not-allowed>></p>',
82  [
83  '<p></p>',
84  '<p></p>',
85  ],
86  ],
87  [
88  '<p title="<encode-me>"></p>',
89  [
90  '<p title="<encode-me>"></p>',
91  '<p title="&lt;encode-me&gt;"></p>',
92  ],
93  ],
94  [
95  '<p title=<encode-me>></p>',
96  [
97  '<p title="<encode-me>"></p>',
98  '<p title="&lt;encode-me&gt;"></p>',
99  ],
100  ],
101  [
102  '<p title="""></p>',
103  [
104  '<p></p>',
105  '<p></p>',
106  ],
107  ],
108  [
109  '<p title="title"></p>',
110  [
111  '<p title="title"></p>',
112  '<p title="title"></p>',
113  ],
114  ],
115  [
116  '<p title="escape"<img src=src>"></p>',
117  [
118  '<p title="escape">"&gt;</p>',
119  '<p title="escape">"></p>',
120  ],
121  ],
122  [
123  '<p title=""""></p>',
124  [
125  '<p title></p>',
126  '<p title></p>',
127  ],
128  ],
129  [
130  '<p title=""anything"></p>',
131  [
132  '<p></p>',
133  '<p></p>',
134  ],
135  ],
136  [
137  '<p title=""anything""></p>',
138  [
139  '<p title></p>',
140  '<p title></p>',
141  ],
142  ],
143  [
144  '<p title="anything""></p>',
145  [
146  '<p></p>',
147  '<p></p>',
148  ],
149  ],
150  [
151  '<not-allowed><p title="</not-allowed><img src=x onerror=alert(1)><img src=x onerror=alert(2)>',
152  [
153  '<p>&lt;not-allowed&gt;</p>' . "\r\n" . '<p></p>',
154  '<p>&lt;not-allowed&gt;</p>' . "\r\n" . '<p></p>',
155  ],
156  ],
157  [
158  '<not-allowed><p title="</not-allowed><img src="x" onerror="alert(1)"><img src="x" onerror="alert(2)">',
159  [
160  '<p>&lt;not-allowed&gt;</p>' . "\r\n" . '<p></p>',
161  '<p>&lt;not-allowed&gt;</p>' . "\r\n" . '<p></p>',
162  ],
163  ],
164  [
165  '<script>alert(3)</script>',
166  [
167  '&lt;script&gt;alert(3)&lt;/script&gt;',
168  '&lt;script&gt;alert(3)&lt;/script&gt;',
169  ],
170  ],
171  [
172  '<p><script>alert(3)</script></p>',
173  [
174  '<p>&lt;script&gt;alert(3)&lt;/script&gt;</p>',
175  '<p>&lt;script&gt;alert(3)&lt;/script&gt;</p>',
176  ],
177  ],
178  [
179  '<title>title</title>',
180  [
181  '&lt;title&gt;title&lt;/title&gt;',
182  '&lt;title&gt;title&lt;/title&gt;',
183  ],
184  ],
185  [
186  '<p><title>title</title></p>',
187  [
188  '<p>&lt;title&gt;title&lt;/title&gt;</p>',
189  '<p>&lt;title&gt;title&lt;/title&gt;</p>',
190  ],
191  ],
192  [
193  '<font face="a" color="b" onmouseover="alert(1);">text</font>'
194  . '<img src="x" alt="test" onerror="alert(2)">',
195  [
196  // @todo `ts_images` in `RteHtmlParser` adds (empty) `alt` and `style`
197  '<font face="a" color="b">text</font>'
198  . '<img src="x" alt="test" style>',
199  // @todo "expected" for the time being without using HTML Sanitizer
200  '<font face="a" color="b" onmouseover="alert(1);">text</font>'
201  . '<img src="x" alt="test" onerror="alert(2)" style="" />',
202  ],
203  ],
204  [
205  '<p>'
206  . '<font face="a" color="b" onmouseover="alert(1);">text</font>'
207  . '<img src="x" alt="test" onerror="alert(2)">'
208  . '</p>',
209  [
210  // @todo `ts_images` in `RteHtmlParser` adds (empty) `alt` and `style`
211  '<p><font face="a" color="b">text</font>'
212  . '<img src="x" alt="test" style></p>',
213  // @todo "expected" for the time being without using HTML Sanitizer
214  '<p><font face="a" color="b" onmouseover="alert(1);">text</font>'
215  . '<img src="x" alt="test" onerror="alert(2)" style="" /></p>',
216  ],
217  ],
218  [
219  '<p><a href="https://typo3.org" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
220  [
221  '<p><a href="https://typo3.org" target="_blank" rel="noreferrer" role="button">text</a></p>',
222  // @todo "expected" for the time being without using HTML Sanitizer
223  '<p><a href="https://typo3.org" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
224  ],
225  ],
226  [
227  '<p><a href="t3://page?uid=1" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
228  [
229  '<p><a href="t3://page?uid=1" target="_blank" rel="noreferrer" role="button">text</a></p>',
230  // @todo "expected" for the time being without using HTML Sanitizer
231  '<p><a href="t3://page?uid=1" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
232  ],
233  ],
234  ];
235  }
236 
248  public function ‪markupIsSanitizedForContentBodytextWithHtmlSanitizerEnabled(string $input, array $expectations): void
249  {
250  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['security.backend.htmlSanitizeRte'] = true;
251  $newIds = $this->actionService->createNewRecord('tt_content', 1, [
252  'CType' => 'text',
253  'bodytext' => $input,
254  ]);
255  $contentId = current($newIds['tt_content'] ?? 0);
256  self::assertGreaterThan(0, $contentId, 'Could not resolve content id');
257 
258  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
259  ->getConnectionForTable('tt_content');
260  $record = $connection->select(['bodytext'], 'tt_content', ['uid' => (int)$contentId])->fetch();
261  $bodytext = $record['bodytext'] ?? null;
262 
263  $expectation = $expectations[0];
264  self::assertSame($expectation, $bodytext, sprintf('Given markup: `%s`', $input));
265  }
266 
278  public function ‪markupIsSanitizedForContentBodytextWithHtmlSanitizerDisabled(string $input, array $expectations): void
279  {
280  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['security.backend.htmlSanitizeRte'] = false;
281  $newIds = $this->actionService->createNewRecord('tt_content', 1, [
282  'CType' => 'text',
283  'bodytext' => $input,
284  ]);
285  $contentId = current($newIds['tt_content'] ?? 0);
286  self::assertGreaterThan(0, $contentId, 'Could not resolve content id');
287 
288  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
289  ->getConnectionForTable('tt_content');
290  $record = $connection->select(['bodytext'], 'tt_content', ['uid' => (int)$contentId])->fetch();
291  $bodytext = $record['bodytext'] ?? null;
292 
293  $expectation = $expectations[1];
294  self::assertSame($expectation, $bodytext, sprintf('Given markup: `%s`', $input));
295  }
296 }
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler
Definition: DefaultValuesTest.php:17
‪TYPO3\CMS\Core\Context\WorkspaceAspect
Definition: WorkspaceAspect.php:29
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\$backendUser
‪BackendUserAuthentication $backendUser
Definition: SecurityTest.php:36
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\crossSiteScriptingDataProvider
‪crossSiteScriptingDataProvider()
Definition: SecurityTest.php:59
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:49
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\markupIsSanitizedForContentBodytextWithHtmlSanitizerDisabled
‪markupIsSanitizedForContentBodytextWithHtmlSanitizerDisabled(string $input, array $expectations)
Definition: SecurityTest.php:275
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\markupIsSanitizedForContentBodytextWithHtmlSanitizerEnabled
‪markupIsSanitizedForContentBodytextWithHtmlSanitizerEnabled(string $input, array $expectations)
Definition: SecurityTest.php:245
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\$coreExtensionsToLoad
‪string[] $coreExtensionsToLoad
Definition: SecurityTest.php:44
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\$actionService
‪ActionService $actionService
Definition: SecurityTest.php:40
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Core\Bootstrap
Definition: Bootstrap.php:50
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\setUp
‪setUp()
Definition: SecurityTest.php:46
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest
Definition: SecurityTest.php:33
‪TYPO3\CMS\Core\Core\Bootstrap\initializeLanguageObject
‪static Bootstrap null initializeLanguageObject()
Definition: Bootstrap.php:986