Защита от XSS

Доброго времени суток. Написав систему комментариев, я всерьёз задумался о защите от XSS. Немного погуглив на эту тему мои глаза приняли такой вид «О_О». Что есть на данный момент:

1. Пишу на javascript, используя nodeJS
2. Текст полученный от браузера проходит следующие метаморфозы:

а) формируется DOM-древо (jsdom)
б) подключается jQuery
в) пробегаю $( '*' ) по каждому тегу и провожу его сквозь парсер. Повторяю пробеги до тех пор пока не искоренятся все проблемы, либо число пробегов превысит разумные нормы (в этом случае выкидываю ошибку).

Парсер тега работает примерно по такому принципу:

1) если тег не входит в список доступных пользователю тегов (i, b, s, strong, em, ul, ol, li, p, pre, span, br, img, a), заменяю его SPAN-тегом
2) пробегаюсь по всем атрибутам тега, удаляя все не доступные (оставил только width, height, src для image и href для a).
3) в годных атрибутах прохожусь регуляркой по значению ( .replace( /[^\d]+/, '' ) для width, height ).

Остаются такие аттрибуты как src и href. Я думал в них достаточно срезать начальную 'javasript:', но почитав эту статью, я понял, что нужно как то очень хитро подойти к этому вопросу.

Собственно вопросы:

1. Какие у описанной выше схемы есть изъяны? Что стоило бы добавить?
2. Каким образом фильтровать атрибуты вроде href и src

Интересует именно HTML, а не BB коды или другая разметка. + планирую эту наработку использовать не только в системе комментариев.
  • Вопрос задан
  • 8621 просмотр
Пригласить эксперта
Ответы на вопрос 5
Если по «правильному», то защита от XSS сводиться к элементарной проверке входящих данных на сервере. Желательно использовать белый список.
Ответ написан
Комментировать
AlexanderPHP
@AlexanderPHP
Только на javascript фильтровать нельзя, т.к. firebug`ом можно обойти.

Вообще, на стороне PHP есть хороший способ:

$find = array ('/data:/i', '/about:/i', '/vbscript:/i', '/onclick/i', '/onload/i', '/onunload/i', '/onabort/i', '/onerror/i', '/onblur/i', '/onchange/i', '/onfocus/i', '/onreset/i', '/onsubmit/i', '/ondblclick/i', '/onkeydown/i', '/onkeypress/i', '/onkeyup/i', '/onmousedown/i', '/onmouseup/i', '/onmouseover/i', '/onmouseout/i', '/onselect/i', '/javascript/i', '/javascript/i' );
$replace = array ("data:", "about:", "vbscript<b></b>:", "onclick", "onload", "onunload", "onabort", "onerror", "onblur", "onchange", "onfocus", "onreset", "onsubmit", "ondblclick", "onkeydown", "onkeypress", "onkeyup", "onmousedown", "onmouseup", "onmouseover", "onmouseout", "onselect", "javascript" );

$txt = preg_replace( $find, $replace, $txt );
$txt = preg_replace( "#<iframe#i", "<iframe", $txt );
$txt = preg_replace( "#<script#i", "<script", $txt );
$txt = str_replace( "<?", "<?", $txt );
$txt = str_replace( "?>", "?>", $txt );
Ответ написан
NekitoSP
@NekitoSP
Прочитав статью с того сайта вы похоже до сих пор немного не разобрались как действовать. Моя идея фильтрации данных на стороне сервера такова:
1) для начала декодируем все данные, заменяя все подобные вещи

на нормальные символы, с которыми далее будем работать
3) далее при нахождении границ тега, будь то ... мы удаляем все непечатаемые(?) символы (в т.ч. и переносы строк) в параметрах тега а так же между открывающим и закрывающим. Проблема будет лишь с \0, но если работать с данными как с массивом символов, а не как со строкой — то наверное удастся их обойти.
3) затем работа с параметрами тега, соответственно убираем всё, что не является нормальным URL-адресом, и по возможности, избавляемся от тега, если вдруг URL «небезопасный» (безопасными URL я думаю стоит считать лишь те, которые начинаются с http:// или https://, ну и на крайний случай — ... в общем вам решать)
Ответ написан
@Xrizolin
https://www.owasp.org/index.php/XSS_(Cross_Site_Sc...
И на всякий случай после проверки исходников прогнать поверх сканером.
Например https://metascan.ru
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы