2017-08-24 28 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樣式參數插入,以防止注入攻擊。