如何在变量中扩展 SQL 查询?

How can I extend an SQL query in a variable?

提问人:Arcanus 提问时间:1/30/2022 最后编辑:O. JonesArcanus 更新时间:1/30/2022 访问量:191

问:

我正在我的数据库上测试可能的SQL注入,并且我正在运行一个简单的函数来获得用户不应该得到的结果。返回值基于 id 是正确的,但是,查询的其余部分将被完全忽略。

我想从数据表中返回所有数据。

我的语法有问题吗?

这是我的实现:

function test(id) {
  db.query("SELECT * FROM users WHERE id = ?", [id], (err, result) => {
    console.log(result[0]);
  });
}

const id = "122 UNION SELECT * FROM data";
test(id);
javascript mysql sql 节点 .js sql 注入

评论

2赞 AminM 1/30/2022
驱动程序不应允许您在 ID 中注入 SQL。我不清楚您使用的是什么 API,但通常驱动程序会在插入值之前清理或预编译您的语句。SQL 注入通常在手动连接时发生。
0赞 The Impaler 1/30/2022
看起来像是您的语言或 API 中的安全漏洞。不要连接参数,而是使用“预准备语句”。

答:

1赞 Joel Coehoorn 1/30/2022 #1

你不能这样做。事实上,无法做到这一点是参数化查询的全部意义所在。它可以防止攻击者为您提供类似输入的字符串。122; DROP Table users;

评论

0赞 Arcanus 1/30/2022
您能否详细说明一下您的答案中究竟参数化的内容?它是内置的吗?如果是这样,那么SQL注入怎么可能呢?
0赞 Joel Coehoorn 1/30/2022
它也被称为“预准备语句”,大多数库(至少是那些值得使用的库)确实具有内置的功能。SQL注入是不可能的,这才是重点。当有人使用原始字符串连接而不是参数化查询功能时,就会发生 SQL 注入。
2赞 O. Jones 1/30/2022 #2

这看起来像带有 npm mysql 驱动程序包的 nodejs Javascript。而且,我猜您的列被定义为 INT 或 BIGINT,而不是某种文本字符串。id

使用该方法是防止 SQL 注入的正确方法。它是参数化的。这意味着 SQL 中的每个参数都由一个占位符表示。的第二个参数是要替换占位符的参数值数组。对于您的用例,驱动程序会生成如下所示的查询。.query()?.query()

 SELECT * FROM users WHERE id = '122 UNION SELECT * FROM data' 

并将其传递给 MySQL 服务器。然后,服务器获取您传递的字符串,并尝试将其解释为数字。由于MySQL中的一个怪癖,它将字符串解释为数字122,因此查找。(MySQL通过寻找前导数字将字符串强制转换为整数。所以给出 123,并给出 0。这可能会令人困惑。其他品牌和型号的 RDBMS 在给定它们期望整数的字符串时会抛出错误。'122 UNION SELECT * FROM data'WHERE id = 122123RedLightHello

它正确地忽略了字符串的其余部分。

如果你想让你的代码容易受到SQL注入的攻击(你不想这样做!),你可以写

function test(id) {   /* danger: sql injection in next line */
  db.query("SELECT * FROM users WHERE id = " + id, (err, result) => { /* wrong ! */
    console.log(result[0]);
  });
}

这将发送

 SELECT * FROM users WHERE id = 122 UNION SELECT * FROM data

到服务器,并给你你的数据泄漏。

评论

0赞 O. Jones 1/30/2022
为什么SQL注入很危险?有关一些提示,请参阅 haveibeenpwned.com
0赞 Arcanus 1/30/2022
感谢您非常清晰和详细的解释。刚刚学到了很多东西,谢谢。