【问题标题】: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

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

供参考:

更新/回答

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

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

【问题讨论】:

    标签: javascript mysql sql express node-mysql


    【解决方案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一无所知,无法解决您的其他问题。
    猜你喜欢
    • 2012-05-20
    • 1970-01-01
    • 2021-11-29
    • 2020-11-21
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-30
    相关资源
    最近更新 更多