‪TYPO3CMS  10.4
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  '<font face="a" color="b">text</font>'
197  . '<img src="x" alt="test">',
198  // @todo "expected" for the time being without using HTML Sanitizer
199  '<font face="a" color="b" onmouseover="alert(1);">text</font>'
200  . '<img src="x" alt="test" onerror="alert(2)">',
201  ],
202  ],
203  [
204  '<p>'
205  . '<font face="a" color="b" onmouseover="alert(1);">text</font>'
206  . '<img src="x" alt="test" onerror="alert(2)">'
207  . '</p>',
208  [
209  '<p><font face="a" color="b">text</font>'
210  . '<img src="x" alt="test"></p>',
211  // @todo "expected" for the time being without using HTML Sanitizer
212  '<p><font face="a" color="b" onmouseover="alert(1);">text</font>'
213  . '<img src="x" alt="test" onerror="alert(2)"></p>',
214  ],
215  ],
216  [
217  '<p><a href="https://typo3.org" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
218  [
219  '<p><a href="https://typo3.org" target="_blank" rel="noreferrer" role="button">text</a></p>',
220  // @todo "expected" for the time being without using HTML Sanitizer
221  '<p><a href="https://typo3.org" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
222  ],
223  ],
224  [
225  '<p><a href="t3://page?uid=1" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
226  [
227  '<p><a href="t3://page?uid=1" target="_blank" rel="noreferrer" role="button">text</a></p>',
228  // @todo "expected" for the time being without using HTML Sanitizer
229  '<p><a href="t3://page?uid=1" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
230  ],
231  ],
232  ];
233  }
234 
246  public function ‪markupIsSanitizedForContentBodytextWithHtmlSanitizerEnabled(string $input, array $expectations): void
247  {
248  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['security.backend.htmlSanitizeRte'] = true;
249  $newIds = $this->actionService->createNewRecord('tt_content', 1, [
250  'CType' => 'text',
251  'bodytext' => $input,
252  ]);
253  $contentId = current($newIds['tt_content'] ?? 0);
254  self::assertGreaterThan(0, $contentId, 'Could not resolve content id');
255 
256  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
257  ->getConnectionForTable('tt_content');
258  $record = $connection->select(['bodytext'], 'tt_content', ['uid' => (int)$contentId])->fetch();
259  $bodytext = $record['bodytext'] ?? null;
260 
261  $expectation = $expectations[0];
262  self::assertSame($expectation, $bodytext, sprintf('Given markup: `%s`', $input));
263  }
264 
276  public function ‪markupIsSanitizedForContentBodytextWithHtmlSanitizerDisabled(string $input, array $expectations): void
277  {
278  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['security.backend.htmlSanitizeRte'] = false;
279  $newIds = $this->actionService->createNewRecord('tt_content', 1, [
280  'CType' => 'text',
281  'bodytext' => $input,
282  ]);
283  $contentId = current($newIds['tt_content'] ?? 0);
284  self::assertGreaterThan(0, $contentId, 'Could not resolve content id');
285 
286  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
287  ->getConnectionForTable('tt_content');
288  $record = $connection->select(['bodytext'], 'tt_content', ['uid' => (int)$contentId])->fetch();
289  $bodytext = $record['bodytext'] ?? null;
290 
291  $expectation = $expectations[1];
292  self::assertSame($expectation, $bodytext, sprintf('Given markup: `%s`', $input));
293  }
294 }
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler
Definition: DefaultValuesTest.php:18
‪TYPO3\CMS\Core\Context\WorkspaceAspect
Definition: WorkspaceAspect.php:31
‪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:53
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\markupIsSanitizedForContentBodytextWithHtmlSanitizerDisabled
‪markupIsSanitizedForContentBodytextWithHtmlSanitizerDisabled(string $input, array $expectations)
Definition: SecurityTest.php:273
‪TYPO3\CMS\Core\Core\Bootstrap\initializeLanguageObject
‪static initializeLanguageObject()
Definition: Bootstrap.php:617
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\markupIsSanitizedForContentBodytextWithHtmlSanitizerEnabled
‪markupIsSanitizedForContentBodytextWithHtmlSanitizerEnabled(string $input, array $expectations)
Definition: SecurityTest.php:243
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪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:66
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪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