Python MySQL,这是一个准备好的语句吗?
Posted
技术标签:
【中文标题】Python MySQL,这是一个准备好的语句吗?【英文标题】:Python MySQL, is this a prepared statement? 【发布时间】:2019-01-31 12:14:24 【问题描述】:我正在设置一个 mysql 应用程序。这是我使用标准 mysqldb 格式连接的 getUsername 方法。 这是否意味着这是一个准备好的声明?另外,这段代码安全吗,还是我容易受到 SQL 注入的攻击?
def selectUser(userName):
try:
username = pickle.loads(base64.decode(userName))
except:
username = "admin"
query = "SELECT name FROM users WHERE name = '%s'"
conn = MySQLdb.connect('localhost', 'dbAdmin', 'lja8j30lJJal##', 'blog');
with conn:
c = conn.cursor()
c.execute(query, (username,))
【问题讨论】:
我相信这是一个 parameterized 语句,而不是一个 prepared 语句。是的,它不会受到 SQL 注入的影响。 我不是 100% 确定这在 Python 中是如何工作的,但我怀疑name = '%s'
最终会变成 name = ''John''
或 name = 'NULL'
,这可能不是什么您打算这样做,在前一种情况下可能会导致 SQL 端出现语法错误。通常参数周围没有引号,因为如有必要,它们将由库添加。
我的想法是使攻击向量成为可能,因为 pickle.loads() 会出错,因为方法应该是 load()。这样,它将始终是管理员用户。
【参考方案1】:
否 - 无法在 MySQLdb 中创建准备好的语句。在MySQL API binding in _mysql.c 中找不到任何mysql_stmt_init()
、mysql_stmt_prepare()
或mysql_stmt_execute()
。
无论出于何种原因,MySQLdb 的作者选择模拟参数,而不是使用真正的服务器端准备好的语句。
为了防止 SQL 注入,MySQLdb 包使用 Python 字符串格式语法。它将动态值插入 SQL 查询并应用正确的转义,即在引号字符之前添加 \
以确保动态值不包含字符串分隔符。
请参阅我对How do PyMySQL prevent user from sql injection attack? 的回答以进行演示。
但是,如果您需要对数值常量使用动态值,则转义将无济于事。
【讨论】:
Sticky bit 在上面留下了关于查询报价的评论。这是攻击向量还是 mysqldb 不存在格式错误的查询? 如果引用不正确,则存在 SQL 注入漏洞的风险。请参阅我为另一个 Stack Overflow 答案提供的链接中的示例。以上是关于Python MySQL,这是一个准备好的语句吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 MySQL 中使用准备好的语句可以防止 SQL 注入攻击吗?
Python MySql Connector 准备好的语句和字典类
为啥mysql.connecter python准备好的语句在bytearray中返回字符串
无法在准备好的 INSERT 语句中的 python mysql.connector 中使用 None (NULL) 值