Я разрабатываю веб-приложение, где пользователи могут ответ на записи в блоге. Это - проблема безопасности, потому что они могут отправить опасные данные, которые будут представлены другим пользователям (и выполнены JavaScript).
Они не могут отформатировать текст, который они отправляют. Нет "полужирный", никакие цвета, нет ничто. Просто простой текст. Я придумал этот regex для решения моей проблемы:
[^\\w\\s.?!()]
Так что-либо, что не является словесным символом (a-Z, A-Z, 0-9), не пробел, ". ", "?", "!", "(" или")" будет заменен пустой строкой. Чем каждый quatation метка будет заменена: """.
Я проверяю данные по фронтэнду, и я проверяю его на своем сервере.
Есть ли какой-либо способ, которым кто-то мог обойти это "решение"?
Я задаюсь вопросом, как StackOverflow делает эту вещь? Существует большое форматирование здесь, таким образом, они должны сделать хорошую работу с ним.
Если вы должны разрешить HTML-теги, определите белый список и сравните с ним ввод пользователя. Вы даже можете использовать для этого регулярное выражение.
<\ S [^>] *>
<(p | a href = "[^"] + " | img src = "[^"] + ") /?> | (a | p)>
Если вам нужен простой текст, не беспокойтесь о фильтрации специфических html-тегов. Вам нужен эквивалент htmlspecialchars() от PHP. Хороший способ использовать это - print htmlspecialchars($var,ENT_QUOTES);
Эта функция будет выполнять следующие кодировки:
'&' (ampersand) becomes '&'
'"' (double quote) becomes '"' when ENT_NOQUOTES is not set.
''' (single quote) becomes ''' only when ENT_QUOTES is set.
'<' (less than) becomes '<'
'>' (greater than) becomes '>'
Это решает проблему XSS на самом низком уровне, и вам не нужна какая-то сложная библиотека/регекс, которую вы не понимаете (и которая, вероятно, небезопасна, ведь сложность - враг безопасности).
Обязательно проверьте свой XSS-фильтр, запустив бесплатный xss-сканер.
Внешний интерфейс можно обойти с помощью Fiddler, например, добавив информацию о форме. Для внутреннего использования используйте кодировку html, например = & lt; a & gt;
Таким образом, текст будет отображаться как текст, а не как элементы html.
Я согласен с Томалаком, и просто хотел добавить несколько пунктов.
Я бы рекомендовал прочитать шпаргалку по предотвращению XSS, в которой подробно описаны лучшие методы предотвращения XSS-атак. По сути, то, что вам нужно фильтровать, зависит от контекста, в котором это будет использоваться.
Например, в таком сценарии:
<body>...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...</body>
Вам нужно сделать:
& --> &
< --> <
> --> >
" --> "
' --> ' ' is not recommended
/ --> / forward slash is included as it helps end an HTML entity
В то время как в случае примера href=""
вам нужно сделать urlescape:
"За исключением буквенно-цифровых символов, экранируйте все символы со значениями ASCII менее 256 с помощью
%HH
формата экранирования. Включение недоверенных данных в данные: URL не должно быть разрешено, поскольку нет хорошего способа отключить атаки с экранированием для предотвращения перехода из URL. Все атрибуты должны быть заключены в кавычки. Атрибуты без кавычек могут быть разбиты на множество символов, включая [пробел] % * + , - / ; < = > ^ и |. Обратите внимание, что кодировка сущностей бесполезна в этом контексте."
Хотя в цитируемой статье приводится полный вердикт, надеюсь, в этом ответе достаточно информации, чтобы вы могли начать.
Сначала удалите все неправильные последовательности символов, например слишком длинный UTF-8, недопустимый Unicode.
Вам нужно будет более четко указать, удаляются ли <и> или превращаются в сущности.
Вам также потребуется разделить или закодировать двойные и одинарные кавычки, иначе злоумышленник может добавить внутреннее событие, которого вы не ожидали, например
Если вы действительно хотите разрешить какое-то подмножество HTML, будьте осторожны, пытаясь проанализировать его с помощью регулярных выражений, особенно те, которые вы придумали сами, например браузеры будут отображать хитрые теги
просто отлично, если регулярное выражение может им не соответствовать. Ознакомьтесь с ранее упомянутым Anti-Samy .
Если вы разрешаете HTML-теги с атрибутами href
или src
, убедитесь, что они указывают на схемы http (s):
, а не на ] javascript:
один.