Защита от sql injection python

Как лучше защитить sql запрос от sql injection средствами python?

Использую python 3.7 и библиотеку pymysql.
Mysql 5.7
Какие метода защиты посоветуете (желательно с примером) ? Или какую литературу ? Любая информация будет очень полезна мне.
UPD: Почитав как защищает pymysql здесь понял что у меня VALUES уже так экранирован и защищен.

Простой 7 комментариев

Usually your SQL operations will need to use values from Python variables. You shouldn’t assemble your query using Python’s string operations because doing so is insecure; it makes your program vulnerable to an SQL injection attack (see https://xkcd.com/327/ for humorous example of what can go wrong).

Instead, use the DB-API’s parameter substitution. Put ? as a placeholder wherever you want to use a value, and then provide a tuple of values as the second argument to the cursor’s execute() method. (Other database modules may use a different placeholder, such as %s or :1.)

r4khic

r4khic, Это доки стандартного питоновского курсора, в pymysql Для этого используется %s.
Т.е. у тебя и так уже экранированный запрос получится

r4khic

javedimka, я читал доки pymysql и ничего такого не нашел,если вам не трудно можете пожалуйста скинуть ссылку на то место ?

r4khic, Ну и вообще вся информация которую я скинул была расписана понятным языком в ответе который ты отметил решением, ctrl + f по Crafting Safe Query Parameters

r4khic

TheRonCronix

Вообще, если хотите сделать правильно, то нужно использовать связывание переменных с запросом (bind variables). Это:
1 — решает проблему sql-инъекции. 2 — способствует повышению производительности, т.к. запрос парсится в субд 1 раз и затем уже просто переиспользуется с новыми значениями переменных.
В статьях, которые вам подкинули про это есть. Это важно не только для python, но и вообще везде, поэтому стоит запомнить один раз. Используйте bind variables.

r4khic

Пожалуйста, не изобретайте велосипед.
Для начала задумайтесь, как происходит инъекция? Как зловредный код попадает в SQL-базу?
Затем подробнее прочитайте про WEB-фреймворки и ORM.
Например Django — очень развитый фреймворк в плане security и у него вполне пригодный ORM.

r4khic

r4khic, Если вы озабочены проблемой SQL-инъекций, значит ваш веб-сервис будет висеть на хостинге и будет доступен всему миру и его могут заметить злые хакеры и попробовать сломать. Если это так и если оно действительно того стоит, может подойти к вопросу безопасности чуть более серьёзно и довериться более проверенным и комплексным решениям?
Хотя, если вы лишь в самом начале и просто изучаете Python и веб-программирование — дерзайте. Читайте мануалы, пробуйте разные подходы, наступайте на типичные грабли. Для начала защититесь от SQL-инъекций, потом от XSS и т.д.
Говорю тут совершенно без сарказма, это нормальный путь настоящего программиста — всё пробовать самому.

r4khic

Антон Коновалов, благодарю за такой развертывающий ответ.Все по полочкам расставили.Благодарю еще раз

Источник

Безопасная разработка на Python

Язык программирования Python приобрел большую популярность среди разработчиков благодаря различным решениям, заложенным в его архитектуру. Такими решениями являются сильная динамическая типизация, то есть язык не допускает неявных приведений типов в неоднозначных ситуациях (например, сложение букв и цифр), при этом тип переменной определяется во время присваивания ей значения и может изменяться по ходу программы. Также полезной функцией языка Python автоматическое управление памятью и поддержка множества парадигм программирования, таких как структурное и функциональное программирование. И наконец, Python является полностью объектно-ориентированным языком с поддержкой интроспекции, то есть способности определять тип объекта во время выполнения.

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

Такие разные инъекции

Прежде всего, начнем с определения. Инъекция команд — это вид атаки, целью которой является выполнение произвольных команд ОС сервера или произвольных SQL запросов в случае с СУБД.

Инъекция команд позволяет выполнить практически любую команду ОС с правами текущего пользователя. Так, командная строка shell, запущенная с помощью инъекции /bin/sh в приложение, работающее с правами root, будет работать также с правами привилегированного пользователя. Причина такого “странного” поведения кода кроется в некорректной обработке данных при динамической оценке интерпретатором выполняемого кода.

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

Объект Popen

Команда popen , а также команды popen3 , popen4 выполняют переданную строку как команду, что создает возможность для инъекции произвольных команд. Рассмотрим небольшой пример:

 import os user_input = "/etc && cat /etc/passwd os.popen("ls -l " + user_input)

Здесь мы в переменной user_input в качестве пользовательского ввода получаем путь к тому каталогу, содержимое которого нужно вывести на экран. Но если пользователь передает в качестве параметра не только каталог, но и другую команду, то popen выполняет обе команды. То есть в данном случае выводит содержимое файла /etc/passwd.

Еще одна проблемная команда — это subprocess . Команда subprocess позволяет создавать новые процессы, подключаться к их каналам ввода/вывода/ошибок и получать их коды возврата. Данная команда позволяет создавать новые процессы, а метод call выполняет переданную текстовую строку:

import subprocess import sys user_input = "/bin && cat /etc/passwd" subprocess.call("grep -R <> .".format(user_input), shell=True)

И еще одна аналогичная команда, выполняющая переданные пользователем данные без какой-либо проверки это os.system:

import os user_input = "/etc && cat /etc/passwd" os.system("grep -R <> .".format(user_input))

SQL инъекции

Инъекции команд SQL, наверное, можно назвать наиболее распространенным видом инъекций команд. SQL инъекции — это метод внедрения кода, который позволяет злоумышленнику вставить или изменить SQL-запрос в приложении. Для понимания проблемы приведем пример фрагмента кода:

 def list_users(): rank = request.args.get('rank', '') if rank == 'admin': return "Can't list admins!" c = CONNECTION.cursor() c.execute("SELECT username, rank FROM users WHERE rank = ''".format(rank)) data = c.fetchall()

Здесь, если в качестве запроса к веб-приложению передать следующую строку:

http://localhost:5000/users?rank=user’ UNION ALL SELECT * FROM SSN—

Тогда приложение вернет все записи из таблицы SSN. SQL-инъекции являются проблемой для большинства языков программирования, не только для Python.

Общие рекомендации по защите

Мы рассмотрели несколько примеров использования небезопасных команд и способов эксплуатации инъекций. Теперь самое время поговорить о том, как можно защититься от таких уязвимостей. Сразу хочу заметить, что инъекции команд — это не единственный вид уязвимостей, которые есть в Python, и в следующих статьях мы поговорим о других проблемах данного языка.

Итак, список рекомендаций для разработчиков можно начать с «прописной истины», а именно: Никогда не доверяйте данным, передаваемым пользователями! Да, концепция нулевого доверия существует уже много лет и все вроде бы хорошо знают, что нельзя доверять данным передаваемым пользователями, но уязвимости инъекции команд по прежнему можно встретить, особенно в веб-приложениях.

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

Приведем небольшой пример. Пусть у нас в приложении используется команда find . Мы можем «захардкодить» выполнение этой команды, но оставить ввод произвольных параметров. Вроде бы пользователь не может осуществить инъекцию в чистом виде, но у find есть ключик exec, позволяющий выполнить любую команду. И если наше исходное приложение будет запущено под sudo или с SUID bit, то после инъекции ключа exec с нужным значением злоумышленник получит права root.

sudo find . -exec /bin/sh ; -quit

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

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

Безопасные команды

Рассмотрим безопасные варианты из приведенных выше примеров кода:

user_input python">subprocess.check_output('ls -l dir/’)# проверка ввода

Значение shell=False не позволит выполнить команды:

 subprocess.call('echo $HOME', shell=False)# запрет выполнения

И наконец, проверка переданных приложению аргументов на соответствие имени какого-либо существующего файла.

os.path.isfile(sys.argv [ 1])# проверка передаваемых аргументов

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

Модуль Re

Принцип работы модуля — это использование регулярных выражений для проверки вводимых пользователем строк на наличие потенциально опасных команд.

import re Python_code = input() Pattern = re.compile(‘re_command_pattern’) If pattern.fullmatch(python_code): # выполнение python_code

Модуль Yaml

Еще одно средство контроля пользовательского ввода — это модуль Yaml. С помощью этого модуля мы можем проверить является ли переданный пользователем файл потенциально опасным или это обычный безобидный файл.

В примере ниже мы сначала проверяем обычный текстовый файл, на который программа никак не реагирует, а затем передаем в качестве входной строки путь к файлу /bin/ls и получаем кучу различных сообщений об ошибках.

import yaml user_input = input() with open(user_input) as secure_file: contents = yaml.safe_load(secure_file) 

Заключение

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

А сейчас рекомендую всем желающим посетить открытый урок «Основы ООП в Python», на котором мы познакомимся с наследованием и научимся работать с классами. В результате этого занятия вы:

  • научитесь создавать свои классы;
  • разберётесь с наследованием;
  • научитесь переопределять методы и обращаться к методам суперклассов.

Источник

Как избежать SQL-инъекций в Python при использовании psycopg2

Язык программирования Python

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

Схема

Допустим, у нас есть веб-страница, на которой через текстовую форму пользователи могут оставлять комментарии.

В приведенном ниже фрагменте кода информация принимается и сохраняется.

def add_comments(content): conn = psycopg2.connect("dbname=yourdatabase") cursor = conn.cursor() cursor.execute("insert into comments values ('$s')" % content) conn.commit() conn.close()
Code language: JavaScript (javascript)

Где проблема в приведенном выше коде? Вы сможете ее найти?

Прежде чем выявлять и устранять проблему, давайте посмотрим в документации psycopg, о чем она нам говорит:

Перевод: документация предупреждает нас никогда, НИКОГДА не использовать объединение строк (+) или интерполяцию строк (%) для передачи переменной в строку SQL.

К чему это может привести?

Делая это таким образом (cursor.execute(“insert into comments values (‘$s’)” % content)). При использовании, например, кавычек или другого специального символа, код выдаст ошибку 500 (Internal Server Error), поскольку символ напрямую соединяется со строкой SQL, вызывая ее поломку.

Как это исправить?

Исправим наш код, чтобы решить проблему, согласно документации psycopg в рамке, выделенной зеленым цветом:

def add_comments(content): conn = psycopg2.connect("dbname=yourdatabase") cursor = conn.cursor() cursor.execute("insert into comments values ($s)", (content,)) conn.commit() conn.close()
Code language: JavaScript (javascript)

Итак, проблема решена, и мы защитили себя от SQL Injection.

Источник

Читайте также:  Пояснение работы парсера
Оцените статью