Каковы наилучшие методы снижения атак SQL-инъекций при использовании SQLAlchemy?
SQLAlchemy + SQL Injection
Ответ 1
Если у вас есть специальные символы (например, точки с запятой или апострофы) в ваших данных, они будут автоматически указываться для вас Объект SQLEngine, поэтому вам не нужно беспокоиться о цитировании. Это также означает что, если вы намеренно не обходите Механизмы цитирования SQLAlchemy, Атаки SQL-инъекций в основном невозможно.
[per http://www.rmunn.com/sqlalchemy-tutorial/tutorial.html]
Ответ 2
TL;DR: Избегайте необработанного SQL как можно больше.
Принятый ответ ленив и неверен. Метод фильтра принимает необработанный SQL, и если он используется таким образом, он полностью восприимчив к атакам SQL-инъекций. Например, если вы должны принять значение из URL-адреса и объединить его с сырым sql в фильтре, вы можете атаковать:
session.query(MyClass).filter("foo={}".format(getArgs['val']))
используя приведенный выше код и приведенный ниже URL, вы будете вводить SQL в свой оператор фильтра. Приведенный выше код вернет все строки в вашей базе данных.
http://domain.com/?val=2%20or%201%20=%201
Ответ 3
Добавить в ответ @Tendrid. Я сделал небольшое исследование, используя тихий наивный подход. filter
метод имеет *criterion
в качестве аргумента, несколько других методов ORM Query имеют схожие аргументы.
В случае аргумента filter
метод *criterion
аргумент заканчивается переданным в _ literal_as_text, который в случае строки указывает на его безопасность sql (пожалуйста, поправьте меня, если я ошибаюсь). Поэтому он делает его небезопасным.
Вот результат исследование метода класса ORM с аргументом *criterion
:
filter - uses _literal_as_text (NOT SAFE)
having - uses _literal_as_text (NOT SAFE)
distinct - uses _literal_as_label_reference (NOT SAFE)
group_by - uses _literal_as_label_reference (NOT SAFE)
order_by - uses _literal_as_label_reference (NOT SAFE)
join - uses model attributes to resolve relation (SAFE)
Примеры возможных пропусков метода (чтобы это было просто, форматирование строк пропущено):
db.session.query(User.login).group_by('login').having('count(id) > 4; select name from roles').all()
db.session.query(User.login).distinct('name) name from roles /*').order_by('*/').all()
db.session.query(User.login).order_by('users_login; select name from roles').all()
db.session.query(User.login).group_by('login union select name from roles').all()