Clearance 0.16.3 fixes a password reset vulnerability

Mike Burns

The new release of Clearance works around the latest Rails SQL injection. Upgrade to Clearance 0.16.3 for the security fix.

gem 'clearance', '~> 0.16.3'

Background

In Clearance we generate a confirmation_token when you forget your password, and clear it when you successfully reset your password. In the controller we find the user like this:

@user = User.find_by_id_and_confirmation_token(params[:user_id], params[:token])

This approximately translates to this ARel query:

User.where(:id => params[:user_id], :confirmation_token => params[:token])

Normally this generates perfectly safe SQL:

SELECT users.*
FROM users
WHERE users.id = 1
AND users.confirmation_token = 'hello'
LIMIT 1

Exploit

If params[:token] is a list with one nil element, the generated SQL is closer to this:

SELECT users.*
FROM users
WHERE users.id = 1
AND users.confirmation_token IS NULL
LIMIT 1

That is, if you can get params[:token] to produce [nil] then you can become any user without a confirmation_token.

Prior to Rails 3.2.5, this URL would generate [nil]:

/users/1/password/edit?token[]

We catch this in Clearance now.

Fix

Upgrade to Clearance 0.16.3. If you are using Rails 3.2.5 or above then you do not need to upgrade Clearance to get this fix.

Acknowledgements

Thank you to Ben Murphy for bringing this to our attention in a professional manner, and to the Rails team for fixing it quickly.