Inserito da Fabio Cevasco il 2013-03-03
Un'incontrollata espansione di entità può provocare una vulnerabilità DoS in REXML. L'identificativo CVE "CVE-2013-1821" è stato assegnato a questa vulnerabilità. Raccomandiamo fortemente di aggiornare Ruby.
Dettagli
Durante la lettura di nodi testuali da un documento XML, il parser RAXML può essere utilizzato per allocare degli oggetti string estremamente grandi che possono consumare tutta la memoria su una macchina, causando un Denial of Service.
Il codice impattato è del tipo:
document = REXML::Document.new some_xml_doc
document.root.text
Quando il metodo `text` viene chiamato, le entità XML vengono espanse. Un utente malintenzionato può utilizzare un documento XML relativamente piccolo che, quando le entità vengono risolte, consumerà grandi quantità di memoria nel sistema.
Da notare che questo attacco è simile, ma differente, all'attacco "Billion Laughs", che è correlato al CVE-2013-1664 di Python.
Tutti gli utenti che utilizzano una versione soggetta a questa vulnerabilità dovrebbero procedere all'aggiornamento o utilizzare uno dei workaround immediatamente.
Workaround
Se non puoi aggiornare Ruby, utilizza questa patch manuale come workaround:
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
Questa patch limiterà la grandezza della sostituzione delle entità a 10k per nodo. REXML inoltre di default permette solamente 10000 sostituzioni di entità per documento, quindi il massimo ammontare di testo che può essere generato tramite sostituzione di entità sarà attorno ai 98MB.
Versioni soggette alla vulnerabilità
- Tutte le versioni di Ruby 1.9 precedenti a 1.9.3 patchlevel 392
- Tutte le versioni di Ruby 2.0 precedenti a 2.0.0 patchlevel 0
- Tutte le versioni precedenti alla trunk revision 39384
Crediti
Grazie a Ben Murphy per averci notificato il problema.
Cronologia
- Originariamente pubblicato il giorno 2013-02-22 alle ore 12:00:00 (UTC)