rails/rails — pull request #9207 by dylanahsmith (2013-02-07 10:38:03+00:00)
Title: active_record: Quote numeric values compared to string columns.

## Problem

The problem is described in [Potential Query Manipulation with Common Rails Practises](https://groups.google.com/forum/?hl=en&fromgroups=#!topic/rubyonrails-security/ZOdH5GH5jCU), which notes that "it is not possible for ActiveRecord to automatically protect against all instances of this attack". However, it is possible to handle the case where the column type is known.

For example:

```ruby
User.where(:login_token=>params[:token]).first
```
performs the query
```sql
SELECT * FROM `users` WHERE `login_token` = 0 LIMIT 1;
```
where it will match any login_token that starts with a non-digit character. But since active record can determine that login_token is a string type column, it can quote the integer it is being compared with as follows.

```sql
SELECT * FROM `users` WHERE `login_token` = '0' LIMIT 1;
```

which will have the desired affect of only matching the exact string '0'.

## Solution

Modify the connection adapter's `quote` method to quote the numeric value as a SQL string if the column it is being compared with is known to be non-numeric. Boolean values are represented as the integers 0 or 1 for some databases, so booleans are also quoted as SQL strings when comparing against a string type column.

The PredicateBuilder also needed to be modified to ensure that integers are quoted, since Arel treats them as literals. Quoting the integer and passing it to Arel as a `Arel::Nodes::SqlLiteral` object will ensure that the value is not double quoted.

## Limitations

SQL fragments with quoted values have no information about the column type, so the following is still unsafe.

```ruby
User.where("login_token = ?", params[:token])
```

The parameters to the SQL fragment should still be converted to the correct type before passing it to active record as follows.

```ruby
User.where("login_token = ?", params[:token].to_s)
```