Очистка пользовательского ввода с помощью Python

Как лучше всего очистить ввод пользователя для веб-приложения на Python? Есть ли одна функция для удаления символов HTML и любых других необходимых комбинаций символов для предотвращения атаки XSS или SQL-инъекции?

Вы не должны пытаться исправить SQL-инъекцию путем дезинфекции пользовательского ввода! При правильном использовании API базы данных вероятность SQL-инъекции отсутствует.

John La Rooy 22.03.2010 23:52

... if database API is used properly there is no chance of SQL injection. Под «правильно» вы имеете в виду использование параметризованных запросов? Это покрывает вас на 100%?

user 27.08.2014 19:03

@buffer, я знаю, что ваш комментарий старый, но если вы хотите, чтобы другие люди, кроме OP, видели ваши комментарии, вы должны вызвать их с помощью символа \ @.

user1717828 27.10.2015 22:59
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
59
3
37 074
7

Ответы 7

Если вы используете фреймворк, например джанго, фреймворк может легко сделать это за вас с помощью стандартных фильтров. На самом деле, я почти уверен, что 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&#x09;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')".

Gareth Simpson 22.03.2010 21:30

Вы можете легко добавить это с помощью другого регулярного выражения для vbscript: например, для javascript:

tghw 22.03.2010 23:27

@tghw, Пример vbscript вот почему решения из белого списка обычно предпочтительнее решений из черного списка. Как узнать наверняка, что все необходимое занесено в черный список? С черным списком на следующей неделе может выйти новый браузер, который будет уязвим, поскольку поддерживает новый тип тега скрипта.

John La Rooy 22.03.2010 23:56

@gnibbler Я согласен, и по большей части это решение для белых списков, но для href и src действительно нет способа легко добавить в белый список. Единственный вариант, который я могу придумать, - это сделать все URL-адреса абсолютными, передав URL-адрес страницы, а затем просматривая каждую ссылку и изображение и вычисляя абсолютный URL-адрес на основе URL-адреса страницы. Чем больше я об этом думаю, тем легче это кажется. Добавлю выше.

tghw 25.03.2010 04:15

Как правило, дезинфицировать HTML очень сложно, существует множество векторов: nick.cleaton.net/xssrant.html

rjh 25.03.2010 04:40

Спасибо большое. Я включил этот метод в сообщение в блоге, посвященное настройке безопасного ввода данных пользователем с помощью Django: birdhouse.org/blog/2010/05/12/secure-user-input-with-django

shacker 13.05.2010 06:37

Это потрясающе. Использование его для очистки комментариев в моем маленьком блоге. :) -- Спасибо.

PKKid 28.08.2010 10:02

Я больше не занимаюсь веб-разработкой, но когда занялся, то сделал что-то вроде этого:

Когда не предполагается никакого синтаксического анализа, я обычно просто избегаю данных, чтобы не мешать базе данных, когда я их сохраняю, и избегаю всего, что я читаю из базы данных, чтобы не мешать html, когда я показываю его (cgi.escape () в питон).

Скорее всего, если кто-то попытается ввести символы html или что-то в этом роде, они действительно захотят, чтобы это отображалось как текст. Если они этого не сделали, хорошо :)

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

Когда мне нужен был некоторый синтаксический анализ (разметка или что-то еще), я обычно пытался сохранить этот язык в непересекающемся наборе с html, чтобы я мог просто сохранить его с соответствующим экранированием (после проверки на синтаксические ошибки) и проанализировать его в html при отображении без нужно беспокоиться о том, что данные, которые пользователь поместил туда, мешают вашему html.

См. Также Экранирование HTML

Лучший способ предотвратить XSS - это не пытаться фильтровать все, а просто выполнять кодирование HTML Entity. Например, автоматический поворот

SQL-инъекция, вопреки другому мнению, все еще возможна, если вы просто создаете строку запроса. Например, если вы просто объединяете входящий параметр в строку запроса, у вас будет SQL Injection. Лучший способ защититься от этого - не фильтровать, а строго использовать параметризованные запросы и НИКОГДА не объединять вводимые пользователем данные.

Это не означает, что фильтрация по-прежнему не является лучшей практикой, но с точки зрения SQL-инъекции и XSS вы будете гораздо более защищены, если будете неукоснительно использовать параметризацию запросов и кодирование сущностей HTML.

Во многих случаях это неверно. См. Примечания OSWAP «Почему я не могу просто кодировать ненадежные данные в HTML?» owasp.org/index.php/…

Purrell 30.12.2016 10:33

Редактировать: отбеливать - это оболочка для 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()

SingleNegationElimination 08.05.2012 20:35

Другие вопросы по теме