在 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 Statements
,SQL 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 构建查询是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章