这个参数化查询如何防止 SQL 注入?

Posted

技术标签:

【中文标题】这个参数化查询如何防止 SQL 注入?【英文标题】:How can this Parametrized Query Prevent SQL Injection? 【发布时间】:2020-05-01 11:21:29 【问题描述】:

我知道参数化查询用于防止 SQL 注入,但这如何防止 SQL 注入?有人不能将他们的 id 设置为等于; DROP TABLE * -- 并将其插入到参数化查询中吗?

let updateQueryData = `UPDATE table SET lookups = $1 WHERE id = $2`;
        let updateQueryValues = [numLookups, data.rows[0].id];
        pool.query(updateQueryData, updateQueryValues, err => 

【问题讨论】:

WHERE id = DROP TABLE * 会因语法错误而失败。尝试在查询中运行它。 当您使用参数化查询时,查询引擎不仅会解析您的参数并将它们放入查询字符串中。它被直接注入查询引擎。因此,它对输入进行了验证,以防止查询注入。 它们的关键区别在于参数指示数据库查询引擎这些是 并且应该被这样对待,而直接字符串连接不会将此类信息传递给查询引擎并且它只是执行你给它的任何 code。在前者中,占位符和值是分开的,直到它们到达数据库并允许数据库正确处理它们,它知道该怎么做。用户当然可以提供看起来像代码的值,但它只是一个字符串值,仅此而已。 这能回答你的问题吗? How can prepared statements protect from SQL injection attacks? 【参考方案1】:

UPDATE 表 SET 查找 = $1 WHERE id = $2

您的查询参数化。

如果有人传递像'; DROP TABLE * --' 这样的恶意值会发生什么:

如果对应的列是字符串数据类型,那么查询变成这样:
UPDATE table SET lookups = '; DROP TABLE * --' WHERE id = 1
如果列是数字,您将收到运行时错误,因为'; DROP TABLE * --' 不是数字

【讨论】:

【参考方案2】:

没有。数据不是简单地插入到查询的文本表示中。它是单独发送的。

为了防止注入,数据必须与命令分开,这样数据和命令之间就没有歧义。这正是参数化查询的作用。

(注意:有些库仍然会发送包含一体式数据的查询,但所有数据都会自动“转义”,因此仍然可以安全使用。)

另外,我强烈建议您删除这些反引号并用常规引号替换,这样您以后就不会意外地将数据连接到该查询中。

【讨论】:

以上是关于这个参数化查询如何防止 SQL 注入?的主要内容,如果未能解决你的问题,请参考以下文章

参数化查询如何帮助防止 SQL 注入?

参数化查询为什么能够防止SQL注入 (转)

为什么参数化查询可以防止SQL注入?(转)

参数化查询防止Sql注入

使用参数化查询防止SQL注入漏洞

参数化sql查询语句