‪TYPO3CMS  ‪main
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 
25 use TYPO3\TestingFramework\Core\Functional\Framework\DataHandling\ActionService;
26 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
27 
31 final class ‪SecurityTest extends FunctionalTestCase
32 {
33  private ActionService ‪$actionService;
34 
35  protected array ‪$coreExtensionsToLoad = ['rte_ckeditor'];
36 
37  protected function ‪setUp(): void
38  {
39  parent::setUp();
40  $this->importCSVDataSet(__DIR__ . '/DataSet/pages.csv');
41  $this->importCSVDataSet(__DIR__ . '/../../Fixtures/be_users_admin.csv');
42  $backendUser = $this->setUpBackendUser(1);
43  $backendUser->workspace = 0;
44  GeneralUtility::makeInstance(Context::class)
45  ->setAspect('workspace', new ‪WorkspaceAspect(0));
46  ‪$GLOBALS['LANG'] = $this->get(LanguageServiceFactory::class)->createFromUserPreferences($backendUser);
47 
48  $this->actionService = GeneralUtility::makeInstance(ActionService::class);
49  }
50 
51  public static function ‪crossSiteScriptingDataProvider(): array
52  {
53  return [
54  [
55  'The "test" value might be =< x or > y...', // submitted payload
56  [
57  // @todo issue in `masterminds/html5`, first `<` should be parsed and encoded to `&lt;`
58  'The "test" value might be = x or &gt; y...', // default processing, HTML Sanitizer enabled
59  'The "test" value might be =< x or > y...', // default processing, HTML Sanitizer disabled
60  ],
61  ],
62  [
63  '<p undefined="<not-allowed>"></p>',
64  [
65  '<p></p>',
66  '<p></p>',
67  ],
68  ],
69  [
70  '<p undefined=<not-allowed>></p>',
71  [
72  '<p></p>',
73  '<p></p>',
74  ],
75  ],
76  [
77  '<p title="<encode-me>"></p>',
78  [
79  '<p title="&lt;encode-me&gt;"></p>',
80  '<p title="&lt;encode-me&gt;"></p>',
81  ],
82  ],
83  [
84  '<p title=<encode-me>></p>',
85  [
86  '<p title="&lt;encode-me&gt;"></p>',
87  '<p title="&lt;encode-me&gt;"></p>',
88  ],
89  ],
90  [
91  '<p title="""></p>',
92  [
93  '<p></p>',
94  '<p></p>',
95  ],
96  ],
97  [
98  '<p title="title"></p>',
99  [
100  '<p title="title"></p>',
101  '<p title="title"></p>',
102  ],
103  ],
104  [
105  '<p title="escape"<img src=src>"></p>',
106  [
107  '<p title="escape">"&gt;</p>',
108  '<p title="escape">"></p>',
109  ],
110  ],
111  [
112  '<p title=""""></p>',
113  [
114  '<p title></p>',
115  '<p title></p>',
116  ],
117  ],
118  [
119  '<p title=""anything"></p>',
120  [
121  '<p></p>',
122  '<p></p>',
123  ],
124  ],
125  [
126  '<p title=""anything""></p>',
127  [
128  '<p title></p>',
129  '<p title></p>',
130  ],
131  ],
132  [
133  '<p title="anything""></p>',
134  [
135  '<p></p>',
136  '<p></p>',
137  ],
138  ],
139  [
140  '<not-allowed><p title="</not-allowed><img src=x onerror=alert(1)><img src=x onerror=alert(2)>',
141  [
142  '<p>&lt;not-allowed&gt;</p>' . "\r\n" . '<p></p>',
143  '<p>&lt;not-allowed&gt;</p>' . "\r\n" . '<p></p>',
144  ],
145  ],
146  [
147  '<not-allowed><p title="</not-allowed><img src="x" onerror="alert(1)"><img src="x" onerror="alert(2)">',
148  [
149  '<p>&lt;not-allowed&gt;</p>' . "\r\n" . '<p></p>',
150  '<p>&lt;not-allowed&gt;</p>' . "\r\n" . '<p></p>',
151  ],
152  ],
153  [
154  '<script>alert(3)</script>',
155  [
156  '&lt;script&gt;alert(3)&lt;/script&gt;',
157  '&lt;script&gt;alert(3)&lt;/script&gt;',
158  ],
159  ],
160  [
161  '<p><script>alert(3)</script></p>',
162  [
163  '<p>&lt;script&gt;alert(3)&lt;/script&gt;</p>',
164  '<p>&lt;script&gt;alert(3)&lt;/script&gt;</p>',
165  ],
166  ],
167  [
168  '<title>title</title>',
169  [
170  '&lt;title&gt;title&lt;/title&gt;',
171  '&lt;title&gt;title&lt;/title&gt;',
172  ],
173  ],
174  [
175  '<p><title>title</title></p>',
176  [
177  '<p>&lt;title&gt;title&lt;/title&gt;</p>',
178  '<p>&lt;title&gt;title&lt;/title&gt;</p>',
179  ],
180  ],
181  [
182  '<font face="a" color="b" onmouseover="alert(1);">text</font>'
183  . '<img src="x" alt="test" onerror="alert(2)">',
184  [
185  '<font face="a" color="b">text</font>'
186  . '<img src="x" alt="test">',
187  // @todo "expected" for the time being without using HTML Sanitizer
188  '<font face="a" color="b" onmouseover="alert(1);">text</font>'
189  . '<img src="x" alt="test" onerror="alert(2)">',
190  ],
191  ],
192  [
193  '<p>'
194  . '<font face="a" color="b" onmouseover="alert(1);">text</font>'
195  . '<img src="x" alt="test" onerror="alert(2)">'
196  . '</p>',
197  [
198  '<p><font face="a" color="b">text</font>'
199  . '<img src="x" alt="test"></p>',
200  // @todo "expected" for the time being without using HTML Sanitizer
201  '<p><font face="a" color="b" onmouseover="alert(1);">text</font>'
202  . '<img src="x" alt="test" onerror="alert(2)"></p>',
203  ],
204  ],
205  [
206  '<p><a href="https://typo3.org" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
207  [
208  '<p><a href="https://typo3.org" target="_blank" rel="noreferrer" role="button">text</a></p>',
209  // @todo "expected" for the time being without using HTML Sanitizer
210  '<p><a href="https://typo3.org" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
211  ],
212  ],
213  [
214  '<p><a href="t3://page?uid=1" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
215  [
216  '<p><a href="t3://page?uid=1" target="_blank" rel="noreferrer" role="button">text</a></p>',
217  // @todo "expected" for the time being without using HTML Sanitizer
218  '<p><a href="t3://page?uid=1" target="_blank" rel="noreferrer" role="button" onmouseover="alert(1)">text</a></p>',
219  ],
220  ],
221  [
222  '<?xml >s<img src=x onerror=alert(1)> ?>',
223  [
224  '&lt;?xml &gt;s&lt;img src=x onerror=alert(1)&gt; ?&gt;',
225  '<?xml >s<img src=x onerror=alert(1)> ?>',
226  ],
227  ],
228  ];
229  }
230 
240  public function ‪markupIsSanitizedForContentBodytextWithHtmlSanitizerEnabled(string $input, array $expectations): void
241  {
242  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['security.backend.htmlSanitizeRte'] = true;
243  $newIds = $this->actionService->createNewRecord('tt_content', 1, [
244  'CType' => 'text',
245  'bodytext' => $input,
246  ]);
247  $contentId = current($newIds['tt_content'] ?? 0);
248  self::assertGreaterThan(0, $contentId, 'Could not resolve content id');
249 
250  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
251  ->getConnectionForTable('tt_content');
252  ‪$record = $connection->select(['bodytext'], 'tt_content', ['uid' => (int)$contentId])->fetchAssociative();
253  $bodytext = ‪$record['bodytext'] ?? null;
254 
255  $expectation = $expectations[0];
256  self::assertSame($expectation, $bodytext, sprintf('Given markup: `%s`', $input));
257  }
258 
268  public function ‪markupIsSanitizedForContentBodytextWithHtmlSanitizerDisabled(string $input, array $expectations): void
269  {
270  ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['security.backend.htmlSanitizeRte'] = false;
271  $newIds = $this->actionService->createNewRecord('tt_content', 1, [
272  'CType' => 'text',
273  'bodytext' => $input,
274  ]);
275  $contentId = current($newIds['tt_content'] ?? 0);
276  self::assertGreaterThan(0, $contentId, 'Could not resolve content id');
277 
278  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
279  ->getConnectionForTable('tt_content');
280  ‪$record = $connection->select(['bodytext'], 'tt_content', ['uid' => (int)$contentId])->fetchAssociative();
281  $bodytext = ‪$record['bodytext'] ?? null;
282 
283  $expectation = $expectations[1];
284  self::assertSame($expectation, $bodytext, sprintf('Given markup: `%s`', $input));
285  }
286 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler
Definition: CheckboxValidationTest.php:18
‪TYPO3\CMS\Core\Context\WorkspaceAspect
Definition: WorkspaceAspect.php:31
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\$coreExtensionsToLoad
‪array $coreExtensionsToLoad
Definition: SecurityTest.php:35
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\markupIsSanitizedForContentBodytextWithHtmlSanitizerDisabled
‪markupIsSanitizedForContentBodytextWithHtmlSanitizerDisabled(string $input, array $expectations)
Definition: SecurityTest.php:268
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\markupIsSanitizedForContentBodytextWithHtmlSanitizerEnabled
‪markupIsSanitizedForContentBodytextWithHtmlSanitizerEnabled(string $input, array $expectations)
Definition: SecurityTest.php:240
‪TYPO3\CMS\Webhooks\Message\$record
‪identifier readonly int readonly array $record
Definition: PageModificationMessage.php:36
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\$actionService
‪ActionService $actionService
Definition: SecurityTest.php:33
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\crossSiteScriptingDataProvider
‪static crossSiteScriptingDataProvider()
Definition: SecurityTest.php:51
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest\setUp
‪setUp()
Definition: SecurityTest.php:37
‪TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler\SecurityTest
Definition: SecurityTest.php:32