Очистить введенный пользователем 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; 
}
Author: radiok, 2012-06-01

5 answers

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

 3
Author: fuxia, 2012-06-01 19:31:34

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

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

Я скачал 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];

(код или этого не произошло)

 2
Author: radiok, 2014-10-15 16:21:40

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

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

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

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

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

 1
Author: Ian Dunn, 2015-11-30 19:47:47
wp_filter_nohtml_kses()

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

 0
Author: Nico, 2015-04-22 21:30:26

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

 -1
Author: Chip Bennett, 2012-06-01 18:15:58