Rails 6 has been out since December 2019, but sadly the site has been missing information about changes and new methods in Rails 6.
As that deficiency has recently been rectified, let’s walk through what has changed since Rails 5!
In earlier versions of Rails,
destroy_all could be passed a string of raw SQL.
In Rails 6, these two methods no longer accept any arguments.
Instead, you can use…
This means they are vulnerable to the same kind of SQL injection.
Resulting query that deletes all users:
Since Rails did not offer an easy way of setting sort direction, this kind of code was common:
In Rails 6.0, injection attempts would raise a deprecation warning:
Starting with Rails 6.1, some logic to check the arguments to
order. If the arguments do not appear to be column names or sort order, they will be rejected:
1 2 3 4
It is still possible to inject additional columns to extract some information from the table, such as number of columns or names of the columns:
pluck pulls out specified columns from a query, instead of loading whole records.
In previous versions of Rails,
pluck (somewhat surprisingly!) accepted arbitrary SQL strings if they were passed in as an array.
reorder, Rails 6.0 started warning about this:
In Rails 6.1,
pluck now only accepts attribute names!
Rails 6 introduced
reselect, which allows one to completely replace the
SELECT clause of a query. Like
select, it accepts any SQL string. Since
SELECT is at the very beginning of the SQL query, it makes it a great target for SQL injection.
Note this selects all columns from a different table:
rewhere is analogous to
reselect but it replaces the
where, it is very easy to open up
rewhere to SQL injection.
Any other new methods that allow SQL injection? Let me know!
Want to find out more?