Providing security resources for the Ruby community.
Follow us @rubysec or email us via info at

Advisory Archive


gem: activerecord
date: 2016-01-25
cve: 2015-7577
title: Nested attributes rejection proc bypass in Active Record
description: "There is a vulnerability in how the nested attributes feature in Active
  Record \nhandles updates in combination with destroy flags when destroying records
  is \ndisabled. This vulnerability has been assigned the CVE identifier CVE-2015-7577.
  \n\nVersions Affected:  3.1.0 and newer \nNot affected:       3.0.x and older \nFixed
  Versions:     5.0.0.beta1.1,,, \n\nImpact \n------ \nWhen
  using the nested attributes feature in Active Record you can prevent the \ndestruction
  of associated records by passing the `allow_destroy: false` option \nto the `accepts_nested_attributes_for`
  method. However due to a change in the \ncommit [a9b4b5d][1] the `_destroy` flag
  prevents the `:reject_if` proc from \nbeing called because it assumes that the record
  will be destroyed anyway. \n\nHowever this isn't true if `:allow_destroy` is false
  so this leads to changes \nthat would have been rejected being applied to the record.
  Attackers could use \nthis do things like set attributes to invalid values and to
  clear all of the \nattributes amongst other things. The severity will be dependent
  on how the \napplication has used this feature. \n\nAll users running an affected
  release should either upgrade or use one of \nthe workarounds immediately. \n\nReleases
  \n-------- \nThe FIXED releases are available at the normal locations. \n\nWorkarounds
  \n----------- \nIf you can't upgrade, please use the following monkey patch in an
  initializer \nthat is loaded before your application: \n\n``` \n$ cat config/initializers/nested_attributes_bypass_fix.rb
  \nmodule ActiveRecord \n  module NestedAttributes \n    private \n\n    def reject_new_record?(association_name,
  attributes) \n      will_be_destroyed?(association_name, attributes) || call_reject_if(association_name,
  attributes) \n    end \n\n    def call_reject_if(association_name, attributes) \n
  \     return false if will_be_destroyed?(association_name, attributes) \n\n      case
  callback = self.nested_attributes_options[association_name][:reject_if] \n      when
  Symbol \n        method(callback).arity == 0 ? send(callback) : send(callback, attributes)
  \n      when Proc \n \n      end \n    end \n\n
  \   def will_be_destroyed?(association_name, attributes) \n      allow_destroy?(association_name)
  && has_destroy_flag?(attributes) \n    end \n\n    def allow_destroy?(association_name)
  \n      self.nested_attributes_options[association_name][:allow_destroy] \n    end
  \n  end \nend \n``` \n\nPatches \n------- \nTo aid users who aren't able to upgrade
  immediately we have provided patches for \nthe two supported release series. They
  are in git-am format and consist of a \nsingle changeset. \n\n* 3-2-nested-attributes-reject-if-bypass.patch
  - Patch for 3.2 series \n* 4-1-nested-attributes-reject-if-bypass.patch - Patch
  for 4.1 series \n* 4-2-nested-attributes-reject-if-bypass.patch - Patch for 4.2
  series \n* 5-0-nested-attributes-reject-if-bypass.patch - Patch for 5.0 series \n\nPlease
  note that only the 4.1.x and 4.2.x series are supported at present. Users \nof earlier
  unsupported releases are advised to upgrade as soon as possible as we \ncannot guarantee
  the continued availability of security fixes for unsupported \nreleases. \n\nCredits
  \n------- \nThank you to Justin Coyne for reporting the problem and working with
  us to fix it. \n\n[1]:
- "~> 3.0.0"
- "< 3.0.0"
- "~> 5.0.0.beta1.1"
- "~> 4.2.5, >="
- "~> 4.1.14, >="
- "~>"