Lỗ hổng DoS mở rộng thực thể trong REXML (XML bomb, CVE-2013-1821)

Đăng bởi usa vào 22 Feb 2013

Việc mở rộng thực thể không giới hạn có thể dẫn đến lỗ hổng DoS trong REXML. Lỗ hổng này đã được gán mã CVE CVE-2013-1821. Chúng tôi khuyến nghị mạnh mẽ việc nâng cấp ruby.

Chi tiết

Khi đọc các text node từ một tài liệu XML, bộ phân tích REXML có thể bị ép buộc cấp phát các đối tượng chuỗi cực kỳ lớn, có thể tiêu thụ toàn bộ bộ nhớ trên máy, gây ra từ chối dịch vụ.

Mã bị ảnh hưởng sẽ trông giống như thế này:

document = REXML::Document.new some_xml_doc
document.root.text

Khi phương thức `text` được gọi, các thực thể sẽ được mở rộng. Kẻ tấn công có thể gửi một tài liệu XML tương đối nhỏ mà khi các thực thể được giải quyết, sẽ tiêu thụ lượng bộ nhớ cực lớn trên hệ thống đích.

Lưu ý rằng cuộc tấn công này tương tự nhưng khác với cuộc tấn công Billion Laughs. Điều này cũng liên quan đến CVE-2013-1664 của Python.

Tất cả người dùng đang chạy phiên bản bị ảnh hưởng nên nâng cấp hoặc sử dụng một trong các giải pháp thay thế ngay lập tức.

Giải pháp thay thế

Nếu bạn không thể nâng cấp Ruby, hãy sử dụng monkey patch này như một giải pháp thay thế:

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

Monkey patch này sẽ giới hạn kích thước thay thế thực thể ở mức 10k mỗi node. REXML đã mặc định chỉ cho phép 10000 lần thay thế thực thể mỗi tài liệu, vì vậy lượng văn bản tối đa có thể được tạo ra bởi thay thế thực thể sẽ khoảng 98 megabyte.

Phiên bản bị ảnh hưởng

  • Tất cả phiên bản ruby 1.9 trước ruby 1.9.3 patchlevel 392
  • Tất cả phiên bản ruby 2.0 trước ruby 2.0.0 patchlevel 0
  • Trước trunk revision 39384

Ghi nhận

Cảm ơn Ben Murphy đã báo cáo vấn đề này.

Lịch sử

  • Thêm số CVE vào 2013-03-11 07:45:00 (UTC)
  • Được công bố lần đầu vào 2013-02-22 12:00:00 (UTC)

Tin mới nhất

Phát hành Ruby 4.0.0

Chúng tôi vui mừng thông báo phát hành Ruby 4.0.0. Ruby 4.0 giới thiệu “Ruby Box” và “ZJIT”, cùng nhiều cải tiến khác.

Đăng bởi naruse vào 25 Dec 2025

Diện mạo mới cho tài liệu Ruby

Tiếp theo việc thiết kế lại ruby-lang.org, chúng tôi có thêm tin vui để kỷ niệm 30 năm Ruby: docs.ruby-lang.org có diện mạo hoàn toàn...

Đăng bởi Stan Lo vào 23 Dec 2025

Thêm Tin...