2016-12-07 12 views
2

私はこのようなエクトクエリを構築しています:生のSQLをログに記録することはできますか?

from item in query, 
where: like(item.description, ^"%#{text}%") 

私は、これはtextでSQLインジェクションを可能にすることを心配。これを修正する前に、クエリが実際にデータベースにどのように送信されているかを確認したいと思います。

もし私がinspect the queryを見るか、または記録されているものを見ると、私はいくつかのSQLを見ますが、それは無効です。例えば

、クエリを検査することは私にこの示しています。私はコピーしてpsqlにそれを貼り付ける場合、

SELECT i0."id", i0."store_id", i0."title", i0."description" 
    FROM "items" AS i0 WHERE (i0."description" LIKE $1) ["%foo%"] 

しかし:私はRepo.allにこのクエリを渡すと、それはこれをログに記録

{"SELECT i0.\"id\", i0.\"store_id\", i0.\"title\", i0.\"description\" 
    FROM \"items\" AS i0 WHERE (i0.\"description\" LIKE $1)", 
["%foo%"]} 

をPostgreSQLは私にエラーを返します:

ERROR: 42P02: there is no parameter $1

oughエクトは、実際にこのように、parameterized queryをやっていることがあります。

PREPARE bydesc(text) AS SELECT i0."id", 
    i0."store_id", i0."title", i0."description" 
    FROM "items" AS i0 WHERE (i0."description" LIKE $1); 
EXECUTE bydesc('foo'); 

もしそうなら、私は、SQLインジェクションを防ぐだろうと思います。しかし、私はちょうどこれがEctoのことだと推測しています。

Ectoが実行している実際のSQLをどのように確認できますか?

答えて

7

Ectoはプリペアドステートメントのみを使用します。 ectoクエリ構文を使用する場合、SQLインジェクションを導入することはできません。問合せ構文はコンパイル時にSQLインジェクションが可能でないことを検証します。実行されたクエリが原因で夫婦の理由で困難であるかもしれない正確に表示

  • Postgrex(ひいてはエクトは)ので、PostgreSQLのバイナリプロトコルを(代わりに、最も一般的な、あまり効率的で、テキストプロトコルの)使用していますPREPAREクエリは実際には文字列として存在しません。
  • ほとんどの場合、最初に表示されるのはPREPARE 64237612638712636123(...) AS ...で、後ではEXECUTE 64237612638712636123(...)のように多くなりますが、これはあまり役に立ちません。 1つを別のものに関連づけようとすると恐ろしいことになります。

私の経験では、ほとんどの種類のソフトウェアは、システムの動作を理解するのに役立つので、準備文を使用して生のクエリではなくログに記録します。

+1

「クエリ構文には、SQLインジェクションが可能でないコンパイル時に検証します。」 Ectoが 'like(item.description、^"%#{text}% ")'をコンパイルするとき、 'text'のエスケープを追加すると言っていますか? PostgreSQLはプリペアドステートメントを使用しているだけなので、安全です。そうすれば、PostgreSQLは(例えば)単一の 'SELECT'と*' * SELECT'の後に 'DROP TABLE'を実行することを前もって知っていますか? –

+1

エスケープしません。パラメータを使用します。 '%foo%'は決してクエリの一部ではないので、クエリに何も挿入することはできません。それは、準備されたステートメントへのパラメータとして完全に別々に渡されます。 – michalmuskala

+1

また、プリペアドステートメントには1つのステートメントしか含めることができないので、 ' - ;のようなものを追加することはできません。 DROP TABLE' - postgresは2つの式を1つに入れようとしていると言っています。 – michalmuskala

3

はい、それはエクトによって実行される正確なSQLである(それは内部db_connectionパッケージにより調製クエリを使用する)およびNO SQLインジェクションは、そのコードに不可能です。

... 
log_statement = 'all' 
... 

、その後のPostgreSQLを再起動し、クエリを実行している:これはpostgresql.confalllog_statementを変更することで、すべての実行されたSQLクエリのログ記録をオンにすることで確認することができます。これは、ログに記録され

Repo.get(Post, 1) 
Repo.get(Post, 2) 

::次のクエリについて

LOG: execute ecto_818: SELECT p0."id", p0."title", p0."user_id", p0."inserted_at", p0."updated_at" FROM "posts" AS p0 WHERE (p0."id" = $1) 
DETAIL: parameters: $1 = '1' 
LOG: execute ecto_818: SELECT p0."id", p0."title", p0."user_id", p0."inserted_at", p0."updated_at" FROM "posts" AS p0 WHERE (p0."id" = $1) 
DETAIL: parameters: $1 = '2' 
関連する問題