Check attributes passed to create_with and where

If the request parameters are passed to create_with and where they can
be used to do mass assignment when used in combination with
Relation#create.

Fixes CVE-2014-3514
This commit is contained in:
Rafael Mendonça França 2014-08-06 21:17:19 -03:00
parent 7c4bfe1c95
commit 9456990b14
3 changed files with 45 additions and 2 deletions

View File

@ -23,5 +23,6 @@ module ActiveModel
attributes
end
end
alias :sanitize_forbidden_attributes :sanitize_for_mass_assignment
end
end

View File

@ -1,9 +1,12 @@
require 'active_support/core_ext/array/wrap'
require 'active_model/forbidden_attributes_protection'
module ActiveRecord
module QueryMethods
extend ActiveSupport::Concern
include ActiveModel::ForbiddenAttributesProtection
# WhereChain objects act as placeholder for queries in which #where does not have any parameter.
# In this case, #where must be chained with #not to return a new relation.
class WhereChain
@ -561,7 +564,10 @@ module ActiveRecord
if opts == :chain
WhereChain.new(self)
else
references!(PredicateBuilder.references(opts)) if Hash === opts
if Hash === opts
opts = sanitize_forbidden_attributes(opts)
references!(PredicateBuilder.references(opts))
end
self.where_values += build_where(opts, rest)
self
@ -711,7 +717,13 @@ module ActiveRecord
end
def create_with!(value) # :nodoc:
self.create_with_value = value ? create_with_value.merge(value) : {}
if value
value = sanitize_forbidden_attributes(value)
self.create_with_value = create_with_value.merge(value)
else
self.create_with_value = {}
end
self
end

View File

@ -66,4 +66,34 @@ class ForbiddenAttributesProtectionTest < ActiveRecord::TestCase
person = Person.new
assert_nil person.assign_attributes(ProtectedParams.new({}))
end
def test_create_with_checks_permitted
params = ProtectedParams.new(first_name: 'Guille', gender: 'm')
assert_raises(ActiveModel::ForbiddenAttributesError) do
Person.create_with(params).create!
end
end
def test_create_with_works_with_params_values
params = ProtectedParams.new(first_name: 'Guille')
person = Person.create_with(first_name: params[:first_name]).create!
assert_equal 'Guille', person.first_name
end
def test_where_checks_permitted
params = ProtectedParams.new(first_name: 'Guille', gender: 'm')
assert_raises(ActiveModel::ForbiddenAttributesError) do
Person.where(params).create!
end
end
def test_where_works_with_params_values
params = ProtectedParams.new(first_name: 'Guille')
person = Person.where(first_name: params[:first_name]).create!
assert_equal 'Guille', person.first_name
end
end