Reputation: 9278
What are the Rails methods that are vulnerable to SQL injection, and in what form?
For example, I know that where
with a string argument is vulnerable:
Model.where("name = #{params[:name]}") # unsafe
But a parameterized string or hash is not:
Model.where("name = ?", params[:name]) # safe
Model.where(name: params[:name]) # safe
I'm mostly wondering about where
, order
, limit
and joins
, but would like to know about any other methods that might be attack vectors.
Upvotes: 4
Views: 679
Reputation: 9278
In Rails, where
, order
, limit
and joins
all have vulnerable forms. However, Rails limits the number of SQL operations performed to 1 so vulnerability is limited. An attacker cannot end a statement and execute a new arbitrary one.
Where
Where has one vulnerable form: string.
# string, unsafe
Model.where("name = '#{params[:name]}'")
# hash/parameterized string/array, safe
Model.where(name: params[:name])
Model.where("name = ?", params[:name])
Model.where(["name = ?", params[:name]])
Order
String form is vulnerable:
# unsafe
params[:order] = "1; --\n drop table users;\n --"
Model.order("#{params[:order]} ASC")
# safe
order_clause = sanitize(params[:order])
Model.order(order_clause)
Limit
Limit has no vulnerable forms, since Rails casts input to Integer beforehand.
Model.limit("1; -- \n SELECT password from users; -- ")
=> ArgumentError: invalid value for Integer(): "1; -- \n SELECT password from users; -- "
Joins
String form is vulnerable:
params[:table] = "WHERE false <> $1; --"
Model.where(:user_id => 1).joins(params[:table])
=> SELECT "models".* FROM "models" WHERE false <> $1 -- WHERE "models"."user_id" = $1 [["user_id", 1]]
Much more comprehensive information can be found at rails-sqli.org.
Upvotes: 4
Reputation: 1705
Generally: If you let the user input and save any text into your database, without escaping code, it could harm your system. Especially if these texts may contain tags/code snippets.
Upvotes: 2