Является ли это дезинфицирующее средство уязвимым для XSS?

Чтобы иметь простой и безопасный редактор для текстовых полей приложения django, у меня есть этот фрагмент для очистки входного HTML в коде django:

from bs4 import BeautifulSoup

def sanitize_html(value):
  tag_whitelist = ['img','b','strong','blockquote', 'a']
  attr_whitelist = ['src', 'alt', 'width', 'height', 'href','class']
  soup = BeautifulSoup(value)
  for tag in soup.find_all():
      if tag.name.lower() in tag_whitelist:
          tag.attrs = { name: value for name, value in tag.attrs.items() 
              if name.lower() in attr_whitelist }
      else:
          tag.unwrap()   

  # scripts can be executed from comments in some cases
  try:
    comments = soup.find_all(text=lambda text:isinstance(text, Comment))
    for comment in comments:
      comment.extract()
  except:
    pass
  return unicode(soup)

Я также занесен в черный список javascript в полях модели, используя этот метод:

BADLIST = ['javascript']

def no_js (text):
    if any(e in text for e in BADLIST):
        raise ValidationError("Your text contains bad words!")
    else:
        return True

С другой стороны, в шаблоне мне нужно использовать {{text| safe}} разрешить отображение здоровых HTML-тегов.

Так что мне интересно с этими ограничениями, является ли ввод по-прежнему уязвимым для XSS? И если так, как это исправить?

2 ответа

Это, вероятно, небезопасно. По умолчанию BeautifulSoup использует синтаксический анализатор lxml.html, и, вероятно, можно использовать различия между этим и синтаксическими анализаторами браузеров (все в соответствии со спецификацией HTML), чтобы перебирать строки, которые браузер будет видеть как элемент, а ваш код - нет. Использование BeautifulSoup с html5lib уменьшит эту возможную поверхность атаки, так как тогда у вас будет парсер, идентичный браузерам.

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

Тем не менее, в целом, я бы согласился с ответом Втуера о том, что использование сторонней библиотеки, вероятно, более безопасно.

На первый взгляд код выглядит хорошо, но проверка на наличие уязвимостей безопасности не является чем-то, что не следует воспринимать легкомысленно, и для проверки самостоятельно требуется немного времени.

Например, проверьте, если предоставить строку, такую ​​как <script>alert('hello')</script> выполнен. Помимо этого упрощенного теста, есть много вещей, которые нужно проверить. Есть много документации по этому вопросу.

Кроме того, как упоминалось в моем комментарии, я настоятельно рекомендую вам использовать установленную библиотеку для очистки входных данных. Такая библиотека является отбеливателем:

Bleach - это библиотека HTML для очистки и преобразования текстовых ссылок на основе белого списка. Он предназначен для ввода ненадежного пользовательского ввода с некоторым HTML.

Поскольку Bleach использует html5lib для разбора фрагментов документов так же, как это делают браузеры, он чрезвычайно устойчив к неизвестным атакам, в гораздо большей степени, чем дезинфицирующие средства на основе регулярных выражений.

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

Пример использования:

import bleach
mystring = bleach.clean(form.cleaned_data['mystring'], 
                        tags=ALLOWED_TAGS,
                        attributes=ALLOWED_ATTRIBUTES, 
                        styles=ALLOWED_STYLES, 
                        strip=False, strip_comments=True)
Другие вопросы по тегам