Заметка Наиболее полный фильтр XSS для HTML

Темы, которые НЕ подходят по объему под префикс "Статья"
Уже порядка 9 лет я занимаюсь web разработкой и не понаслышке знаю что такое XSS. Так сложилось что избавиться от него крайне сложно почти для любого сайта, где пользователи постят хоть какой-то контент и я собирал все возможные комбинации атак на клиентскую часть. Скрипт получился очень простой и производительный, он не только позволяет спокойно пропускать весь HTML от пользователя и выводить его безопасно, но и прекрасно обрабатывает такие неизвестные уязвимости как encoding mutations.

Mafia.png


Помимо прочего я постарался и добавил возможность вычищать спрятанные в Base64(например, SVG) прослушки.

К сожалению, в последнее время очень многие уязвимости не работают из-за введения в браузер CORS и CSP. Сегодня я обнаружил что перестала работать глубинная base64 в SVG, когда можно было неограниченно в один графический векторный файл вкладывать бесконечное количество base64 со скриптами внутри так глубоко, что его не находили. Лет 5 назад c XSS был полный рай, но сейчас браузер бьет по рукам и уязвимостей становится все меньше и меньше.

Для данного скрипта уязвимости собирались порядка 7 лет и не публикую мануалы по взлому. Расписаны уязвимости внизу класса и, если вы умеете читать регулярные выражения, то c легкостью разберетесь в пошаговом ступенчатом фильтре и выясните что именно работает. Это самый полный список уязвимостей XSS и их комбинаций упакованный в RegExp.

Скрипт умеет чистить атрибуты и теги входного HTML, удалять мутации, а также погружаться в base64 убирать зловредный JavaScript там при этом восстанавливая работоспособность графики и стилей.

Исходный код на PHP:

PHP:
<?php

/*
* Total XSS preventer class by Full-R
*
*/

final class xCleaner {

    public static function clean( string $html ): string {

        return self::cleanXSS(

            preg_replace(

                [

                    '/\s?<iframe[^>]*?>.*?<\/iframe>\s?/si',
                    '/\s?<style[^>]*?>.*?<\/style>\s?/si',
                    '/\s?<script[^>]*?>.*?<\/script>\s?/si',
                    '#\son\w*="[^"]+"#',

                ],

                [
                    '',
                    '',
                    ''
                ],

                $html

            )

        );

    }

    protected static function hexToSymbols( string $s ): string {

        return html_entity_decode($s, ENT_XML1, 'UTF-8');

    }

    protected static function escape( string $s, string $m = 'attr' ): string {

        preg_match_all('/data:\w+\/([a-zA-Z]*);base64,(?!_#_#_)([^)\'"]*)/mi', $s, $b64, PREG_OFFSET_CAPTURE);

        if( count( array_filter( $b64 ) ) > 0 ) {

            switch( $m ) {

                case 'attr':

                    $xclean = self::cleanXSS(

                                        urldecode(

                                            base64_decode(

                                                $b64[ 2 ][ 0 ][ 0 ]

                                            )

                                        )

                                );

                    break;

                case 'tag':

                    $xclean = self::cleanTagInnerXSS(

                                        urldecode(

                                            base64_decode(

                                                $b64[ 2 ][ 0 ][ 0 ]

                                            )

                                        )

                                );

                    break;

            }

            return substr_replace(

                $s,

                '_#_#_'. base64_encode( $xclean ),

                $b64[ 2 ][ 0 ][ 1 ],

                strlen( $b64[ 2 ][ 0 ][ 0 ] )

            );

        }
        else {

            return $s;

        }

    }

    protected static function cleanXSS( string $s ): string {

        // base64 injection prevention
        $st = self::escape( $s, 'attr' );

        return preg_replace([

                // JSON unicode
                '/\\\\u?{?([a-f0-9]{4,}?)}?/mi',                                                                    // [1] unicode JSON clean

                // Data b64 safe
                '/\*\w*\*/mi',                                                                                            // [2] unicode simple clean

                // Malware payloads
                '/:?e[\s]*x[\s]*p[\s]*r[\s]*e[\s]*s[\s]*s[\s]*i[\s]*o[\s]*n[\s]*(:|;|,)?\w*/mi',    // [3]  (:expression) evalution
                '/l[\s]*i[\s]*v[\s]*e[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',         // [4]  (livescript:) evalution
                '/j[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',                                 // [5]  (jscript:) evalution
                '/j[\s]*a[\s]*v[\s]*a[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',       // [6]  (javascript:) evalution
                '/b[\s]*e[\s]*h[\s]*a[\s]*v[\s]*i[\s]*o[\s]*r[\s]*(:|;|,)?\w*/mi',                     // [7]  (behavior:) evalution
                '/v[\s]*b[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t[\s]*(:|;|,)?\w*/mi',                      // [8]  (vsbscript:) evalution
                '/v[\s]*b[\s]*s[\s]*(:|;|,)?\w*/mi',                                                              // [9]  (vbs:) evalution
                '/e[\s]*c[\s]*m[\s]*a[\s]*s[\s]*c[\s]*r[\s]*i[\s]*p[\s]*t*(:|;|,)?\w*/mi',        // [10] (ecmascript:) possible ES evalution
                '/b[\s]*i[\s]*n[\s]*d[\s]*i[\s]*n[\s]*g*(:|;|,)?\w*/mi',                                 // [11] (-binding) payload
                '/\+\/v(8|9|\+|\/)?/mi',                                                                          // [12] (UTF-7 mutation)

                // Some entities
                '/&{\w*}\w*/mi',                                                                                   // [13] html entites clenup
                '/&#\d+;?/m',                                                                                      // [14] html entites clenup

                // Script tag encoding mutation issue
                '/\¼\/?\w*\¾\w*/mi',                                                                         // [21] mutation KOI-8
                '/\+ADw-\/?\w*\+AD4-\w*/mi',                                                         // [22] mutation old encodings

                '/\/*?%00*?\//m',

                // base64 escaped
                '/_#_#_/mi',                                                                                       // [23] base64 escaped marker cleanup
             
            ],

            // Replacements steps :: 23
            ['&#x$1;', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''],

            str_ireplace(

                ['\u0', '&colon;', '&tab;', '&newline;'],
                ['\0', ':', '', ''],

            // U-HEX prepare step
            self::hexToSymbols( $st ))

        );

    }

}

?>
 

Вложения

  • xcleaner.zip
    1,4 КБ · Просмотры: 165
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!