代码之家  ›  专栏  ›  技术社区  ›  Sir Rubberduck

从SQL注入生成的查询有多安全?

  •  1
  • Sir Rubberduck  · 技术社区  · 7 年前

    我正在尝试创建一个搜索栏,它可以处理多个单词,但我担心SQL注入。

    我正在使用 节点快速 npm mssql 包裹。

    下面是获取条件、生成SQL并运行它的代码:

    router
    .get('/search/:criteria', function (req, res) {
        var criteria = req.params.criteria;
        var words = criteria.split(" ");
    
        var x = ""
        words.map(word => x += `name like '%${word}%' and `);
        x = x.substring(0, x.length - 5); // Remove trailing 'and'
    
        var query = `SELECT * FROM table WHERE ${x}`
    
        new sql.ConnectionPool(db).connect().then(pool => {
            return pool.request().query(query)
        }).then(result => {
    
        })
    });
    

    搜索 something to search 将导致此查询:

    SELECT * FROM table 
    WHERE 
        name like '%something%'
        and name like '%to%'
        and name like '%search%'
    

    我自己也尝试过一些SQL注入,但它们似乎都不起作用。


    注释 :我知道我们应该 总是 为此使用输入。它一个字就可以用,但我不知道如何对许多字使用输入。前任:

    new sql.ConnectionPool(db).connect().then(pool => {
            return pool.request()
            .input('input', '%'+criteria+'%')
            .query(query)
        })
    
    1 回复  |  直到 7 年前
        1
  •  5
  •   Tomalak    7 年前

    答案是:这不安全。你的代码也不能保证安全。不要通过将用户提供的数据连接/插入语句来构建SQL。

    另外,你不会为 LIKE 它本身也是不洁净的。

    如果需要动态SQL,请使用预期数量的占位符和 然后 将用户提供的值绑定到这些占位符。

    router.get('/search/:criteria', (req, res) => {
        const ps = new sql.PreparedStatement();
        const sqlConditions = [];
        const escapedValues = {};
    
        // set up escaped values, safe SQL bits, PS parameters
        req.params.criteria.split(" ").forEach((v, i) => {
            const paramName = 'val' + i;
            escapedValues[paramName] = v.replace(/[\\%_]/g, '\\$&');
            sqlConditions.push(`name LIKE '%' + @${paramName} + '%' ESCAPE '\'`);
            ps.input(paramName, sql.VarChar);
        });
    
        // build safe SQL string, prepare statement
        const sql = 'SELECT * FROM table WHERE ' + sqlConditions.join(' AND '); 
        ps.prepare(sql);
    
        // connect, execute, return
        ps.execute(escapedValues).then(result => {
            res(result)
        });
    });
    

    (免责声明:代码未经测试,因为我目前没有可用的SQL Server,但您可以理解。)