由 usa 发布于 2013年2月22日
不受限制的实体扩展可能导致 REXML 中出现 DoS 漏洞。此漏洞已被分配 CVE 标识符 CVE-2013-1821。我们强烈建议升级 Ruby。
详情
当从 XML 文档中读取文本节点时,REXML 解析器可能会被强制分配非常大的字符串对象,这些对象会消耗机器上的所有内存,从而导致拒绝服务。
受影响的代码可能如下所示
document = REXML::Document.new some_xml_doc
document.root.text
当调用 `text` 方法时,实体将被扩展。攻击者可以发送一个相对较小的 XML 文档,当实体被解析时,该文档将消耗目标系统上的大量内存。
请注意,此攻击类似于 Billion Laughs 攻击,但与之不同。 这也与 Python 的 CVE-2013-1664 有关。
所有运行受影响版本的用户都应立即升级或使用其中一种解决方法。
解决方法
如果您无法升级 Ruby,请使用此猴子补丁作为解决方法
class REXML::Document
@@entity_expansion_text_limit = 10_240
def self.entity_expansion_text_limit=( val )
@@entity_expansion_text_limit = val
end
def self.entity_expansion_text_limit
@@entity_expansion_text_limit
end
end
class REXML::Text
def self.unnormalize(string, doctype=nil, filter=nil, illegal=nil)
sum = 0
string.gsub( /\r\n?/, "\n" ).gsub( REFERENCE ) {
s = self.expand($&, doctype, filter)
if sum + s.bytesize > REXML::Document.entity_expansion_text_limit
raise "entity expansion has grown too large"
else
sum += s.bytesize
end
s
}
end
def self.expand(ref, doctype, filter)
if ref[1] == ?#
if ref[2] == ?x
[ref[3...-1].to_i(16)].pack('U*')
else
[ref[2...-1].to_i].pack('U*')
end
elsif ref == '&'
'&'
elsif filter and filter.include?( ref[1...-1] )
ref
elsif doctype
doctype.entity( ref[1...-1] ) or ref
else
entity_value = DocType::DEFAULT_ENTITIES[ ref[1...-1] ]
entity_value ? entity_value.value : ref
end
end
end
这个猴子补丁会将每个节点的实体替换大小限制为 10k。REXML 已经默认为每个文档只允许 10000 个实体替换,因此实体替换可以生成的最大文本量约为 98 MB。
受影响的版本
- 所有 ruby 1.9 版本,早于 ruby 1.9.3 patchlevel 392
- 所有 ruby 2.0 版本,早于 ruby 2.0.0 patchlevel 0
- 早于 trunk 版本 39384
鸣谢
感谢 Ben Murphy 报告此问题。
历史
- 在 2013-03-11 07:45:00 (UTC) 添加了关于 CVE 编号的信息
- 最初发布于 2013-02-22 12:00:00 (UTC)