Предотвращение атак XSS - PullRequest
5 голосов
/ 06 мая 2010

Я занимаюсь разработкой веб-приложения, в котором пользователи могут отвечать на записи в блоге. Это проблема безопасности, потому что они могут отправлять опасные данные, которые будут предоставлены другим пользователям (и выполнены javascript).

Они не могут отформатировать отправляемый текст. Нет "смелых", нет цветов, нет ничего. Просто простой текст. Я придумал это регулярное выражение, чтобы решить мою проблему:

[^\\w\\s.?!()]

Таким образом, все, что не является символом слова (aZ, AZ, 0-9), не является пробелом, ".", "?", "!", "(" Или ")" будет заменено пустым строка. После этого каждая отметка будет заменена на «& quot».

Я проверяю данные на внешнем интерфейсе и проверяю их на своем сервере.

Можно ли как-нибудь обойти это "решение"?

Мне интересно, как StackOverflow делает это? Здесь много форматирования, поэтому они должны хорошо с ним работать.

Ответы [ 6 ]

3 голосов
/ 06 мая 2010

Если вам нужен простой текст , не беспокойтесь о фильтрации определенных HTML-тегов . Вы хотите эквивалентный PHP htmlspecialchars () . Хороший способ использовать это 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 '&lt;'
'>' (greater than) becomes '&gt;'

Это решение проблемы XSS на самом низком уровне, и вам не нужны сложные библиотеки / регулярные выражения, которые вы не понимаете (и, вероятно, небезопасны после того, как вся сложность является врагом безопасности).

Обязательно ПРОВЕРЬТЕ СВОЙ XSS-ФИЛЬТР , запустив бесплатный сканер xss .

2 голосов
/ 24 мая 2010

Я бы порекомендовал прочитать Шпаргалку по профилактике XSS , в которой подробно описан передовой опыт по предотвращению атак XSS. По сути, то, что вам нужно отфильтровать, зависит от контекста, в котором он будет использоваться.

Например, в сценарии такого типа:

<body>...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...</body>

Вам нужно сделать:

& --> &amp;
< --> &lt;
> --> &gt;
" --> &quot;
' --> &#x27;     &apos; is not recommended
/ --> &#x2F;     forward slash is included as it helps end an HTML entity

В то время как в случае href="" вам нужно сделать urlescape:

"За исключением буквенно-цифровых символов, экранируйте все символы со значениями ASCII, меньшими 256, в формате экранирования %HH. Включая ненадежные данные в данные: URL-адреса не должны быть разрешены, поскольку нет хорошего способа отключить атаки с экранированием для предотвращения переключение из URL. Все атрибуты должны быть заключены в кавычки. Не заключенные в кавычки атрибуты могут быть разбиты множеством символов, включая [пробел]% * +, - /; <=> ^ и |. Обратите внимание, что в этом контексте кодирование сущностей бесполезно. «

Хотя приведенная статья дает полный вердикт, надеюсь, в этом ответе достаточно информации, чтобы вы могли начать.

2 голосов
/ 06 мая 2010

Я согласен с Томалаком и просто хотел добавить несколько пунктов.

  1. Не разрешать теги HTML. Идея состоит в том, чтобы обрабатывать ввод пользователя как текст, а также экранирующие html-символы перед их отображением. Для этой цели используйте проект OWASP ESAPI . Эта страница объясняет различные возможные кодировки , о которых вам следует знать.
  2. Если вам нужно разрешить теги HTML, используйте библиотеку, чтобы выполнить фильтрацию за вас. НЕ пишите свои собственные регулярные выражения; их трудно понять правильно. Используйте проект OWASP Anti-Samy - он был разработан специально для этого варианта использования.
1 голос
/ 06 мая 2010
  1. Не разрешать теги HTML.
  2. Не выводить что-либо, введенное пользователем, без экранирования HTML-кода. Это гораздо более важный момент! Сделайте это, и у вас никогда не будет проблем с XSS.
  3. Предоставьте функцию предварительного просмотра, чтобы пользователи могли видеть, как она будет выглядеть перед публикацией.

Если вам необходимо разрешить теги HTML, определите белый список и проверьте введенные пользователем данные. Вы даже можете использовать регулярные выражения для этого.

Допустим, вы разрешаете <p>, <a href="..."> и <img src="...">:

  1. найти в пользовательской строке все, что соответствует <\S[^>]*>
  2. для каждого матча, сравните его с <(p|a href="[^"]+"|img src="[^"]+")/?>|</(a|p)>
  3. если оно не соответствует этому строгому регулярному выражению, отбросьте его.
  4. См. Пункт № 2 выше.
  5. Старайтесь сознательно сломать вашу систему. Попросите других попытаться сломать вашу систему.
0 голосов
/ 18 июня 2010

Сначала удалите все последовательности плохих символов, например, слишком длинный UTF-8, недопустимый Unicode.

Вам нужно будет более четко указать, будут ли <и> разделены или превращены в объекты.

Вам также понадобится удалить или закодировать двойные и одинарные кавычки, в противном случае злоумышленник может добавить внутреннее событие, если вы этого не ожидали, например, ' onSomething = payload; a = ''>

Если вы действительно хотите разрешить некоторое подмножество HTML, будьте осторожны, пытаясь проанализировать его с помощью регулярных выражений, особенно тех, которые вы придумали сами, например. браузеры будут отображать хитрые теги <a b=">"onMouseOver=alert(42)> просто отлично, если регулярное выражение может не соответствовать. Проверьте ранее упомянутый Anti-Samy .

Если вы разрешаете теги HTML, которые имеют атрибуты href или src, убедитесь, что они указывают на схемы http(s):, а не javascript:.

0 голосов
/ 06 мая 2010

Внешний интерфейс можно обойти, например, с помощью Fiddler, добавив информацию о форме. На бэкэнде используйте html-кодировку, например = & lt; a & gt;

Таким образом, текст будет отображаться как текст, а не как элементы html.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...