参数化动态查询/SQL卫生NodeJS
Parameterized Dynamic Queries / SQL Sanitation NodeJS
我是 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 注射到您需要的地方。例如,在这个声明中你应该有注入保护,而你没有。这是它应该是什么样子的示例:
filter += name !== undefined ? ` AND a.name LIKE '%${SqlString.escape(name)}%'` : '';
name
大概是用户输入变量,此时您需要防止 SQL 注入。所有用户输入变量都需要 SQL 注入保护 直接应用到它们 。
在你已经用变量构造了一个 SQL 片段之后,你绝对不能提供 SQL 注入保护。当您构建 filter
SQL 片段然后尝试稍后插入它时,您在做什么...实际上您在进行有意的 SQL 注入。
免责声明:与这种转义式保护相比,使用准备好的语句(或等效技术)您将获得更高级别的保护。逃逸风格保护是针对 SQL 注入攻击的最低保护级别,您可以使用它并且仍然有任何保护。
免责声明 2: 允许用户输入部分 table 名称也可能非常危险,并且很难正确转义。
例如,假设您有一堆 table,从 tbl_foo_1
到 tbl_foo_99
。并且您希望您的用户可以访问所有这些。但是,如果后来有人添加了 tbl_foo_secret
会怎样?你猜怎么着?您的用户也可以访问它,因为您让他们选择自己的 table 名称。或者,如果您添加整个模式 tbl_foo_top_secret
会怎样?他们可以很容易地告诉您 table 后缀是 tbl_foo_top_secret.table_name
,并且您的代码会很好地接受它,因为在这个库中 句点不会被转义 。因此,您可能希望添加自己的自定义检查以确保 table 名称后缀是 acceptable.
我是 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 注射到您需要的地方。例如,在这个声明中你应该有注入保护,而你没有。这是它应该是什么样子的示例:
filter += name !== undefined ? ` AND a.name LIKE '%${SqlString.escape(name)}%'` : '';
name
大概是用户输入变量,此时您需要防止 SQL 注入。所有用户输入变量都需要 SQL 注入保护 直接应用到它们 。
在你已经用变量构造了一个 SQL 片段之后,你绝对不能提供 SQL 注入保护。当您构建 filter
SQL 片段然后尝试稍后插入它时,您在做什么...实际上您在进行有意的 SQL 注入。
免责声明:与这种转义式保护相比,使用准备好的语句(或等效技术)您将获得更高级别的保护。逃逸风格保护是针对 SQL 注入攻击的最低保护级别,您可以使用它并且仍然有任何保护。
免责声明 2: 允许用户输入部分 table 名称也可能非常危险,并且很难正确转义。
例如,假设您有一堆 table,从 tbl_foo_1
到 tbl_foo_99
。并且您希望您的用户可以访问所有这些。但是,如果后来有人添加了 tbl_foo_secret
会怎样?你猜怎么着?您的用户也可以访问它,因为您让他们选择自己的 table 名称。或者,如果您添加整个模式 tbl_foo_top_secret
会怎样?他们可以很容易地告诉您 table 后缀是 tbl_foo_top_secret.table_name
,并且您的代码会很好地接受它,因为在这个库中 句点不会被转义 。因此,您可能希望添加自己的自定义检查以确保 table 名称后缀是 acceptable.