在 SQL 注入中使用 LIKE 构建查询是不是安全?

Posted

技术标签:

【中文标题】在 SQL 注入中使用 LIKE 构建查询是不是安全?【英文标题】:Is building a query using LIKE safe from SQL Injection?在 SQL 注入中使用 LIKE 构建查询是否安全? 【发布时间】:2015-04-25 13:57:04 【问题描述】:

我的快速应用程序中有一个接受 POST 数据 (json) 的端点。我想使用这些数据安全地查询 mysql 数据库。转义和更改我的字符串是否会使我容易受到剥削?

我需要更改来自请求的字符串,因为我不想在 LIKE 子句的结束单引号之前插入“%”。

var searchTerm = mysql.escape(req.body.firstName)
var newStr = "'" + searchTerm.substring(1, searchTerm.length - 1) + "%'"

// Example:  'alex' => 'alex%'

我的查询是:

SELECT * FROM tbl WHERE col LIKE " + newStr + " ORDER BY key

这可行,但有没有首选或更安全的方法来做到这一点?

供参考:

我正在使用我正在使用这个包:https://github.com/felixge/node-mysql

更新/回答

根据EternalHour 的回答,正确的语法是:

var newStr = req.body.firstName + "%"
var sql = "SELECT cols FROM tbl WHERE col LIKE ? ORDER BY key"
sql = mysql.format(sql, newStr)

【问题讨论】:

【参考方案1】:

使用下面的方法直接尝试 newStr(不要显式添加 %):

SELECT * FROM tbl WHERE col LIKE '" + newStr + "%' ORDER BY key

【讨论】:

如果我这样做,产生的错误是:ER_PARSE_ERROR:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取在 'alex'%' 附近使用的正确语法。这就是为什么我不得不重新构建字符串【参考方案2】:

你应该通过Prepared Statement

C#:

//Creates new SQL Command with parameter @newStr
var command = new SqlCommand( "SELECT * FROM tbl WHERE col LIKE '@newStr' ORDER BY key", db);

//Set paramater @newStr to 40 characters
command.Parameters.Add("@newStr", SqlDbType.VarChar, 40);

//Prepares the statement, after all parameters are defined
command.Prepare();

//Set Parameter @newStr to "newStrValue"
command.Parameters["@newStr"] = "newStrValue";

//Executes the Command
command.Execute();

对于 Node.js,有一个包支持准备好的语句:

https://www.npmjs.com/package/mysql2

使用Prepared StatementsSQL Injection 永远不会发生,因为数据库知道这是用户输入,而不是 SQL 命令。

【讨论】:

这看起来像 C#,但我使用的是 javascript @Mike,对此感到抱歉。没看到。不了解 Javascript 和 MySql。你正在使用 Node.js?在我这边,这里没有知识。但我想说,在每种语言中,Prepared Statements 都是关键。这个包似乎支持他们:npmjs.com/package/mysql2 我正在使用这个包:github.com/felixge/node-mysql/#escaping-query-values。我确实尝试使用准备好的语句,问题似乎是 LIKE 需要用单引号括起来,而我的转义字符串也出现在单引号中 \' 之类的东西不起作用?对不起,我不知道Node.js。但可以肯定的是,您想找到一种使用Prepared Statements 的方法。它们是当前解决问题的方法。【参考方案3】:

正如 Christian 所建议的(在不同的编程语言中),使用准备好的语句是最安全的选择。看起来您需要重新格式化您的字符串以删除单引号(因为准备好的语句通常会自动转义)。看来这个库也不例外。

对这个库不熟悉,但看起来会是这样的:

var query = "SELECT * FROM tbl WHERE col LIKE ? ORDER BY key";
var newStr = searchTerm.substring(1, searchTerm.length - 1) + "%";
sql = mysql.format(query, newStr);

附带说明,尽量不要在 SQL 选择语句中使用 *

【讨论】:

逻辑正确,语法接近。我将用有效的方法更新我的问题。至于使用 *,我知道我不应该使用它;) @EternalHour。你能解释为什么“选择*”不是一个好习惯吗?此外,node-mysql 的动态 SQL 构造并不完全完整,因为它不支持真正的准备好的语句,并且还有其他方法可以避免 SQL 注入,这些方法非常特定于该包,或者我认为如此。该软件包的文档在这方面有一些解释,但不是很清楚。 @Samir - SELECT * 是不好的做法,除非您实际上需要每一列,如果您需要整个表,请务必这样做。我认为一些开发人员只是变得懒惰,或者可能想要更短的 SQL 语句,所以他们使用它。我对node-mysql一无所知,无法解决您的其他问题。

以上是关于在 SQL 注入中使用 LIKE 构建查询是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

PHP 在LIKE查询中阻止sql注入

MyBatis单表查询——参数占位符${}和#{}SQL注入like查询

pg数据库like防止sql注入

信安小白,一篇博文讲明白暴力破解和SQL注入

C#中 SQL语句 带参数的like 查询怎么写

QLDB/PartiQL 中是不是可能存在 SQL 注入攻击