CVE-2015-1819
Einführung
CVE-2015-1819 beschreibt eine Sicherheitslücke, die in vielen XML-Parsern vorhanden war und durch die fehlende Absicherung gegen rekursiv definierte XML-Dokumente definiert wurde. Diese Lücke ermöglichte es dank des stark erhöhten Hauptspeicheraufwands, der durch das Parsen der XML-Dokumente entsteht, denial of service (DoS)-Angriffe auf die betroffenen Systeme auszuführen. Die Sicherheitslücke lässt sich ohne viele Kenntnisse ausnutzen und bietet abgesehen von der Auswirkung auf die Performance des Systems keine Möglichkeit Daten oder das System zu kompromittieren.
Aufbau des XML-Dokuments
Man definiert zuerst eine Entity mit einem simplen String
<!ENTITY ZERO "A">
Danach definiert man eine weitere Entity, und referenziert in dieser die erste Entity
<!ENTITY ONE "&ZERO;&ZERO;">
Diese Rekursion führt man fort
<!ENTITY TWO "&ONE;&ONE;">
...
<!ENTITY THIRTYTWO "&THIRTYONE;&THIRTYONE;">
Nach den Rekursionen wird die letzte Entity im Data-Tag eingesetzt um den Parser zu dazu zu bringen, die rekursive Definition aufzulösen
<data>&THIRTYTWO;</data>
Nach der Auflösung hat der String von THIRTYTWO eine Länge von 2^32, was etwa einem Speicherverbrauch von 4GB entspricht.
Problemlösung
Um zu verhindern das der xmlreader überläuft wird der zur Verfügung stehende Puffer begrenzt.
Dafür wurde ein neuer Allokationstyp für den Buffer erstellt.
#include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
/*
* Used to provide parsing limits
*/
if ((buf->use + len >= XML_MAX_TEXT_LENGTH) ||
(buf->size >= XML_MAX_TEXT_LENGTH)) {
xmlBufMemoryError(buf, "buffer error: text too long\n");
return(0);
}
if (size >= XML_MAX_TEXT_LENGTH)
size = XML_MAX_TEXT_LENGTH;
}
if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
/*
* Used to provide parsing limits
*/
if (size >= XML_MAX_TEXT_LENGTH) {
xmlBufMemoryError(buf, "buffer error: text too long\n");
return(0);
}
}
if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
/*
* Used to provide parsing limits
*/
if (needSize >= XML_MAX_TEXT_LENGTH) {
xmlBufMemoryError(buf, "buffer error: text too long\n");
return(-1);
}
}
if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
/*
* Used to provide parsing limits
*/
if (needSize >= XML_MAX_TEXT_LENGTH) {
xmlBufMemoryError(buf, "buffer error: text too long\n");
return(-1);
}
}
XML_BUFFER_ALLOC_HYBRID, /* exact up to a threshold, and doubleit thereafter */
XML_BUFFER_ALLOC_BOUNDED /* limit the upper size of the buffer */
xmlBufSetAllocationScheme(ret->buffer,
XML_BUFFER_ALLOC_BOUNDED);
const xmlChar *ret;
xmlBufSetAllocationScheme(reader->buffer,
XML_BUFFER_ALLOC_BOUNDED);
ret = xmlBufContent(reader->buffer);
if (ret == NULL) {
/* error on the buffer best to reallocate */
xmlBufFree(reader->buffer);
reader->buffer = xmlBufCreateSize(100);
xmlBufSetAllocationScheme(reader->buffer,
XML_BUFFER_ALLOC_BOUNDED);
ret = BAD_CAST "";
}
return(ret);
/* no operation on a reader should require a huge buffer */
xmlBufSetAllocationScheme(reader->buffer,
XML_BUFFER_ALLOC_BOUNDED);
Betroffene Systeme/ Anwendungen
Linux
- Debian 7.0/8.0
- Ubuntu 12.04/14.04/15.04
- Redhat <= 5.0
- Fedora 22/23
- openSUSE 13.1/13.2
xmlsoft
- libxml allVersions
Apple
- iOS <= 9.2.1
- macOS <= 10.11.3
- WatchOS <= 2.1
Quellen
https://cwe.mitre.org/data/definitions/776.html
https://nvd.nist.gov/vuln/detail/CVE-2015-1819
https://gitlab.gnome.org/GNOME/libxml2/-/commit/213f1fe0d76d30eaed6e5853057defc43e6df2c9