SQL查询参数化如何工作?

Way*_*rts 33 sql security sql-injection

我觉得这有点傻,因为我似乎是世界上唯一一个没有得到它的人,但无论如何都要去.我将以Python为例.当我使用原始SQL查询(我通常使用ORM)时,我使用参数化,就像使用SQLite的这个例子一样:

方法A:

username = "wayne"
query_params = (username)
cursor.execute("SELECT * FROM mytable WHERE user=?", query_params)
Run Code Online (Sandbox Code Playgroud)

我知道这有效,我知道这是一般推荐的方法.一个SQL注入易受影响的方法来做同样的事情将是这样的:

方法B:

username = "wayne"
cursor.execute("SELECT * FROM mytable WHERE user='%s'" % username)
Run Code Online (Sandbox Code Playgroud)

到目前为止,我可以告诉我理解SQL注入,正如本维基百科文章中所解释的那样.我的问题很简单:方法A与方法B有什么不同?为什么方法A的最终结果与方法B不同?我假设该cursor.execute()方法(Python的DB-API规范的一部分)负责正确转义和输入类型检查,但这在任何地方都没有明确说明.在这种情况下,这就是所有参数化吗?对我来说,当我们说"参数化"时,所有这些都意味着"字符串替换",如%-formatting.这是不正确的?

Joh*_*eek 42

参数化查询实际上不进行字符串替换.如果使用字符串替换,那么SQL引擎实际上会看到一个类似的查询

SELECT * FROM mytable WHERE user='wayne'
Run Code Online (Sandbox Code Playgroud)

如果使用?参数,则SQL引擎会看到类似的查询

SELECT * FROM mytable WHERE user=<some value>
Run Code Online (Sandbox Code Playgroud)

这意味着在它甚至看到字符串"wayne"之前,它可以完全解析查询并通常理解查询的作用.它将"wayne"粘贴到自己的查询表示中,而不是描述查询的SQL字符串.因此,SQL注入是不可能的,因为我们已经通过了该过程的SQL阶段.

(以上是概括的,但它或多或少传达了这个想法.)

  • @johnny:它会找到`mytable`中的所有内容,其中`user`是`wayne; drop table accounts`.它将拉回Little Bobby Tables的实际记录. (7认同)
  • 因此,如果他有办法;丢弃表帐户,它会给出什么样的错误?没结果? (2认同)