CVE-2014-8080: Tấn công từ chối dịch vụ giãn nở XML (XML Expansion)

Việc không kiểm soát thực thể giãn nở (expansion of entity) có thể dẫn đến lỗ hổng tấn công từ chối dịch vụ trong REXML. Lỗ hổng này đã được đánh dấu lỗi trên CVE CVE-2014-8080. Chúng tôi khuyến cáo bạn nên nâng cấp Ruby.

Chi tiết

Khi đọc những text node trong 1 tài liệu XML, bộ dịch REXML có thể bị ép buộc để cấp phát bộ nhớ cho các đối tượng chuỗi (string object) cực lớn, có thể chiếm hết toàn bộ bộ nhớ trên 1 máy, và gây ra lỗi từ chối dịch vụ.

Mã gây ảnh hưởng sẽ có thể nhìn gần giống như sau:

require 'rexml/document'

xml = <<XML
<!DOCTYPE root [
  # ENTITY expansion vector
]>
<cd></cd>
XML

p REXML::Document.new(xml)

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

Phiên bản bị dính lỗi

  • Tất cả phiên bản Ruby 1.9 trước Ruby 1.9.3 bản vá 550
  • Tất cả phiên bản Ruby 2.0 trước Ruby 2.0.0 bản vá 594
  • Tất cả phiên bản Ruby 2.1 trước Ruby 2.1.4
  • tất cả phiên bản trước phiên bản 48161

Tạm vá

Nếu như bạn không thể nâng cấp Ruby, sử dụng cách vá sau để khắc phục trên các phiên bản Ruby 2.1.0+:

class REXML::Entity
  def value
      if @value
        matches = @value.scan(PEREFERENCE_RE)
        rv = @value.clone
        if @parent
          sum = 0
          matches.each do |entity_reference|
            entity_value = @parent.entity( entity_reference[0] )
            if sum + entity_value.bytesize > Security.entity_expansion_text_limit
              raise "entity expansion has grown too large"
            else
              sum += entity_value.bytesize
            end
            rv.gsub!( /%#{entity_reference.join};/um, entity_value )
          end
        end
        return rv
      end
      nil
   end
end

Với những phiên bản Ruby cũ hơn 2.1.0, bạn có thể dùng phương pháp sau để khắc phục:

class REXML::Entity
  def value
      if @value
        matches = @value.scan(PEREFERENCE_RE)
        rv = @value.clone
        if @parent
          sum = 0
          matches.each do |entity_reference|
            entity_value = @parent.entity( entity_reference[0] )
            if sum + entity_value.bytesize > Document.entity_expansion_text_limit
              raise "entity expansion has grown too large"
            else
              sum += entity_value.bytesize
            end
            rv.gsub!( /%#{entity_reference.join};/um, entity_value )
          end
        end
        return rv
      end
      nil
   end
end

Cảm ơn

Gửi lời cảm ơn tới Willis Vandevanter vì đã thông báo về vấn đề này.

Lịch sử

  • Được công bố chính thức vào lúc 2014-10-27 12:00:00 (UTC)