4

ActiveRecord を使用して適切なクエリを作成する方法をまだ学んでいます。クエリで日付フィールドを使用している方法が原因で、このクエリが sql インジェクションの対象になるかどうかに興味があります。

明らかな間違いや、このクエリを書くためのより良い方法を誰かが指摘できますか?

@arrangements_for_month =
  Arrangement.joins(:timeslot).
              where("timeslots.timeslot BETWEEN '#{month}' AND '#{month.end_of_month}'", params[:id]).
              order('location_id')
4

2 に答える 2

8

安全のために、パラメータを含めるための推奨される方法を使用する必要があります。このガイドをチェックしてください:

純粋な文字列として独自の条件を構築すると、SQLインジェクションのエクスプロイトに対して脆弱になる可能性があります。たとえば、Client.where("first_name LIKE '%#{params[:first_name]}%'")安全ではありません。配列を使用して条件を処理するための推奨される方法については、次のセクションを参照してください。

試す:

@arrangements_for_month = Arrangement.joins(:timeslot)
  .where("timeslots.timeslot BETWEEN ? AND ?", month, month.end_of_month)
  .order('location_id')

リンクされたガイドのそのセクションで説明されているように、必要に応じて、ルビー範囲を使用してそのような範囲条件を定義する別の方法があります。

Client.where(:created_at => (Time.now.midnight - 1.day)..Time.now.midnight)

したがって、コードについて他に何も知らなくても、おそらく次のようなことができます。

@arrangements_for_month = Arrangement.joins(:timeslot)
  .where("timeslots.timeslot" => month .. month.end_of_month)
  .order('location_id')
于 2013-03-14T01:19:15.137 に答える
6

はい、そうです。ユーザーの入力をクエリ文字列に挿入するたびに、脆弱性があります。になる場合month

5' AND '8'; DROP TABLE timeslots;--

あなたは深刻な問題を抱えているかもしれません。ドロップデータベースなどは言うまでもありません。

私はこのクエリを正確に再現していませんが、acts_as_paranoidプラグインを使用しているため、クエリに似たようなもの[追加する必要がありました]:

SomeModel.pluck(:id)
 => [1, 2, 4, 3, 5, 6]

abc = 'a\');delete from some_models where id=6;--'
User.where("name = '#{abc}'")
 => []

SomeModel.pluck(:id)
 => [1, 2, 4, 3, 5] # please note that record with id 6 was deleted!

攻撃が可能だった理由は、私が提供できた'からです--(コメントを開始します)。提案された方法を使用する場合、つまり.where( "name =?"、 "my_name")を使用する場合、攻撃は不可能です。これをチェックしてください:

abc = 'a\');delete from some_models where id=5;--'

User.where("name = ?", abc)
 => []

SomeModel.pluck(:id)
 => [1, 2, 4, 3, 5] # this time record with id 5 was not deleted

これは最初のクエリです:

 User Load (1.5ms)  SELECT "users".* FROM "users" WHERE ("users"."deleted_at" IS NULL) AND (name = 'a');delete from some_models where id=6;--')

これは2番目です

  User Load (1.0ms)  SELECT "users".* FROM "users" WHERE ("users"."deleted_at" IS NULL) AND (name = 'a'');delete from some_models where id=5;--')

2番目の追加に注意してください'-query(name = 'a'')

于 2013-03-14T01:24:49.453 に答える