正确插入表名

Posted

技术标签:

【中文标题】正确插入表名【英文标题】:Proper insertion of table name 【发布时间】:2016-10-07 18:52:03 【问题描述】:

如果可以动态确定名称并且仍然可以防止SQL注入攻击,如何正确提供表名?我正在使用node-postgres。

例如:

以下工作,但我认为不安全:

dbclient.query("INSERT INTO " + table_name + " VALUES ($1, $2, $3)", [value_a, value_b, value_c])`

我想要的等效(但不起作用)是:

dbclient.query("INSERT INTO $1 VALUES ($2, $3, $4)", [table_name, value_a, value_b, value_c])`

【问题讨论】:

根据github.com/brianc/node-postgres/issues/1426,在postgres中是不可能的 【参考方案1】:

如果表名使用正则表达式某些其他验证逻辑,您可以手动检查有效性。我可能会使用包含允许的表名的字典。

var tables = users:'users', boats:'boats';
table_name = tables[table_name];
if (! table_name) throw new Error();
dbclient.query("INSERT INTO " + table_name + " VALUES ($1, $2, $3)", [value_a, value_b, value_c])

如果您计划生成大量动态 sql,请使用查询构建器,例如 http://knexjs.org/

【讨论】:

我建议您改用 table_name = tables.hasOwnProperty(table_name) ? tables[table_name] : null - 没有用户可以提供的 hasOwnProperty 检查,例如 table_name = 'toString',这会导致意外错误。【参考方案2】:

有一个哈希let tables = tableName1: 'table_name1', tableName2: 'table_name2'... 然后

//assuming you receive t as table name input
if(tables[t])
  //build SQL query with tables[t] as the table name
else
  //throw error about non-existing table

这样,您可以控制数据库中的实际表名。

另外,不要忘记清除所有输入 - 这些值可能包含注入。

【讨论】:

注入攻击对于这种现有的哈希查找会是什么样子?【参考方案3】:

任何好的库都应该为 SQL 名称提供适当的转义,包括:

架构名称 表名 列名

例如,在pg-promise 中,您可以这样使用它:

db.query("INSERT INTO $1~ VALUES ($2, $3, $4)", [table_name, value_a, value_b, value_c])

即您可以通过在变量后面附加~ 来正确转义您的表名,从而使其免受 SQL 注入的影响。

来自here,库执行的表名的简单转义:

return '"' + name.replace(/"/g, '""') + '"';

另见:SQL Names

【讨论】:

【参考方案4】:

您可以使用pg-escape npm 模块中的escape 函数来引用表名等标识符:

只使用转义函数:

escape("INSERT INTO %I VALUES (%L, %L, %L)", table_name, value_a, value_b, value_c);

结合节点postgres:

dbclient.query(escape("INSERT INTO %I VALUES ($2, $3, $4)", table_name), [value_a, value_b, value_c]);

【讨论】:

以上是关于正确插入表名的主要内容,如果未能解决你的问题,请参考以下文章

如果插入查询执行完成,则更改表名

在 oracle 中批量插入时表名无效

在触发器函数中插入动态表名

SQL Server:使用动态表名插入存储过程

influxdb插入语句怎么自动区分表名,tag,field,

从子查询中获取表名以在一行中用于 Oracle 中的删除/更新/插入子句