2017-08-24 31 views
3

我正在用pg-promise写数据库查询。我的表是这样的:插入混合硬编码和变量值时避免SQL注入?

​​

我想一些值插入到setting - 三个都是硬编码的,和一个我需要从visualisation抬头。

下面的语句做什么,我需要的,但必须受到SQL注入攻击:

var q = "INSERT INTO setting (user_id, visualisation_id, template_id) (" + 
     "SELECT $1, $2, template_id, $3 FROM visualisation WHERE id = $2)"; 
conn.query(q, [2, 54, 'foo']).then(data => { 
    console.log(data); 
}); 

我知道我应该使用SQL names,但如果我尝试使用它们如下我得到TypeError: Invalid sql name: 2

var q = "INSERT INTO setting (user_id, visualisation_id, template_id) (" + 
     "SELECT $1~, $2~, template_id, $3~ FROM visualisation WHERE id = $2)"; 

我猜这不奇怪,因为它把2放在双引号中,所以SQL认为它是一个列名。

,如果我尝试重写使用VALUES我也得到一个语法错误的查询:

var q = "INSERT INTO setting (user_id, visualisation_id, template_id) VALUES (" + 
     "$1, $2, SELECT template_id FROM visualisation WHERE id = $2, $3)"; 

什么是插入硬编码的变量值的组合的最佳方式,同时避免了SQL注入风险?

+1

使用查询作为值,将其作为子查询的括号,例如'“$ 1,$ 2,(SELECT template_id FROM visualization WHERE id = $ 2),$ 3)”' –

+0

我认为@VaoTsun在这里是正确的。而SQL名称在这里没有什么可做的,因为你没有使用动态列名。 –

+0

谢谢。在第一个例子中,用户不能提供一些SQL来代替'$ 1'并且可能实现SQL注入,因为内部查询使用动态列名? (我正在检查现有代码是否存在漏洞。) – Richard

回答

2

您的查询完好无损。我想你也知道值占位符($ X参数)和SQL名称,但你有点困惑。

在您的查询中,您只将值分配给占位符。数据库驱动程序将为您处理它们,提供适当的转义和变量替换。

documentation说:

When a parameter's data type is not specified or is declared as unknown, the type is inferred from the context in which the parameter is used (if possible).

我找不到,指出什么是默认类型的来源,但我认为INSERT语句提供了足够的上下文,以确定真正的类型。

另一方面,当您建立您的查询dinamically时,你必须使用SQL Names。例如,你有可变的列或表名称。它们必须通过$1~$1:name样式参数插入,以防止注入攻击。