我问这个问题有点傻,因为我似乎是世界上唯一一个不了解这个问题的人,但是无论如何,这都是可行的。我将以Python为例。当我使用原始SQL查询(通常使用ORM)时,我会使用参数化,例如使用SQLite的以下示例:
方法A:
username = "wayne" query_params = (username) cursor.execute("SELECT * FROM mytable WHERE user=?", query_params)
我知道这可行,我知道这是通常推荐的方式。SQL注入易受攻击的方式可以执行以下操作:
方法B:
username = "wayne" cursor.execute("SELECT * FROM mytable WHERE user='%s'" % username)
到目前为止,我可以告诉我了解SQL注入,如本Wikipedia文章中所述。我的问题很简单:方法A与方法B有什么真正的不同?为什么方法A的最终结果与方法B不同?我假设该cursor.execute()方法(Python的DB- API规范的一部分)负责正确地对输入进行转义和类型检查,但这从未在任何地方明确声明。在这种情况下,所有这些参数化就是吗?对我来说,当我们说“参数化”时,所有的意思就是“字符串替换”,例如%格式。那不对吗?
cursor.execute()
参数化查询实际上并不执行字符串替换。如果使用字符串替换,则SQL引擎实际上会看到类似以下的查询
SELECT * FROM mytable WHERE user='wayne'
如果使用?参数,则SQL引擎会看到如下查询
?
SELECT * FROM mytable WHERE user=<some value>
这意味着,即使在看到字符串“ wayne”之前,它也可以完全解析查询并大致了解查询的功能。它将“ wayne”粘贴到它自己的查询表示中,而不是描述查询的SQL字符串中。因此,SQL注入是不可能的,因为我们已经通过了该过程的SQL阶段。
(以上是概括性的,但或多或少传达了这个想法。)