【发布时间】:2019-09-23 23:19:24
【问题描述】:
我尝试在 pymysql 中使用 UPDATE 语句来更新某些列的值,其中self.key、self.value、self.id 是三个变量。
cur.execute("UPDATE environment_history SET {key}=%s WHERE id=%s".format(key=self.key),
(self.value, self.id)
)
虽然在上面的代码中,这为 SQL 注入留下了机会。我们只需要发布一些这样的数据
{"id":"23151","key":"uuid='ac211';#","value":"abcde"}
这将更新所有行,这可能更危险。 我必须阻止这种情况发生。
我尝试了一些不切实际的解决方案,其中之一是:
cur.execute("UPDATE environment_history SET %s=%s WHERE id=%s",
(self.key,self.value, self.id)
)
但是,pymysql 会将列名转义为\'uuid\'。
这是一个 SQL 语法错误,因为 SET col_name=3 和 SET `col_name`=3 是正确的。
那么,如何避免这种SQL注入呢?
尝试手动替换和转义 self.key 是我能想到的唯一选择,但这听起来不是一种优雅的方式。
我的数据库是 MySQL。
有什么想法吗?谢谢!
【问题讨论】:
-
列名不能作为准备好的语句中的参数。即使上述方法可以工作,你也不应该这样做。相反,请找到一种方法,以便您可以对列名和表名进行硬编码。
-
您是否直接从输入中获得
self.key?这本身就很危险。为什么不按特定关键字过滤呢? -
我投票关闭作为“如何动态准备 SQL 查询(也包括列名)避免 SQL 注入”的重复项,即使该问题使用 PHP 作为示例代码。但是任何语言的原理都是一样的。将您的
self.key限制为已知列名值的白名单,然后使用纯字符串插值将其插入 SQL 字符串,而不是使用引用值的cur.execute()魔法。
标签: python mysql sql-injection pymysql