Bug #80888 ยป removexssdatauri.patch

patch for data attributes against 6.2 - Jigal van Hemert, 2017-08-01 11:42

View differences:

typo3/sysext/core/Tests/Legacy/typo3/contrib/class.removexssTest.php (revision )
245 245
    public function checkAttackMetaWithUrl()
246 246
    {
247 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">';
248
        $expectedString = '<me<x>ta HTTP-EQUIV="refresh" CONTENT="0;url=<sc<x>ript>alert(\'XSS\')</script>
249
">';
249 250
        $actualString = RemoveXSS::process($testString);
250 251

  
251 252
        $this->assertEquals($expectedString, $actualString);
......
467 468
            RemoveXSS::process($input)
468 469
        );
469 470
    }
471

  
472
    /**
473
     * @return array<array> input strings and expected output strings to test
474
     *
475
     * @see dataUrlWithDataProvider
476
     */
477
    public function dataUrlDataProvider()
478
    {
479
        return array(
480
            'attackWithUrlEncodedData' => array(
481
                '<a href="data:,%3Cscript%3Ealert%28%27XSS%21%27%29%3B%3C%2Fscript%3E">click</a>',
482
                '<a href="<sc<x>ript>alert(\'XSS!\');</script>">click</a>',
483
            ),
484
            'attackWithUrlEncodedDataAndMimeType' => array(
485
                '<a href="data:text/javascript,%3Cscript%3Ealert%28%27XSS%21%27%29%3B%3C%2Fscript%3E">click</a>',
486
                '<a href="<sc<x>ript>alert(\'XSS!\');</script>">click</a>',
487
            ),
488
            'attackWithUrlEncodedDataAndCharset' => array(
489
                '<a href="data:charset=utf-8,%3Cscript%3Ealert%28%27XSS%21%27%29%3B%3C%2Fscript%3E">click</a>',
490
                '<a href="<sc<x>ript>alert(\'XSS!\');</script>">click</a>',
491
            ),
492
            'attackWithUrlEncodedDataAndMimeTypeAndCharset' => array(
493
                '<a href="data:text/javascript;utf-8,%3Cscript%3Ealert%28%27XSS%21%27%29%3B%3C%2Fscript%3E">click</a>',
494
                '<a href="<sc<x>ript>alert(\'XSS!\');</script>">click</a>',
495
            ),
496
            'attackWithBase64Data' => array(
497
                '<a href="data:base64,PHNjcmlwdD5hbGVydCgnWFNTIScpOzwvc2NyaXB0Pg">click</a>',
498
                '<a href="<sc<x>ript>alert(\'XSS!\');</script>">click</a>',
499
            ),
500
            'attackWithBase64DataAndMimeType' => array(
501
                '<a href="data:text/javascript;base64,PHNjcmlwdD5hbGVydCgnWFNTIScpOzwvc2NyaXB0Pg">click</a>',
502
                '<a href="<sc<x>ript>alert(\'XSS!\');</script>">click</a>',
503
            ),
504
            'attackWithBase64DataAndCharset' => array(
505
                '<a href="data:charset=utf-8;base64,PHNjcmlwdD5hbGVydCgnWFNTIScpOzwvc2NyaXB0Pg">click</a>',
506
                '<a href="<sc<x>ript>alert(\'XSS!\');</script>">click</a>',
507
            ),
508
            'attackWithBase64DataAndMimeTypeAndCharset' => array(
509
                '<a href="data:text/javascript;chareset=utf-8;base64,PHNjcmlwdD5hbGVydCgnWFNTIScpOzwvc2NyaXB0Pg">click</a>',
510
                '<a href="<sc<x>ript>alert(\'XSS!\');</script>">click</a>',
511
            ),
512
        );
513
    }
514

  
515
    /**
516
     * @test
517
     *
518
     * @param string $input input value to test
519
     * @param string $expected expected output value
520
     *
521
     * @dataProvider dataUrlDataProvider
522
     */
523
    public function dataUrlWithDataProvider($input, $expected)
524
    {
525
        $this->assertEquals(
526
            $expected,
527
            RemoveXSS::process($input)
528
        );
529
    }
530

  
470 531
}
typo3/sysext/core/Resources/PHP/RemoveXSS.php (revision )
38 38
        // Note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
39 39
        $value = preg_replace('/([\x00-\x08]|[\x0b-\x0c]|[\x0e-\x19])/', '', $value);
40 40

  
41
        // Replace data URLs as they can obfuscate the payload
42
        if (stripos($value, 'data:') !== false) {
43
            $searchDataUris = '/data:((?<!base64|charset|,).*?)?(;?charset=.+?)?(;?base64)?(\,(?:[A-Za-z0-9+\/\._~%-]+)?)/m';
44
            $value = preg_replace_callback(
45
                $searchDataUris,
46
                function($matches) {
47
                    $entireDataUri = array_shift($matches);
48
                    $data = '';
49
                    $encodingFunction = 'rawurldecode';
50
                    $charset = 'US-ASCII';
51
                    $mimeType = 'text';
52
                    foreach ($matches as $match) {
53
                        if (substr($match, 0, 1) === ',') {
54
                            // check for data block
55
                            $data = substr($match, 1);
56
                        } elseif (substr($match, 0, 7) === ';base64' || substr($match, 0, 6) === 'base64') {
57
                            // check for base64 notation
58
                            $encodingFunction = 'base64_decode';
59
                        } elseif (substr($match, 0, 9) === ';charset=' || substr($match, 0, 8) === 'charset=') {
60
                            // check for charset
61
                            $charset = substr(ltrim($match, ';'), 8);
62
                        } elseif (strpos($match, '/') !== false) {
63
                            // check for mime-type
64
                            $mimeTypeParts = explode('/', $match, 2);
65
                            $mimeType = $mimeTypeParts[0];
66
                        }
67
                    }
68
                    if ($mimeType !== 'text') {
69
                        // Anything else than text does not need handling
70
                        return $entireDataUri;
71
                    }
72
                    // charset handling needed?
73
                    return $encodingFunction($data);
74
                },
75
                $value);
76
        }
77

  
41 78
        // Straight replacements, the user should never need these since they're normal characters.
42 79
        // This prevents like <IMG SRC=&#X40&#X61&#X76&#X61&#X73&#X63&#X72&#X69&#X70&#X74&#X3A&#X61&#X6C&#X65&#X72&#X74&#X28&#X27&#X58&#X53&#X53&#X27&#X29>
43 80
        $searchHexEncodings = '/&#[xX]0{0,8}(21|22|23|24|25|26|27|28|29|2a|2b|2d|2f|30|31|32|33|34|35|36|37|38|39|3a|3b|3d|3f|40|41|42|43|44|45|46|47|48|49|4a|4b|4c|4d|4e|4f|50|51|52|53|54|55|56|57|58|59|5a|5b|5c|5d|5e|5f|60|61|62|63|64|65|66|67|68|69|6a|6b|6c|6d|6e|6f|70|71|72|73|74|75|76|77|78|79|7a|7b|7c|7d|7e);?/i';
    (1-1/1)