HexBrain

Ruby on Rails · Report #139321

Unsafe Query Generation (CVE-2012-2660, CVE-2012-2694 and CVE-2013-0155) mitigation bypass

Validstatus
7upvotes
7 Feb 2018disclosed

Summary

Unsafe Query Generation Risk in Active Record

There is a vulnerability when Active Record is used in conjunction with JSON parameter parsing. This vulnerability has been assigned the CVE identifier CVE-2016-6317. This vulnerability is similar to CVE-2012-2660, CVE-2012-2694 and CVE-2013-0155.

Versions Affected: >= 4.2.0 Not affected: < 4.2.0, >= 5.0.0 Fixed Versions: 4.2.7.1

Impact

Due to the way Active Record interprets parameters in combination with the way that JSON parameters are parsed, it is possible for an attacker to issue unexpected database queries with "IS NULL" or empty where clauses. This issue does not let an attacker insert arbitrary values into an SQL query, however they can cause the query to check for NULL or eliminate a WHERE clause when most users wouldn't expect it.

For example, a system has password reset with token functionality:

unless params[:token].nil? 
  user = User.find_by_token(params[:token]) 
  user.reset_password! 
end 

An attacker can craft a request such that params[:token] will return [nil]. The [nil] value will bypass the test for nil, but will still add an "IN ('xyz', NULL)" clause to the SQL query.

Similarly, an attacker can craft a request such that params[:token] will return an empty hash. An empty hash will eliminate the WHERE clause of the query, but can bypass the nil? check.

Note that this impacts not only dynamic finders (find_by_*) but also relations (User.where(:name => params[:name])).

All users running an affected release should either upgrade or use one of the work arounds immediately. All users running an affected release should upgrade immediately. Please note, this vulnerability is a variant of CVE-2012-2660, CVE-2012-2694, and CVE-2013-0155. Even if you upgraded to address those issues, you must take action again.

If this chance in behavior impacts your application, you can manually decode the original values from the request like so:

ActiveSupport::JSON.decode(request.body) 

Releases

The FIXED releases are available at the normal locations.

Workarounds

This problem can be mitigated by casting the parameter to a string before passing it to Active Record. For example:

unless params[:token].nil? || params[:token].to_s.empty? 
  user = User.find_by_token(params[:token].to_s) 
  user.reset_password! 
end 

Patches

To aid users who aren't able to upgrade immediately we have provided patches for the two supported release series. They are in git-am format and consist of a single changeset.

  • 4-2-unsafe-query-generation.patch - Patch for 4.2 series

Please note that only the 5.0.x and 4.2.x series are supported at present. Users of earlier unsupported releases are advised to upgrade as soon as possible as we cannot guarantee the continued availability of security fixes for unsupported releases.

Credits

Thanks to joernchen of Phenoelit for reporting this!

How it was found

The write-up for this report has not been downloaded yet, or the program disclosed it without one. Read it on HackerOne.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original