2017-08-24 6 views
3

私はpg-promiseでデータベースクエリを書いています。私のテーブルは次のようになります。私はsettingにいくつかの値を挿入したいハードコードされた値と変数の値を混在させて挿入しないでください。

​​

- 3ハードコードされており、一つは私が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取得:

をそれは二重引用符で 2を入れているので、私は推測
var q = "INSERT INTO setting (user_id, visualisation_id, template_id) (" + 
     "SELECT $1~, $2~, template_id, $3~ FROM visualisation WHERE id = $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 FRAME visualization WHERE id = $ 2)、$ 3) " –

+0

ここで@VaoTsunは正しいと思います。また、動的な列名を使用していないため、SQL Namesは何もしません。 –

+0

ありがとう。最初の例では、内部クエリが動的な列名を使用するため、ユーザーが '$ 1'の代わりにSQLを供給して潜在的にSQLインジェクションを達成できなかったでしょうか? (私は脆弱性のために既存のコードをチェックしています) – Richard

答えて

2

あなたの質問は結構です。私はあなたが値プレースホルダ($ Xパラメータ)とSQL名を知っていると思うが、あなたはちょっと混乱している。

クエリでは、プレースホルダにのみ値を割り当てます。データベースドライバは、適切なエスケープと変数の置換を提供して、それらを処理します。

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文が本当の種類を識別するのに十分なコンテキストを提供すると思う:

documentation

氏は述べています。

一方、クエリをディナミカルに構築する場合は、SQL Namesを使用する必要があります。たとえば、列名や表名を変更できます。 $1~または$1:nameのスタイルパラメータを使用して挿入する必要があります。

関連する問題