参数化查询没防住SQL注入?我的代码哪里写错了?

俊杰酱~ 阅读 235

最近在学参数化查询防注入,但测试时发现还是能被绕过。比如在Node.js用mysql模块写这个登录验证:


const query = 'SELECT * FROM users WHERE username = ? AND password = ?';
db.query(query, [username, password], (err, results) => {
  // 处理结果
});

但当我用’ OR ‘1’=’1′– 作为用户名测试时,居然能绕过密码验证。难道参数化查询不能防这种条件注入?我是不是应该把参数单独写成对象?或者需要对特殊字符做额外转义?

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
诸葛羽墨
我当时也卡在这,后来发现是用了拼接字符串的姿势不对。

你这段代码本身没有问题,问题可能出在username或者password变量来源上。如果直接用了req.body.username或者URL参数这种未经处理的原始输入,中间件或者库可能已经帮你做过一次unescape了。

举个例子:
假设请求时传的是username=' OR '1'='1'--
到了后端变量里其实会变成username=" OR '1'='1'--

这时候你再用参数化查询,实际执行的语句就变成了:
SELECT * FROM users WHERE username = " OR '1'='1'-- " AND password = ?

看到问题了吗?引号闭合被绕过了。

解决办法很简单,在获取参数的时候手动加一层escape:
username = connection.escape(req.body.username)
password = connection.escape(req.body.password)

或者用Object形式传参:
db.query(query, { username: req.body.username, password: req.body.password }, ...)

我当时调试了整整一下午才找到原因,记住一句话:永远不要相信任何外部输入。
点赞 14
2026-02-06 13:03