Я пытаюсь очистить и XSS-защиту некоторого ввода HTML от клиента. Я использую Python 2.6 с Beautiful Soup. Я анализирую входные данные, удаляю все теги и атрибуты, не входящие в белый список, и преобразую дерево обратно в строку.
Однако ...
>>> unicode(BeautifulSoup('text < text'))
u'text < text'
Это не похоже на действительный HTML для меня. И с моим стриптизером, он открывает путь ко всем видам гадости:
>>> print BeautifulSoup('<<script></script>script>alert("xss")<<script></script>script>').prettify()
<
<script>
</script>
script>alert("xss")<
<script>
</script>
script>
Пары <script></script>
будут удалены, и останется не только атака XSS, но даже действительный HTML.
Очевидное решение состоит в замене всех символов <
на <
, которые после анализа не принадлежат тегу (и аналогичны >&'"
). Но в документации Beautiful Soup упоминается только разбор сущностей, а не их создание. Конечно, я могу выполнить замену на всех NavigableString
узлах, но, поскольку я могу что-то пропустить, я бы предпочел, чтобы какой-то проверенный и протестированный код выполнил эту работу.
Почему Beautiful Soup по умолчанию не убегает <
(и другие магические персонажи), и как мне это сделать?
N.B. Я также посмотрел на lxml.html.clean
. Кажется, он работает на основе черного списка, а не белого списка, поэтому он не кажется мне безопасным. Теги могут быть в белом списке, но атрибуты не могут, и это допускает слишком много атрибутов на мой вкус (например, tabindex
). Кроме того, он дает AssertionError
на входе <SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>
. Не хорошо.
Предложения по другим способам очистки HTML также приветствуются. Я едва ли единственный человек в мире, пытающийся это сделать, но, похоже, стандартного решения не существует.