CVE-2014-8080 : Déni de service sur l'expansion XML

Une expansion d’entité sans restriction peut conduire à une vulnérabilité DoS dans REXML. Cette vulnérabilité a reçu un identifiant CVE-2014-8080. Nous recommandons grandement de mettre à jour Ruby.

Détails

Lors de la lecture des nœuds d’un document XML, l’analyseur REXML peut être forcé à allouer de très grands objets String qui peuvent consommer toute la mémoire de la machine et causer une attaque par déni de service.

Typiquement, les scripts impactés sont de la forme :

require 'rexml/document'

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

p REXML::Document.new(xml)

Tous les utilisateurs utilisant une version affectée doivent soit mettre à jour Ruby ou utiliser une solution de contournement dans les plus brefs délais.

Versions concernées

  • Toutes les versions de Ruby 1.9 antérieures à Ruby 1.9.3 patchlevel 550
  • Toutes les versions de Ruby 2.0 antérieures à Ruby 2.0.0 patchlevel 594
  • Toutes les versions de Ruby 2.1 antérieures à Ruby 2.1.4
  • Toutes les révisions du trunk antérieures à 48161

Solution alternative

Si vous ne pouvez pas mettre à jour Ruby, utilisez ce patch comme solution alternative pour les versions de Ruby supérieure à 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

Pour les versions antérieures à 2.1.0, vous pouvez utiliser le patch suivant :

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

Crédits

Merci à Willis Vandevanter pour avoir signaler ce bug.

Historique

  • Article publié le 27 octobre 2014 à 12h00 (UTC)