发布者:usa,发布于 2013 年 5 月 14 日
Ruby 中的 DL 和 Fiddle 存在一个漏洞,被污染的字符串可以被系统调用使用,而忽略 Ruby 中设置的 $SAFE 级别。此漏洞已被分配 CVE 标识符 CVE-2013-2065。
影响
通过 DL 或 Fiddle 暴露给 Ruby 的本地函数不会检查传入对象的污染值。这可能导致在应该引发 SecurityError 异常时,接受被污染的对象作为输入。
受影响的 DL 代码如下所示
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
受影响的 Fiddle 代码如下所示
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
所有运行受影响版本的用户都应立即升级或使用其中一种解决方法。
请注意,这不会阻止将数字内存偏移量用作指针值。数字不能被污染,因此无法检查传递数字内存偏移量的代码。例如
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
在这种情况下,传递的是内存位置,DL / Fiddle 无法确定对象的污染情况。在这种情况下,请在传递内存位置之前检查用户输入的污染情况
user_input = "uname -rs".taint
raise if $SAFE >= 1 && user_input.tainted?
my_function DL::CPtr[user_input].to_i
解决方法
如果您无法升级 Ruby,可以使用以下猴子补丁作为解决方法
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
受影响的版本
- 所有 ruby 1.9 版本,早于 ruby 1.9.3 patchlevel 426
- 所有 ruby 2.0 版本,早于 ruby 2.0.0 patchlevel 195
- 早于主干版本 40728
ruby 1.8 版本不受影响。
鸣谢
感谢 Vit Ondruch 报告此问题。
历史
- 最初发布于 2013-05-14 13:00:00 (UTC)