javascript - 参数化动态查询/SQL 清理 NodeJS

标签 javascript mysql node.js sql-injection

我是 node 的新手,对使用 sqlstring 的动态参数化查询有疑问。

以下代码的问题在于,过滤器是可选的,具体取决于用户传递给函数的内容,因此它们的顺序可以更改(因此很难分别传递每个过滤器参数)。据我所知,Sqlstring 使用顺序来确定哪些参数与正确的问号匹配。

所以我只剩下一次将所有过滤器传递给 Sqlstring,但是如果没有过滤器处于事件状态,那么我只剩下一个用于过滤器变量的空字符串,这将引发 sql 语法错误。

let filter = idList !== '' ? ` AND id IN(${idList})` : '';
filter += locationsList !== '' ? ` AND a.locationID IN(${locationsList})` : '';
filter += start !== undefined ? ` AND a.lastEdited >= ${start}` : '';
filter += end !== undefined ? ` AND a.lastEdited <= ${end}` : '';
filter += name !== undefined ? ` AND a.name LIKE '%${name}%'` : '';

const qry = `
SELECT
a.id 'id'
,a.number 'number'
,a.name 'name'
,a.locationID 'locationID'
,a.location 'location'
,a.lastEdited 'lastEdited'
,a.userID 'owner'
FROM tbl_foo_${'?'} a
WHERE a.id > ${'?'} ${'?'} LIMIT ${'?'};`;

let values = [ id, cursor, filter, limit ];

const rows = query(db, qry, values);

//inside of the query function it does this and then runs the query against the database
if (qry.includes('?')) {
sanitizedQry = sqlstring.format(qry, values);
}

它产生的查询看起来像这样:

SELECT
a.id 'id'
,a.number 'number'
,a.name 'name'
,a.locationID 'locationID'
,a.location 'location'
,a.lastEdited 'lastEdited'
,a.userID 'owner'
FROM tbl_foo_36 a
WHERE a.id > 1 '' LIMIT 100;

有更好的方法吗?

最佳答案

如果你看一下 sqlstring npm page ,关于 SqlString.format 是这样说的:

This looks similar to prepared statements in MySQL, however it really just uses the same SqlString.escape() method internally.

如果适本地使用 SqlString.escape,您会变得更好。

但问题是,您没有在需要的地方防止 SQL 注入(inject)。例如,在这个声明中你应该有注入(inject)保护,但你没有。下面是它应该是什么样子的示例:

filter += name !== undefined ? ` AND a.name LIKE '%${SqlString.escape(name)}%'` : '';

name 大概是用户输入变量,此时您需要防止 SQL 注入(inject)。所有用户输入变量都需要直接应用 SQL 注入(inject)保护。

在您已经使用变量构建 SQL 片段之后,您绝对不能提供 SQL 注入(inject)保护。当您构建您的 filter SQL 片段然后尝试稍后插入它时,您在做什么……这实际上是您在进行有意的 SQL 注入(inject)。

免责声明:使用准备好的语句(或等效技术),您将获得比这种转义式保护更高级别的保护。转义式保护是针对 SQL 注入(inject)攻击的最低级别的保护,您可以使用它并且仍然有任何保护。

免责声明 2: 允许用户输入部分表名也可能非常危险,并且很难正确转义。

例如,假设您有一堆表,tbl_foo_1tbl_foo_99。并且您希望您的用户可以访问所有这些。但是,如果后来有人添加了一个 tbl_foo_secret 会怎样?你猜怎么了?您的用户也可以访问它,因为您让他们选择自己的表名。或者,如果您添加整个架构 tbl_foo_top_secret 会怎么样?他们可以很容易地告诉您表后缀是 tbl_foo_top_secret.table_name,并且您的代码会很好地接受它,因为在这个库中不会转义句点。因此,您可能希望添加自己的自定义检查以确保表名后缀是可接受的。

关于javascript - 参数化动态查询/SQL 清理 NodeJS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57382704/

相关文章:

php - Codeigniter 隐藏窗体变为 NULL

python - mysql 百万行数据从一张表导入到另一张表

node.js - 使用 perf_events 的 nodejs/v8 火焰图中的未知事件

javascript - 使用 Javascript 动画库 VS 创建要在标题中注入(inject)的动态 &lt;style&gt; 标签

javascript - 提示调用函数中的方法失败

Mysql循环遍历选中的列,在循环中执行Insert查询

javascript - 如何找到本地安装的npm模块依赖于某个模块?

javascript - 如何使用 Javascript 中的括号表示法访问对象的深层属性

javascript - 全局函数中的 Angular.js 依赖注入(inject)

javascript - 为什么在传递给函数时不解释 bool false 参数?