What Is the Billion Laughs Attack in XML?
The Billion Laughs attack, also known as an XML bomb, is a denial-of-service (DoS) attack targeting XML parsers using recursive entity expansion. By exploiting the Document Type Definition (DTD) feature, an attacker crafts a seemingly small XML file that expands exponentially in memory when parsed, exhausting system resources and causing the application or server to crash.
Understanding the Billion Laughs Attack
The Billion Laughs attack is a type of XML External Entity (XXE) and general entity expansion vulnerability. It does not steal data or execute arbitrary code; instead, it aims to render an application unavailable by overloading the server’s CPU and RAM.
The attack earns its name from the common proof-of-concept payload
that recursively defines the string "lol" multiple times,
ultimately producing an astronomical number of “lols” in memory.
How Recursive Entity Expansion Works
XML standards allow documents to define custom macros or shortcuts
called entities within a DTD block (<!DOCTYPE>). When
an XML parser encounters an entity reference (e.g.,
&entity_name;), it replaces the reference with the
defined string value.
In a Billion Laughs attack, entities are defined hierarchically, with each entity referencing the previous entity multiple times:
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>The Exponential Expansion Mechanism
- Base Layer: The root entity
&lol;contains the three-character string"lol". - First Expansion:
&lol1;references&lol;ten times (producing 10 “lol”s, or 30 characters). - Recursive Multiplication:
&lol2;references&lol1;ten times (producing 100 “lol”s). - Final Layer: By the time the parser reaches
&lol9;, it attempts to expand \(10^9\) (one billion) instances of the string"lol".
Memory Exhaustion and System Impact
A payload structured this way takes up less than a single kilobyte of disk space or network bandwidth. However, during the parsing phase:
- Memory Usage: Expanding one billion instances of
"lol"generates approximately 3 gigabytes of raw string data in memory. Larger variants with additional layers can easily require hundreds of gigabytes. - CPU Saturation: The parser consumes massive amounts of CPU cycles attempting to traverse and resolve the recursive tree structure.
- Denial of Service: As the parser allocates memory to hold the expanding strings, the operating system eventually runs out of available RAM, triggering out-of-memory (OOM) errors, freezing the process, or crashing the entire host server.
Prevention and Mitigation
Mitigating the Billion Laughs attack requires restricting how XML parsers handle DTDs and entity expansion:
- Disable DTD Processing: The most effective defense
is to completely disable inline DTD declarations (
DOCTYPE) if they are not strictly required by the application. - Disable External and Custom Entities: If DTDs are required for schema validation, configure the parser to ignore custom entity resolutions.
- Limit Entity Expansion: Modern XML parsers (such as
libxml2or modern Java/Python XML libraries) include entity expansion limits (e.g., maximum depth and character size thresholds) to abort parsing if an entity expands beyond safe limits.