Reputation: 1456
I am using ruby 1.8.7 and rails 2.3.2
The following code is prone to sql injection
params[:id] = "1) OR 1=1--"
User.delete_all("id = #{params[:id]}")
My question is by doing the following will be the best solution to avoid sql injection or not. If not then what is the best way to do so?
User.delete_all("id = #{params[:id].to_i}")
Upvotes: 0
Views: 321
Reputation: 3031
The other answers answer this well for Rails and it'll work fine if you follow their suggestions. In a more generic setting when you have to handle this yourself you can typically use a regular expression to extract a value that's in an expected format. This is really simple with an integer id. Think of it like this:
if params[:id] =~ /(\d+)/
safe_id = $1.to_i
# do something with safe_id now
end
That gets a little more complicated when you're handling strings and arbitrary data. If you have to handle such data then you can use the quoting methods available for the database adapters. In Rails this is ultimately rolled into a consistent interface:
safe_string = ActiveRecord::Base.connection.quote(unsafe_string)
For most database systems this will handle single quotes and backslashes in a special manner.
If you're outside of Rails you will have to use the quoting methods specific to your database adapter, but usage is quite similar.
The takeaway:
Upvotes: 1
Reputation: 3347
Use the rails methods to pass your where
options. You can always hardcode them, as in the example that you give, but the usual way would be something like:
User.where(:id => params[:id]).delete_all
User.where("id = ?", params[:id]).delete_all
User.where("id = :id", :id => params[:id]).delete_all
They are well tested and in case a new vulnerability is detected, an update will fix the problem and your code will not need to be changed.
By the way, if you just want to delete 1 record based on its id, what I would do is:
User.find(params[:id]).destroy
Upvotes: 0
Reputation: 115511
What about:
User.where(id: params[:id]).delete_all
Ok sorry for Rails 2.x its:
User.delete_all(["id = ?", params[:id]])
Btw, be sure you want to use delete_all
instead of destroy_all
, the former doesn't trigger callbacks.
Upvotes: 2