Skip to main content

CVE-2021-3541 "Parameter Laughs" fixed in libxml2 2.9.11

In context of my work on protection against Billion Laughs Attacks for libexpat, I played with the existing protection of libxml2 against those attacks. As an unintended byproduct, that led me to finding a bypass of that protection, a new vulnerability in libxml2 prior to 2.9.11 that I call Parameter Laughs; it has been assigned CVE number CVE-2021-3541 and is known as libxml2 issue 228 upstream.

Parameter Laughs is based upon well-known ideas from the Billion Laughs Attack — both use nested entities to amplify a small payload of a few hundred bytes up to gigabytes of content to process and hence wasting loads of RAM, CPU time, or both — but in contrast Parameter Laughs…

  1. uses parameter entities (syntax %entity; with %) rather than general entities (syntax &entity; with &) and
  2. uses delayed interpretation to effectively sneak use of parameter entities into the so-called "internal subset" of the XML document (the "here" in <!DOCTYPE r [here]>) where undisguised parameter entities are not allowed, with regard to the XML specification.

What do I mean by "delayed interpretation"? Let us declare a parameter entity like this:

<!ENTITY % pe_2 "&#37;pe_1;<!---->&#37;pe_1;">

Now during replacement of reference %pe_2; text &#37; is turned into % and hence &#37;pe_1; becomes %pe_1;. That triggers two new rounds of replacement for %pe_1; after %pe_2; has been fully replaced — there you have the delay (and the exponential growth).

Here is what Parameter Laughs looks like as a complete XML document (added 2021-05-25):

<?xml version="1.0"?>
  "Parameter Laughs", i.e. variant of Billion Laughs Attack
                           using delayed interpretation
                           of parameter entities
  Copyright (C) Sebastian Pipping <>
  <!ENTITY % pe_1 "<!---->">
  <!ENTITY % pe_2 "&#37;pe_1;<!---->&#37;pe_1;">
  <!ENTITY % pe_3 "&#37;pe_2;<!---->&#37;pe_2;">
  %pe_3; <!-- not at full potential, increase towards "%pe40;"
              carefully -->

Compared to something like arbitrary code execution, Parameter Laughs is "only" a denial of service attack. Its eager use of RAM made my machine need a hard reset in practice: maybe that's something that you want to be protected against, too.