[BUGFIX] Add missing namespace parts
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Legacy / typo3 / contrib / class.removexssTest.php
1 <?php
2 /*
3 * This file is part of the TYPO3 CMS project.
4 *
5 * It is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License, either version 2
7 * of the License, or any later version.
8 *
9 * For the full copyright and license information, please read the
10 * LICENSE.txt file that was distributed with this source code.
11 *
12 * The TYPO3 project - inspiring people to share!
13 */
14
15 /**
16 * Testcase for class RemoveXSS
17 * @ see http://ha.ckers.org/xss.html
18 * @ examples from http://ha.ckers.org/xssAttacks.xml
19 */
20 class RemoveXSSTest extends \TYPO3\Components\TestingFramework\Core\Unit\UnitTestCase
21 {
22 /**
23 * @test
24 */
25 public function checkAttackScriptAlert()
26 {
27 $testString = "<SCRIPT>alert('XSS')</SCRIPT>";
28 $expectedString = "<sc<x>ript>alert('XSS')</SCRIPT>";
29 $actualString = RemoveXSS::process($testString);
30
31 $this->assertEquals($expectedString, $actualString);
32 }
33 /**
34 * @test
35 */
36 public function checkAttackScriptSrcJs()
37 {
38 $testString = '<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>';
39 $expectedString = '<sc<x>ript SRC=http://ha.ckers.org/xss.js></SCRIPT>';
40 $actualString = RemoveXSS::process($testString);
41
42 $this->assertEquals($expectedString, $actualString);
43 }
44 /**
45 * @test
46 */
47 public function checkAttackScriptAlertFromCharCode()
48 {
49 $testString = '<SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>';
50 $expectedString = '<sc<x>ript>alert(String.fromCharCode(88,83,83))</SCRIPT>';
51 $actualString = RemoveXSS::process($testString);
52
53 $this->assertEquals($expectedString, $actualString);
54 }
55 /**
56 * @test
57 */
58 public function checkAttackBaseHref()
59 {
60 $testString = "<BASE HREF=\"javascript:alert('XSS');//\">";
61 $expectedString = "<ba<x>se HREF=\"ja<x>vascript:alert('XSS');//\">";
62 $actualString = RemoveXSS::process($testString);
63
64 $this->assertEquals($expectedString, $actualString);
65 }
66 /**
67 * @test
68 */
69 public function checkAttackBgsound()
70 {
71 $testString = "<BGSOUND SRC=\"javascript:alert('XSS');\">";
72 $expectedString = "<bg<x>sound SRC=\"ja<x>vascript:alert('XSS');\">";
73 $actualString = RemoveXSS::process($testString);
74
75 $this->assertEquals($expectedString, $actualString);
76 }
77 /**
78 * @test
79 */
80 public function checkAttackBodyBackground()
81 {
82 $testString = "<BODY BACKGROUND=\"javascript:alert('XSS');\">";
83 $expectedString = "<BODY BACKGROUND=\"ja<x>vascript:alert('XSS');\">";
84 $actualString = RemoveXSS::process($testString);
85
86 $this->assertEquals($expectedString, $actualString);
87 }
88 /**
89 * @test
90 */
91 public function checkAttackBodyOnLoad()
92 {
93 $testString = "<BODY ONLOAD=alert('XSS')>";
94 $expectedString = "<BODY on<x>load=alert('XSS')>";
95 $actualString = RemoveXSS::process($testString);
96
97 $this->assertEquals($expectedString, $actualString);
98 }
99 /**
100 * @test
101 */
102 public function checkAttackStyleUrl()
103 {
104 $testString = "<DIV STYLE=\"background-image: url(javascript:alert('XSS'))\">";
105 $expectedString = "<DIV st<x>yle=\"background-image: url(ja<x>vascript:alert('XSS'))\">";
106 $actualString = RemoveXSS::process($testString);
107
108 $this->assertEquals($expectedString, $actualString);
109 }
110 /**
111 * @test
112 */
113 public function checkAttackStyleWidth()
114 {
115 $testString = "<DIV STYLE=\"width: expression(alert('XSS'));\">";
116 $expectedString = "<DIV st<x>yle=\"width: expression(alert('XSS'));\">";
117 $actualString = RemoveXSS::process($testString);
118
119 $this->assertEquals($expectedString, $actualString);
120 }
121 /**
122 * @test
123 */
124 public function checkAttackFrameset()
125 {
126 $testString = "<FRAMESET><FRAME SRC=\"javascript:alert('XSS');\"></FRAMESET>";
127 $expectedString = "<fr<x>ameset><fr<x>ame SRC=\"ja<x>vascript:alert('XSS');\"></FRAMESET>";
128 $actualString = RemoveXSS::process($testString);
129
130 $this->assertEquals($expectedString, $actualString);
131 }
132 /**
133 * @test
134 */
135 public function checkAttackIframe()
136 {
137 $testString = "<IFRAME SRC=\"javascript:alert('XSS');\"></IFRAME>";
138 $expectedString = "<if<x>rame SRC=\"ja<x>vascript:alert('XSS');\"></IFRAME>";
139 $actualString = RemoveXSS::process($testString);
140
141 $this->assertEquals($expectedString, $actualString);
142 }
143 /**
144 * @test
145 */
146 public function checkAttackInputImage()
147 {
148 $testString = "<INPUT TYPE=\"IMAGE\" SRC=\"javascript:alert('XSS');\">";
149 $expectedString = "<INPUT TYPE=\"IMAGE\" SRC=\"ja<x>vascript:alert('XSS');\">";
150 $actualString = RemoveXSS::process($testString);
151
152 $this->assertEquals($expectedString, $actualString);
153 }
154 /**
155 * @test
156 */
157 public function checkAttackImageSrc()
158 {
159 $testString = "<IMG SRC=\"javascript:alert('XSS');\">";
160 $expectedString = "<IMG SRC=\"ja<x>vascript:alert('XSS');\">";
161 $actualString = RemoveXSS::process($testString);
162
163 $this->assertEquals($expectedString, $actualString);
164 }
165 /**
166 * @test
167 */
168 public function checkAttackImageSrcNoQuotesNoSemicolon()
169 {
170 $testString = "<IMG SRC=javascript:alert('XSS')>";
171 $expectedString = "<IMG SRC=ja<x>vascript:alert('XSS')>";
172 $actualString = RemoveXSS::process($testString);
173
174 $this->assertEquals($expectedString, $actualString);
175 }
176 /**
177 * @test
178 */
179 public function checkAttackImageDynsrc()
180 {
181 $testString = "<IMG DYNSRC=\"javascript:alert('XSS');\">";
182 $expectedString = "<IMG DYNSRC=\"ja<x>vascript:alert('XSS');\">";
183 $actualString = RemoveXSS::process($testString);
184
185 $this->assertEquals($expectedString, $actualString);
186 }
187 /**
188 * @test
189 */
190 public function checkAttackImageLowsrc()
191 {
192 $testString = "<IMG LOWSRC=\"javascript:alert('XSS');\">";
193 $expectedString = "<IMG LOWSRC=\"ja<x>vascript:alert('XSS');\">";
194 $actualString = RemoveXSS::process($testString);
195
196 $this->assertEquals($expectedString, $actualString);
197 }
198 /**
199 * @test
200 */
201 public function checkAttackStyle()
202 {
203 $testString = "<STYLE>li {list-style-image: url(\"javascript:alert('XSS')\");}</STYLE>";
204 $expectedString = "<st<x>yle>li {list-style-image: url(\"ja<x>vascript:alert('XSS')\");}</STYLE>";
205 $actualString = RemoveXSS::process($testString);
206
207 $this->assertEquals($expectedString, $actualString);
208 }
209 /**
210 * @test
211 */
212 public function checkAttackImageVbscript()
213 {
214 $testString = "<IMG SRC='vbscript:msgbox(\"XSS\")'>";
215 $expectedString = "<IMG SRC='vb<x>script:msgbox(\"XSS\")'>";
216 $actualString = RemoveXSS::process($testString);
217
218 $this->assertEquals($expectedString, $actualString);
219 }
220 /**
221 * @test
222 */
223 public function checkAttackLayer()
224 {
225 $testString = '<LAYER SRC="http://ha.ckers.org/scriptlet.html"></LAYER>';
226 $expectedString = '<la<x>yer SRC="http://ha.ckers.org/scriptlet.html"></LAYER>';
227 $actualString = RemoveXSS::process($testString);
228
229 $this->assertEquals($expectedString, $actualString);
230 }
231 /**
232 * @test
233 */
234 public function checkAttackMeta()
235 {
236 $testString = '<META HTTP-EQUIV="refresh" CONTENT="0;url=javascript:alert(\'XSS\');">';
237 $expectedString = '<me<x>ta HTTP-EQUIV="refresh" CONTENT="0;url=ja<x>vascript:alert(\'XSS\');">';
238 $actualString = RemoveXSS::process($testString);
239
240 $this->assertEquals($expectedString, $actualString);
241 }
242 /**
243 * @test
244 */
245 public function checkAttackMetaWithUrl()
246 {
247 $testString = '<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">';
248 $expectedString = '<me<x>ta HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">';
249 $actualString = RemoveXSS::process($testString);
250
251 $this->assertEquals($expectedString, $actualString);
252 }
253 /**
254 * @test
255 */
256 public function checkAttackMetaWithUrlExtended()
257 {
258 $testString = '<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert(\'XSS\');">';
259 $expectedString = '<me<x>ta HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=ja<x>vascript:alert(\'XSS\');">';
260 $actualString = RemoveXSS::process($testString);
261
262 $this->assertEquals($expectedString, $actualString);
263 }
264 /**
265 * @test
266 */
267 public function checkAttackObject()
268 {
269 $testString = '<OBJECT TYPE="text/x-scriptlet" DATA="http://ha.ckers.org/scriptlet.html"></OBJECT>';
270 $expectedString = '<ob<x>ject TYPE="text/x-scriptlet" DATA="http://ha.ckers.org/scriptlet.html"></OBJECT>';
271 $actualString = RemoveXSS::process($testString);
272
273 $this->assertEquals($expectedString, $actualString);
274 }
275 /**
276 * @test
277 */
278 public function checkAttackObjectEmbeddedXss()
279 {
280 $testString = '<OBJECT classid=clsid:ae24fdae-03c6-11d1-8b76-0080c744f389><param name=url value=javascript:alert(\'XSS\')></OBJECT>';
281 $expectedString = '<ob<x>ject classid=clsid:ae24fdae-03c6-11d1-8b76-0080c744f389><param name=url value=ja<x>vascript:alert(\'XSS\')></OBJECT>';
282 $actualString = RemoveXSS::process($testString);
283
284 $this->assertEquals($expectedString, $actualString);
285 }
286 /**
287 * @test
288 */
289 public function checkAttackEmbedFlash()
290 {
291 $testString = '<EMBED SRC="http://ha.ckers.org/xss.swf" AllowScriptAccess="always"></EMBED>';
292 $expectedString = '<em<x>bed SRC="http://ha.ckers.org/xss.swf" AllowScriptAccess="always"></EMBED>';
293 $actualString = RemoveXSS::process($testString);
294
295 $this->assertEquals($expectedString, $actualString);
296 }
297 /**
298 * @test
299 */
300 public function checkAttackActionScriptEval()
301 {
302 $testString = 'a="get";b="URL("";c="javascript:";d="alert(\'XSS\');")";eval(a+b+c+d);";';
303 $expectedString = 'a="get";b="URL("";c="ja<x>vascript:";d="alert(\'XSS\');")";eval(a+b+c+d);";';
304 $actualString = RemoveXSS::process($testString);
305
306 $this->assertEquals($expectedString, $actualString);
307 }
308 /**
309 * @test
310 */
311 public function checkAttackImageStyleWithComment()
312 {
313 $testString = '<IMG STYLE="xss:expr/*XSS*/ession(alert(\'XSS\'))">';
314 $expectedString = '<IMG st<x>yle="xss:expr/*XSS*/ession(alert(\'XSS\'))">';
315 $actualString = RemoveXSS::process($testString);
316
317 $this->assertEquals($expectedString, $actualString);
318 }
319 /**
320 * @test
321 */
322 public function checkAttackStyleInAnonymousHtml()
323 {
324 $testString = '<XSS STYLE="xss:expression(alert(\'XSS\'))">';
325 $expectedString = '<XSS st<x>yle="xss:expression(alert(\'XSS\'))">';
326 $actualString = RemoveXSS::process($testString);
327
328 $this->assertEquals($expectedString, $actualString);
329 }
330 /**
331 * @test
332 */
333 public function checkAttackStyleWithBackgroundImage()
334 {
335 $testString = '<STYLE>.XSS{background-image:url("javascript:alert(\'XSS\')");}</STYLE><A CLASS=XSS></A>';
336 $expectedString = '<st<x>yle>.XSS{background-image:url("ja<x>vascript:alert(\'XSS\')");}</STYLE><A CLASS=XSS></A>';
337 $actualString = RemoveXSS::process($testString);
338
339 $this->assertEquals($expectedString, $actualString);
340 }
341 /**
342 * @test
343 */
344 public function checkAttackStyleWithBackground()
345 {
346 $testString = '<STYLE type="text/css">BODY{background:url("javascript:alert(\'XSS\')")}</STYLE>';
347 $expectedString = '<st<x>yle type="text/css">BODY{background:url("ja<x>vascript:alert(\'XSS\')")}</STYLE>';
348 $actualString = RemoveXSS::process($testString);
349
350 $this->assertEquals($expectedString, $actualString);
351 }
352 /**
353 * @test
354 */
355 public function checkAttackStylesheet()
356 {
357 $testString = '<LINK REL="stylesheet" HREF="javascript:alert(\'XSS\');">';
358 $expectedString = '<li<x>nk REL="stylesheet" HREF="ja<x>vascript:alert(\'XSS\');">';
359 $actualString = RemoveXSS::process($testString);
360
361 $this->assertEquals($expectedString, $actualString);
362 }
363 /**
364 * @test
365 */
366 public function checkAttackRemoteStylesheet()
367 {
368 $testString = '<LINK REL="stylesheet" HREF="http://ha.ckers.org/xss.css">';
369 $expectedString = '<li<x>nk REL="stylesheet" HREF="http://ha.ckers.org/xss.css">';
370 $actualString = RemoveXSS::process($testString);
371
372 $this->assertEquals($expectedString, $actualString);
373 }
374 /**
375 * @test
376 */
377 public function checkAttackImportRemoteStylesheet()
378 {
379 $testString = '<STYLE>@import\'http://ha.ckers.org/xss.css\';</STYLE>';
380 $expectedString = '<st<x>yle>@import\'http://ha.ckers.org/xss.css\';</STYLE>';
381 $actualString = RemoveXSS::process($testString);
382
383 $this->assertEquals($expectedString, $actualString);
384 }
385
386 /**
387 * @return array<array> input strings and expected output strings to test
388 *
389 * @see processWithDataProvider
390 */
391 public function processDataProvider()
392 {
393 return [
394 'attackWithHexEncodedCharacter' => [
395 '<a href="j&#x61;vascript:alert(123);">click</a>',
396 '<a href="ja<x>vascript:alert(123);">click</a>',
397 ],
398 'attackWithNestedHexEncodedCharacter' => [
399 '<a href="j&#x6&#x31;;vascript:alert(123);">click</a>',
400 '<a href="ja<x>vascript:alert(123);">click</a>',
401 ],
402 'attackWithUnicodeNumericalEncodedCharacter' => [
403 '<a href="j&#x6&#x31;;vascript:alert(123);">click</a>',
404 '<a href="ja<x>vascript:alert(123);">click</a>',
405 ],
406 'attackWithNestedUnicodeNumericalEncodedCharacter' => [
407 '<a href="j&#6&#53;;vascript:alert(123);">click</a>',
408 '<a href="ja<x>vascript:alert(123);">click</a>',
409 ],
410 'attack with null character' => [
411 '<scr' . chr(0) . 'ipt></script>',
412 '<sc<x>ript></script>'
413 ],
414 'attack with null character in attribute' => [
415 '<a href="j' . chr(0) . 'avascript:alert(123);"></a>',
416 '<a href="ja<x>vascript:alert(123);"></a>'
417 ],
418 ];
419 }
420
421 /**
422 * @test
423 *
424 * @param string $input input value to test
425 * @param string $expected expected output value
426 *
427 * @dataProvider processDataProvider
428 */
429 public function processWithDataProvider($input, $expected)
430 {
431 $this->assertEquals(
432 $expected,
433 RemoveXSS::process($input)
434 );
435 }
436
437 /**
438 * Allowed combinations
439 */
440 public function processValidDataProvider()
441 {
442 return [
443 'multibyte characters' => [
444 '<img®€ÜüÖöÄä></img>',
445 ],
446 'tab' => [
447 '<im' . chr(9) . 'g></img>',
448 ],
449 'line feed' => [
450 '<im' . chr(10) . 'g></img>',
451 ],
452 'carriage return' => [
453 '<im' . chr(13) . 'g></img>',
454 ],
455 ];
456 }
457
458 /**
459 * @test
460 * @param string $input Value to test
461 * @dataProvider processValidDataProvider
462 */
463 public function proccessValidStrings($input)
464 {
465 $this->assertEquals(
466 $input,
467 RemoveXSS::process($input)
468 );
469 }
470 }