Санитизация PHP XSS

Вопросы:

Каковы наилучшие функции safe1(), safe2(), safe3() и safe4(), чтобы избежать XSS для страниц с кодировкой UTF8? Это также безопасно во всех браузерах (в частности, в IE6)?

<body><?php echo safe1($xss)?></body>

<body id="<?php echo safe2($xss)?>"></body>

<script type="text/javascript">
  var a = "<?php echo safe3($xss)?>";
</script>

<style type="text/css">
  .myclass {width:<?php echo safe4($xss)?>}
</style>

.

Многие говорят, что лучшее, что можно сделать, это:

// safe1 & safe2
$s = htmlentities($s, ENT_QUOTES, "UTF-8");

// But how would you compare the above to:
//    https://github.com/shadowhand/purifier
// OR http://kohanaframework.org/3.0/guide/api/Security#xss_clean
// OR is there an even better if not perfect solution?

.

// safe3
$s = mb_convert_encoding($s, "UTF-8", "UTF-8");
$s = htmlentities($s, ENT_QUOTES, "UTF-8");

// How would you compare this to using using mysql_real_escape_string($s)?
// (Yes, I know this is a DB function)
// Some other people also recommend calling json_encode() before passing to htmlentities
// What's the best solution?

.

Есть чертовски много сообщений о PHP и XSS. Большинство просто говорят «используйте HTMLPurifier» или «используйте htmlspecialchars» или ошибаются. Другие говорят, что используйте OWASP, но это ЧРЕЗВЫЧАЙНО медленно. Ниже перечислены некоторые из хороших постов, с которыми я столкнулся:

Выполните htmlspecialchars и mysql_real_escape_string защитить мой PHP-код от инъекций?

Предупреждения XSS Me - реальные проблемы XSS?

CodeIgniter - зачем использовать xss_clean


person user324289    schedule 13.05.2011    source источник
comment
Неэкранированные символы — не единственное, о чем вам следует беспокоиться. В вашем var a = "<?php echo safe3($xss)?>"; вам также нужно удалить все символы новой строки.   -  person zerkms    schedule 13.05.2011


Ответы (2)


safe2() явно htmlspecialchars()

Вместо safe1() вам действительно следует использовать HTMLPurifier для очистки целых блоков HTML. Он удаляет нежелательные атрибуты, теги и, в частности, все, что связано с javascript. Да, это медленно, но оно охватывает все небольшие пограничные случаи (даже для более старых версий IE), которые позволяют безопасно повторно использовать пользовательские фрагменты HTML. Но проверьте http://htmlpurifier.org/comparison, чтобы найти альтернативы. -- Если вы действительно хотите отображать там только необработанный пользовательский текст (без фильтрованного html), то htmlspecialchars(strip_tags($src)) на самом деле будет работать нормально .

safe3() кричит регулярное выражение. Здесь вы действительно можете применить белый список только к тому, что вам действительно нужно:

var a = "<?php echo preg_replace('/[^-\w\d .,]/', "", $xss)?>";

Конечно, вы можете использовать здесь json_encode, чтобы получить корректный синтаксис и переменную JS. Но тогда вы только что отложили возможность использования этой строки в своем JS-коде, где вам затем придется присматривать за ней.


Это также безопасно во всех браузерах (в частности, в IE6)?

Если вы укажете кодировку явно, то IE не будет делать свою ужасную магию обнаружения содержимого, поэтому эксплойты UTF7 можно игнорировать.

person mario    schedule 13.05.2011
comment
Для safe2: почему htmlspecialchars($s, ENT_QUOTES, UTF-8) лучше, чем htmlentities($s, ENT_QUOTES, UTF-8)? Являются ли они эквивалентными, но первый просто быстрее? Я слышал, что последний лучше, поскольку он защищает от XSS-атак с иностранными символами. Можете ли вы также расширить то, что вы подразумеваете под «но тогда вы только что задержали возможность использования этой строки в своем JS-коде», приведя мне пример? Спасибо! - person user324289; 13.05.2011
comment
Нет, в основном они одинаковые. htmlentities также кодирует некоторые другие символы. Но поскольку притворный XHTML все еще широко распространен, вам следует предпочесть только htmlspecialchars, который использует только escape-последовательности XML, а не потенциально недопустимые объекты HTML. Иностранные символы не так уж важны для эксплойтов XSS. Более серьезными являются атрибуты без кавычек, потому что там не только " и ' проблематичны, но также @ ! % и другие могут стать терминаторами. - person mario; 13.05.2011
comment
Что касается JS, если ваша переменная содержит var a = "text'><script>...";, вам нужно позаботиться о том, чтобы не выводить ее напрямую. - person mario; 13.05.2011
comment
Что касается вашего предложения использовать HTMLPurifier для safe1(): можете ли вы указать мне пример, где htmlentities() НЕ работает? На самом деле меня не волнует, могут ли пользователи изменять макет веб-сайта или строго соблюдать XHTML и т. д. и т. д. — только то, что произвольный Javascript не может быть запущен. В результате HTMLPurifier кажется мне слишком медленным. - person user324289; 13.05.2011
comment
Кроме того, еще один вопрос: какая функция подойдет для safe4 выше? (Я отредактировал исходный пост) - person user324289; 13.05.2011
comment
HTMLPurifier содержит очиститель CSS, не уверен, что он подходит здесь. (Могут быть отдельные классы.) Я бы снова использовал ограничительное регулярное выражение, но это не будет иметь дело с эксплойтами CSS IE, если вы не запретите скобки. - person mario; 13.05.2011
comment
Спасибо, Марио - не уверен, что вы также видели мой предыдущий вопрос выше о примере, где htmlentities не работает... спасибо - person user324289; 13.05.2011
comment
Нет, один htmlentities работает нормально — если вы используете его в текстовой области или всегда только в пределах атрибутов в кавычках. - person mario; 13.05.2011
comment
Почему вы советуете регулярное выражение для safe3? Разве json_encode((string)$stuff); не лучше? Regex все равно не будет выполнять преобразование сущностей... - person Christian; 24.10.2011
comment
Кроме того, для сейфа4; это зависит от контекста. В общем, регулярное выражение против AZaz09 "'# должно отлично работать (учитывайте, что ; и : здесь самые опасные символы). Также обратите внимание, что для некоторых имен шрифтов требуются странные символы. Но если вы делаете это для простых ключевых слов CSS (solid или red) или измерений (2px или 5em 9px), этого должно быть достаточно. - person Christian; 24.10.2011

http://php.net/htmlentities обратите внимание на раздел о необязательном третьем параметре, который принимает кодировку символов. Вы должны использовать это вместо mv_convert_encoding. Пока сам файл php сохраняется с кодировкой utf8, она должна работать.

htmlentities($s, ENT_COMPAT, 'UTF-8');

Что касается вставки переменной непосредственно в javascript, вы можете вместо этого поместить содержимое в скрытый элемент html где-то еще на странице и вытащить содержимое из dom, когда вам это нужно.

Упомянутые вами очистители используются, когда вы хотите фактически отображать html, отправленный пользователем (например, разрешить браузеру фактически отображать). Использование htmlentities будет кодировать все так, что символы будут отображаться в пользовательском интерфейсе, но ни один из фактического кода не будет интерпретирован браузером. Что вы собираетесь делать?

person wewals    schedule 13.05.2011