I'm still learning how to write good queries using ActiveRecord. I'm curious if this query is subject to sql injection because of the way i'm using the date field in the query.
Can someone please point out any obvious mistakes or any better ways to write this query?
@arrangements_for_month =
Arrangement.joins(:timeslot).
where("timeslots.timeslot BETWEEN '#{month}' AND '#{month.end_of_month}'", params[:id]).
order('location_id')
You should just use the preferred way of including parameters to be safe. Check out this guide:
Building your own conditions as pure strings can leave you vulnerable to SQL injection exploits. For example,
Client.where("first_name LIKE '%#{params[:first_name]}%'")
is not safe. See the next section for the preferred way to handle conditions using an array.
Try:
@arrangements_for_month = Arrangement.joins(:timeslot)
.where("timeslots.timeslot BETWEEN ? AND ?", month, month.end_of_month)
.order('location_id')
And just a heads up, if you like, there is an alternative way to define a range condition like that using ruby ranges, as described in that section of the linked guide:
Client.where(:created_at => (Time.now.midnight - 1.day)..Time.now.midnight)
So, without knowing anything else about your code, you can probably do something like this:
@arrangements_for_month = Arrangement.joins(:timeslot)
.where("timeslots.timeslot" => month .. month.end_of_month)
.order('location_id')
yes it is. Everytime you insert user's input into the query string, it is vulnerable. If month
will be :
5' AND '8'; DROP TABLE timeslots;--
you might be in serious troubles. Not to mention drop database etc.
I haven't reproduced exactly this query, but something similar [ I had to add ) in my query due to using acts_as_paranoid plugin ]:
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!
The reason why the attack was possible, is that I could provide '
and --
( which starts comment ). When yo use the suggested way, i.e. using .where("name = ?", "my_name"), then the attack would not be possible. Check this out:
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
This is first query:
User Load (1.5ms) SELECT "users".* FROM "users" WHERE ("users"."deleted_at" IS NULL) AND (name = 'a');delete from some_models where id=6;--')
This is the second
User Load (1.0ms) SELECT "users".* FROM "users" WHERE ("users"."deleted_at" IS NULL) AND (name = 'a'');delete from some_models where id=5;--')
Note the additional '
in the second - query(name = 'a'')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With