Является ли этот запрос Python / MySQL подвержен SQL-инъекции - PullRequest
2 голосов
/ 06 ноября 2019

В настоящее время я проверяю чей-то код и наткнулся на следующую строку Python:

db.query('''SELECT foo FROM bar WHERE id = %r''' % id)

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

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

  1. Значение 'id' является строкойили номер, предоставленный конечным пользователем / пентестером
  2. Это MySQL
  3. Соединение явно настроено на использование UTF8.

1 Ответ

1 голос
/ 06 ноября 2019

Драйверы Python для MySQL не поддерживают реально подготовленные операторы. Все они выполняют некоторую форму интерполяции строк. Хитрость заключается в том, чтобы заставить Python выполнить интерполяцию строк с правильным экранированием.

Посмотрите демонстрацию небезопасного выполнения этого действия: Как PyMySQL предотвращает атаки от SQL-инъекций?

Обычное решение для имитации параметров заключается в следующем:

sql = "SELECT foo FROM bar WHERE id = %s"
cursor.execute(sql, (id,))

См. https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html


Единственные известные мне способы преодоления побега (когда это сделано правильно)::

  • Использование GBK или SJIS или аналогичных наборов символов, где экранированная кавычка становится частью многобайтового символа. Обеспечив set names utf8, вы будете в безопасности от этой проблемы.
  • Измените sql_mode, чтобы прервать экранирование, например enable NO_BACKSLASH_ESCAPES или ANSI_QUOTES. Вы должны установить sql_mode в начале вашего сеанса, аналогично тому, как вы устанавливаете имена. Это гарантирует, что он не использует глобально измененный sql_mode, который вызывает проблему.

См. Также Достаточно ли "mysqli_real_escape_string", чтобы избежать внедрения SQL или других атак SQL?

...