Aaron Patterson (tenderlove) reports: Object taint bypassing in DL and Fiddle in Ruby There is a vulnerability in DL and Fiddle in Ruby where tainted strings can be used by system calls regardless of the $SAFE level set in Ruby. This vulnerability has been assigned the CVE identifier CVE-2013-2065. Versions Affected: 1.9.3-pX, 2.0.0-p0 Not affected: 1.8.X Fixed Versions: 1.9.3-pX, 2.0.0-pX Impact ------ Native functions exposed to Ruby with DL or Fiddle do not check the taint values set on the objects passed in. This can result in tainted objects being accepted as input when a SecurityError exception should be raised. Impacted DL code will look something like this: def my_function(user_input) handle = DL.dlopen(nil) sys_cfunc = DL::CFunc.new(handle['system'], DL::TYPE_INT, 'system') sys = DL::Function.new(sys_cfunc, [DL::TYPE_VOIDP]) sys.call user_input end $SAFE = 1 my_function "uname -rs".taint Impacted Fiddle code will look something like this: def my_function(user_input) handle = DL.dlopen(nil) sys = Fiddle::Function.new(handle['system'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT) sys.call user_input end $SAFE = 1 my_function "uname -rs".taint All users running an affected release should either upgrade or use one of the work arounds immediately. Note that this *does not* prevent numeric memory offsets from being used as pointer values. Numbers cannot be tainted, so code passing a numeric memory offset cannot be checked. For example: def my_function(input) handle = DL.dlopen(nil) sys = Fiddle::Function.new(handle['system'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT) sys.call input end $SAFE = 1 user_input = "uname -rs".taint my_function DL::CPtr[user_input].to_i In this case, the memory location is passed, and taintedness of the object cannot be determined by DL / Fiddle. In this case, please check the tainting of the user input before passing the memory location: user_input = "uname -rs".taint raise if $SAFE >= 1 && user_input.tainted? my_function DL::CPtr[user_input].to_i Releases -------- The FIXED releases are available at the normal locations. Workarounds ----------- This monkey patch can be used as a workaround: class Fiddle::Function alias :old_call :call def call(*args) if $SAFE >= 1 && args.any? { |x| x.tainted? } raise SecurityError, "tainted parameter not allowed" end old_call(*args) end 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. * 1-9-fiddle-tainting.patch - Patch for 1.9 series * 2-0-fiddle-tainting.patch - Patch for 2.0 series
Created attachment 746494 [details] 1-9-fiddle-tainting-CVE-2013-2065.patch
Created attachment 746495 [details] 2-0-fiddle-tainting-CVE-2013-2065.patch
External References: http://www.ruby-lang.org/en/news/2013/05/14/taint-bypass-dl-fiddle-cve-2013-2065/
Created ruby tracking bugs for this issue Affects: fedora-all [bug 962862]
Vulnerable versions are: * All ruby 1.9 versions prior to ruby 1.9.3 patchlevel 426 * All ruby 2.0 versions prior to ruby 2.0.0 patchlevel 195 * prior to trunk revision 40728 Non vulnerable versions are: * ruby 1.8 versions are not affected.
ruby-2.0.0.195-8.fc19 has been pushed to the Fedora 19 stable repository. If problems still persist, please make note of it in this bug report.
Acknowledgements: This issue was discovered by Vit Ondruch of Red Hat.
Statement: (none)
Upstream patch: https://github.com/ruby/ruby/commit/c7d7ff45f1e0d6fad28e53c02108d4b067e843c3