Санизировать введенный пользователем CSS

Кто-нибудь знает, как санизировать CSS, введенный через пользовательский ввод? Меня беспокоит межсайтовый скриптинг через CSS. Я использую wp_filter_kses для очистки введенного пользователем HTML, но мне нужно подобное решение для введенных пользователем стилей. До сих пор я использую следующую уродливую и неполную функцию, но мне хотелось бы что-то более полное.

function sanitizeCSS ( $css ) { $css = str_replace( '/-moz-binding/', '', $css ); $css = str_replace( '/expression/', '', $css ); $css = str_replace( '/javascript/', '', $css ); $css = str_replace( '/vbscript/', '', $css ); return $css; } 

Вам понадобится настоящий синтаксический анализатор CSS, подобный этому, чтобы отфильтровать CSS. Регулярные выражения или простые замены строк недостаточно безопасны.

Лучший подход, который я нашел, – включить CSSTidy в мой плагин. Я взял страницу из JetPack, которая имеет пользовательскую функцию CSS.

Реализация CSSTidy JetPack содержится в классе Jetpack_Safe_CSS как функция filter_attr. Я не мог полностью понять, почему JetPack вложил пользователя в CSS внутри элемента div до разбора, но после некоторых проб и ошибок я узнал, что CSSTidy на самом деле не способен анализировать CSS-файл. Этот урок узнал, что я буквально сорвал код с JetPack.

Я загрузил CSSTidy, создал каталог, содержащий файлы PHP CSSTidy. Затем я требую class.csstidy.php по мере необходимости в моем коде и инициализирую новый объект csstidy. Гнездо CSS, которое должно быть проверено в элементе «div», проанализировать его с помощью CSSTidy, а затем вытащить простой CSS из объекта csstidy. До сих пор так хорошо с тысячами установок (хотя я никогда не узнаю, сколько пользователей фактически использует функцию CSS моего плагина).

Возможно, я не заметил, что это мой первоначальный вопрос, но я искал самый простой и простой подход, а не самый технический, сложный или мощный подход. Я ценю как можно меньше изменять опыт WordPress. Вот почему я обратился к JetPack как самое близкое к «источнику». Я считаю JetPack почти каноническим, поскольку он разработан Automattic (разработчиками самого WordPress). Мой единственный … сожаление? … заключается в том, что CSSTidy был оставлен в 2007 году, поэтому я предполагаю, что в какой-то момент мне нужно будет найти другое решение.

 require_once( 'csstidy/class.csstidy.php' ); $csstidy = new csstidy(); $csstidy->set_cfg( 'remove_bslash', FALSE ); $csstidy->set_cfg( 'compress_colors', FALSE ); $csstidy->set_cfg( 'compress_font-weight', FALSE ); $csstidy->set_cfg( 'discard_invalid_properties', TRUE ); $csstidy->set_cfg( 'merge_selectors', FALSE ); $csstidy->set_cfg( 'remove_last_;', FALSE ); $csstidy->set_cfg( 'css_level', 'CSS3.0' ); $csstovalidateindiv = 'div {' . $csstovalidate . '}'; $csstovalidateindiv = preg_replace( '/\\\\([0-9a-fA-F]{4})/', '\\\\\\\\$1', $csstovalidateindiv ); $csstovalidateindiv = wp_kses_split( $csstovalidateindiv, array(), array() ); $csstidy->parse( $csstovalidateindiv ); $csstovalidateindiv = $csstidy->print->plain(); $csstovalidateindiv = str_replace( array( "\n", "\r", "\t" ), '', $csstovalidateindiv ); preg_match( "/^div\s*{(.*)}\s*$/", $csstovalidateindiv, $matches ); if ( !empty( $matches[1] ) ) $cssvalidated = $matches[1]; 

(код или его не было)

Jetpack действительно не дезинфицирует CSS, он просто очищает его, что имеет побочный эффект для удаления некоторых уязвимостей, но не для всех.

Злоумышленник все еще может использовать @import для импорта несаминированного CSS; expression() чтобы ввести XSS в более старые браузеры IE; @charset чтобы обмануть браузер в интерпретацию CSS как HTML, открыв возможности XSS; установить URL-адреса с произвольными протоколами для запуска SSRF-атак и т. д.

Если вы хотите полноценную санитацию, вам нужно сделать что-то вроде r2085-meta .

Вы должны запустить вашу санитацию против комплексных тестовых случаев, чтобы убедиться, что она очищает все.

Однако CSSTidy не заброшен; один из оригинальных авторов разветвил класс PHP , а команда Jetpack и другие сделали вклад, чтобы поддерживать его в разумных пределах. Если вам это не нравится, Caja – еще один вариант.

 wp_filter_nohtml_kses() 

похоже, не работает должным образом, потому что он ускользает от «символа», поэтому вы не можете писать никаких селекторов атрибутов. Похоже, что нет простого способа сделать это.

Ну, если вы хотите использовать пистолет на 50 мм, вы можете использовать wp_filter_nohtml_kses() , но могут быть лучшие способы.