Безопасная функция очистки XSS (регулярно обновляется)
Я уже несколько дней охочусь за сетью, пытаясь понять это, но получаю противоречивые ответы.
Есть ли библиотека, класс или функция для PHP, которая надежно защищает/кодирует строку против XSS? Он должен регулярно обновляться, чтобы противостоять новым атакам.
У меня есть несколько вариантов использования:
Случай использования 1) У меня есть текстовое поле, например, для имени или фамилии
- Пользователь вводит текст в поле и отправляет форму
- Прежде чем это будет сохранено в базе данных, я хочу a) обрезать любые пробелы спереди и
конец строки и b) удалите все теги HTML из ввода. Это текстовое поле имени, у них не должно быть никакого HTML-кода.
- Затем я сохраню это в базе данных с подготовленными инструкциями PDO.
Я думаю, что могу просто сделать trim()
и strip_tags()
, затем использовать Sanitize Filter или RegEx со списком символов, Им действительно нужны персонажи! а также? или <
>
в их имени, на самом деле.
Случай использования 2) При выводе содержимого из ранее сохраненной записи базы данных (или из ранее представленной формы) в представление /HTML я хочу полностью очистить ее для XSS. NB: Возможно, он прошел или не прошел этап фильтрации в прецеденте 1, поскольку он может быть другим типом ввода, поэтому не предполагайте, что никакая дезинфекция не была выполнена.
Изначально я, хотя HTMLPurifier выполнял бы эту работу, но, как мне кажется, это не то, что мне нужно, когда Я поставил вопрос на их поддержку
Вот пример лакмусовой бумажки: если пользователь отправляет <b>foo</b>
, должен ли он отображаться как <b>foo</b>
или foo? Если первый, вам не нужен очиститель HTML.
Поэтому я предпочел бы, чтобы он появился как <b>foo</b>
, потому что я не хочу, чтобы какой-либо HTML отображался для простого текстового поля или любого выполняемого JavaScript.
Итак, я охотился за функцией, которая сделает все это для меня. Я наткнулся на метод xss_clean, используемый Kohana 3.0, который, как я предполагаю, работает, но только в том случае, если вы хотите сохранить HTML. Теперь он устарел от Kohana 3.1, поскольку они заменили его на HTMLPurifier. Поэтому я предполагаю, что вы должны сделать HTML::chars()
вместо этого, но только этот код:
public static function chars($value, $double_encode = TRUE)
{
return htmlspecialchars( (string) $value, ENT_QUOTES, Kohana::$charset, $double_encode);
}
Теперь, по-видимому, вы должны использовать htmlentities вместо упомянутого в довольно несколько мест в переполнении стека, поскольку он более безопасен, чем htmlspecialchars.
- Итак, как использовать htmlentities
правильно?
- Это все, что мне нужно?
- Как защитить от шестнадцатеричных, десятичных и базовых 64 кодированных значений, отправленных из перечисленных атак здесь?
Теперь я вижу, что третий параметр для метода htmlentities - это кодировка, которая будет использоваться при преобразовании. Теперь мой сайт /db находится в UTF-8, но, возможно, данные, представленные в форме, не были закодированы в кодировке UTF-8, возможно, они отправили ASCII или HEX, поэтому, возможно, мне нужно сначала преобразовать ее в UTF-8? Это означало бы какой-то код вроде:
$encoding = mb_detect_encoding($input);
$input = mb_convert_encoding($input, 'UTF-8', $encoding);
$input = htmlentities($input, ENT_QUOTES, 'UTF-8');
Да или нет? Тогда я все еще не уверен, как защитить от шестнадцатеричных, десятичных и base64 возможных входов XSS...
Если есть библиотека или PHP с открытым исходным кодом, которая может правильно защитить XSS, мне было бы интересно посмотреть, как они это делают в коде.
Любая помощь очень ценится, извините за длинный пост!
Ответы
Ответ 1
Чтобы ответить на смелый вопрос: Да, есть. Он называется htmlspecialchars
.
Он должен регулярно обновляться до противостоять новым атакам.
Правильный способ предотвращения атак XSS - это не противодействие определенным атакам, фильтрация/дезинфекция данных, а правильная кодировка, везде.
htmlspecialchars
(или htmlentities
) в сочетании с разумным решением кодирования символов (т.е. UTF-8
), и явная спецификация кодирования символов достаточна для предотвращения всех атак XSS. К счастью, вызов htmlspecialchars
без явного кодирования (тогда он предполагает, что ISO-8859-1) тоже будет работать для UTF-8. Если вы хотите сделать это явным, создайте вспомогательную функцию:
// Don't forget to specify UTF-8 as the document encoding
function htmlEncode($s) {
return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}
О, и для обращения к форме беспокоиться: не пытайтесь обнаружить кодировки, они связаны с ошибкой. Вместо этого выдать форму в UTF-8. Затем каждый браузер отправляет пользовательские входы в UTF-8.
Устранение особых проблем:
(...), вы должны использовать htmlentities, потому что htmlspecialchars уязвим для эксплойта UTF-7 XSS.
Эксплуатация UTF-7 XSS может применяться только в том случае, если браузер считает, что документ закодирован в UTF-7. Указание кодировки документа как UTF-8 (в заголовке HTTP/метатеге сразу после <head>
) предотвращает это.
Также, если я не обнаруживаю кодировку, что остановить загрузку злоумышленника html файл, а затем изменить его на UTF-7 или некоторая другая кодировка, то отправив запрос POST на мой сервера с измененной страницы html?
Этот сценарий атаки излишне сложный. Злоумышленник может просто создать строку UTF-7, не нужно ничего загружать.
Если вы принимаете POST злоумышленника (т.е. вы принимаете анонимный публичный пользовательский ввод), ваш сервер будет просто интерпретировать строку UTF-7 как странный UTF-8. Это не проблема, сообщение злоумышленника просто покажется искаженным. Злоумышленник мог добиться такого же эффекта (отправка странного текста), отправив "grfnlk" сто раз.
Если мой метод работает только для UTF-8, то атака XSS пройдет, не?
Нет, не будет. Кодировки не являются волшебными. Кодировка - это всего лишь способ интерпретировать двоичную строку. Например, строка "ö" кодируется как (шестнадцатеричная) 2B 41 50 59
в UTF-7 (и C3 B6
в UTF-8). Декодирование 2B 41 50 59
, поскольку UTF-8 дает "+ APY" - безвредные, казалось бы, случайные символы.
Также как htmlentities защищают от HEX или других атак XSS?
Шестнадцатеричные данные будут выводиться именно так. Злоумышленник, отправляющий "3C" , отправит сообщение "3C" . "3C" может только стать <
, если вы активно пытаетесь интерпретировать шестнадцатеричные входы в противном случае, например, активно сопоставляете их в кодовые точки Юникода, а затем выводите их. Это означает, что если вы принимаете данные во что-то, но просто UTF-8 (например, UTF-8 с кодировкой base32), вам сначала придется распаковать кодировку, а затем используйте htmlspecialchars
, прежде чем включать ее между HTML-кодом.
Ответ 2
Многие инженеры по безопасности рекомендуют использовать эту библиотеку для этой конкретной проблемы:
https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API