Как лучше всего очистить ввод пользователя для веб-приложения на Python? Есть ли одна функция для удаления символов HTML и любых других необходимых комбинаций символов для предотвращения атаки XSS или SQL-инъекции?
... if database API is used properly there is no chance of SQL injection. Под «правильно» вы имеете в виду использование параметризованных запросов? Это покрывает вас на 100%?
@buffer, я знаю, что ваш комментарий старый, но если вы хотите, чтобы другие люди, кроме OP, видели ваши комментарии, вы должны вызвать их с помощью символа \ @.






Если вы используете фреймворк, например джанго, фреймворк может легко сделать это за вас с помощью стандартных фильтров. На самом деле, я почти уверен, что django сделает это автоматически, если вы не скажете ему этого не делать.
В противном случае я бы рекомендовал использовать какую-то проверку регулярных выражений перед принятием входных данных из форм. Я не думаю, что есть серебряная пуля для вашей проблемы, но с помощью модуля re вы сможете сконструировать то, что вам нужно.
Сам Джефф Этвуд описал, как StackOverflow.com дезинфицирует вводимые пользователем данные (в терминах, не зависящих от языка) в блоге Stack Overflow: https://blog.stackoverflow.com/2008/06/safe-html-and-xss/
Однако, как указывает Джастин, если вы используете шаблоны Django или что-то подобное, они, вероятно, все равно дезинфицируют ваш HTML-вывод.
SQL-инъекция также не должна вызывать беспокойства. Все библиотеки баз данных Python (MySQLdb, cx_Oracle и т. д.) Всегда очищают переданные вами параметры. Эти библиотеки используются всеми объектно-реляционными преобразователями Python (такими как модели Django), поэтому вам также не нужно беспокоиться о санитарии.
Вот фрагмент, который удалит все теги, отсутствующие в белом списке, и все атрибуты тегов, не включенные в белый список атрибутов (поэтому вы не можете использовать onclick).
Это модифицированная версия http://www.djangosnippets.org/snippets/205/ с регулярным выражением в значениях атрибутов, чтобы люди не могли использовать href = "javascript:...", и другие случаи, описанные в http://ha.ckers.org/xss.html.
(например, <a href = "ja	vascript:alert('hi')"> или <a href = "ja vascript:alert('hi')"> и т. д.)
Как видите, он использует (потрясающую) библиотеку BeautifulSoup.
import re
from urlparse import urljoin
from BeautifulSoup import BeautifulSoup, Comment
def sanitizeHtml(value, base_url=None):
rjs = r'[\s]*(&#x.{1,7})?'.join(list('javascript:'))
rvb = r'[\s]*(&#x.{1,7})?'.join(list('vbscript:'))
re_scripts = re.compile('(%s)|(%s)' % (rjs, rvb), re.IGNORECASE)
validTags = 'p i strong b u a h1 h2 h3 pre br img'.split()
validAttrs = 'href src width height'.split()
urlAttrs = 'href src'.split() # Attributes which should have a URL
soup = BeautifulSoup(value)
for comment in soup.findAll(text=lambda text: isinstance(text, Comment)):
# Get rid of comments
comment.extract()
for tag in soup.findAll(True):
if tag.name not in validTags:
tag.hidden = True
attrs = tag.attrs
tag.attrs = []
for attr, val in attrs:
if attr in validAttrs:
val = re_scripts.sub('', val) # Remove scripts (vbs & js)
if attr in urlAttrs:
val = urljoin(base_url, val) # Calculate the absolute url
tag.attrs.append((attr, val))
return soup.renderContents().decode('utf8')
Как было сказано на других плакатах, почти все библиотеки Python db заботятся о SQL-инъекции, так что это должно в значительной степени покрыть вас.
Я поддержал это, но теперь я не уверен. Я не думаю, что это защищает пользователей IE от атак src = "vbscript: msgbox ('xss')".
Вы можете легко добавить это с помощью другого регулярного выражения для vbscript: например, для javascript:
@tghw, Пример vbscript вот почему решения из белого списка обычно предпочтительнее решений из черного списка. Как узнать наверняка, что все необходимое занесено в черный список? С черным списком на следующей неделе может выйти новый браузер, который будет уязвим, поскольку поддерживает новый тип тега скрипта.
@gnibbler Я согласен, и по большей части это решение для белых списков, но для href и src действительно нет способа легко добавить в белый список. Единственный вариант, который я могу придумать, - это сделать все URL-адреса абсолютными, передав URL-адрес страницы, а затем просматривая каждую ссылку и изображение и вычисляя абсолютный URL-адрес на основе URL-адреса страницы. Чем больше я об этом думаю, тем легче это кажется. Добавлю выше.
Как правило, дезинфицировать HTML очень сложно, существует множество векторов: nick.cleaton.net/xssrant.html
Спасибо большое. Я включил этот метод в сообщение в блоге, посвященное настройке безопасного ввода данных пользователем с помощью Django: birdhouse.org/blog/2010/05/12/secure-user-input-with-django
Это потрясающе. Использование его для очистки комментариев в моем маленьком блоге. :) -- Спасибо.
Я больше не занимаюсь веб-разработкой, но когда занялся, то сделал что-то вроде этого:
Когда не предполагается никакого синтаксического анализа, я обычно просто избегаю данных, чтобы не мешать базе данных, когда я их сохраняю, и избегаю всего, что я читаю из базы данных, чтобы не мешать html, когда я показываю его (cgi.escape () в питон).
Скорее всего, если кто-то попытается ввести символы html или что-то в этом роде, они действительно захотят, чтобы это отображалось как текст. Если они этого не сделали, хорошо :)
Короче говоря, всегда избегайте того, что может повлиять на текущую цель данных.
Когда мне нужен был некоторый синтаксический анализ (разметка или что-то еще), я обычно пытался сохранить этот язык в непересекающемся наборе с html, чтобы я мог просто сохранить его с соответствующим экранированием (после проверки на синтаксические ошибки) и проанализировать его в html при отображении без нужно беспокоиться о том, что данные, которые пользователь поместил туда, мешают вашему html.
См. Также Экранирование HTML
Лучший способ предотвратить XSS - это не пытаться фильтровать все, а просто выполнять кодирование HTML Entity. Например, автоматический поворот
SQL-инъекция, вопреки другому мнению, все еще возможна, если вы просто создаете строку запроса. Например, если вы просто объединяете входящий параметр в строку запроса, у вас будет SQL Injection. Лучший способ защититься от этого - не фильтровать, а строго использовать параметризованные запросы и НИКОГДА не объединять вводимые пользователем данные.
Это не означает, что фильтрация по-прежнему не является лучшей практикой, но с точки зрения SQL-инъекции и XSS вы будете гораздо более защищены, если будете неукоснительно использовать параметризацию запросов и кодирование сущностей HTML.
Во многих случаях это неверно. См. Примечания OSWAP «Почему я не могу просто кодировать ненадежные данные в HTML?» owasp.org/index.php/…
Редактировать: отбеливать - это оболочка для html5lib, которая упрощает использование в качестве дезинфицирующего средства на основе белого списка.
html5lib поставляется с средством очистки HTML на основе белого списка - его легко создать подкласс, чтобы ограничить теги и атрибуты, которые пользователи могут использовать на вашем сайте, и он даже пытается очистить CSS, если вы разрешаете использование атрибута style.
Вот теперь я использую его в служебной функции sanitize_html моего клона Stack Overflow:
http://code.google.com/p/soclone/source/browse/trunk/soclone/utils/html.py
Я провел все атаки, перечисленные в Шпаргалка по XSS на ha.ckers.org (которые легко удаляются с помощью доступен в формате XML после преобразования Markdown в HTML с использованием python-markdown2, и, похоже, все прошло нормально.
Однако компонент редактора WMD, который в настоящее время использует Stackoverflow, представляет собой проблему - мне фактически пришлось отключить JavaScript, чтобы протестировать атаки XSS Cheatsheet, поскольку вставка их всех в WMD закончилась тем, что я получил окна предупреждений и очистил страницу.
Чтобы очистить строковый ввод, который вы хотите сохранить в базе данных (например, имя клиента), вам нужно либо экранировать его, либо просто удалить из него любые кавычки (', "). Это эффективно предотвращает классическую SQL-инъекцию, которая может произойти, если вы собирают SQL-запрос из строк, переданных пользователем.
Например (если допустимо полное удаление кавычек):
datasetName = datasetName.replace("'","").replace('"',"")
Э ... нет ... Я бы все равно не стал этого делать. Для всего, что является элементом данных, используйте параметризованные запросы. Для запросов, не связанных с данными (динамически создаваемые запросы), вам определенно следует использовать белый список. pg_catalog.pg_user не содержит кавычек, но вы, вероятно, также не захотите этого в сгенерированных запросах. Вместо этого сделайте что-нибудь вроде datasetName = datasetName if datasetName in DATASETNAME_WHITELIST else sulk()
Вы не должны пытаться исправить SQL-инъекцию путем дезинфекции пользовательского ввода! При правильном использовании API базы данных вероятность SQL-инъекции отсутствует.