Я пытаюсь дезинфицировать и XSS-защищать некоторые HTML-данные от клиента. Я использую Python 2.6 с красивым супом. Я анализирую ввод, разделяю все теги и атрибуты не в белом списке и преобразую дерево обратно в строку.
Однако...
>>> 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 documentation упоминает только разбор сущностей, а не их создание. Конечно, я могу запустить замену на все узлы NavigableString, но, поскольку я могу что-то пропустить, я бы предпочел, чтобы какой-то проверенный и проверенный код выполнил эту работу.
Почему по умолчанию не исчезает Beautiful Soup < (и другие магические символы), и как это сделать?
N.B. Я также посмотрел на lxml.html.clean. Кажется, он работает на основе черного списка, а не белого списка, поэтому для меня это не очень безопасно. Теги могут быть в белом списке, но атрибуты не могут, и это позволяет слишком много атрибутов для моего вкуса (например, tabindex). Кроме того, он дает AssertionError на входе <SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>. Нехорошо.
Предложения по другим способам очистки HTML также приветствуются. Я едва ли единственный человек в мире, пытающийся это сделать, но, похоже, нет стандартного решения.