Blog | G5 Cyber Security

Billion Laughs Attack: XXE Explained

TL;DR

The Billion Laughs attack is a type of Denial-of-Service (DoS) attack that exploits XML parsers by sending a specially crafted XML document containing nested entities. This causes the parser to recursively expand these entities, consuming excessive memory and CPU resources until the server crashes or becomes unresponsive.

What is the Billion Laughs Attack?

The Billion Laughs attack (also known as XML bomb) targets applications that process XML data without proper safeguards. It relies on a vulnerability in how some XML parsers handle external entities and recursion. It’s called ‘Billion Laughs’ because even a relatively small XML file can expand to consume gigabytes of memory.

How Does it Work?

  1. XML Entities: XML uses entities to represent data. These can be simple text replacements or references to external resources.
  2. External Entity References: The attack exploits the ability to define entities that point to other entities, creating a recursive chain.
  3. Recursive Expansion: When an XML parser encounters these nested entities, it attempts to resolve them all before rendering the final document. This leads to exponential growth in the amount of data processed.

Example Attack Payload

Here’s a simplified example of an XML payload designed for this attack:

<!DOCTYPE foo [<entity1;> &#38;entity2;]>
<foo><bar><baz><test>&entity1;</baz></bar></foo>
<entity1><entity2>;>
<entity2><entity3>;>
<entity3><entity4>;>
<entity4><entity5>;>
<entity5><entity1>;>

In this example, entity1 references entity2, which references entity3 and so on. Eventually, they loop back to entity1, creating infinite recursion.

Steps to Prevent the Billion Laughs Attack

  1. Disable External Entities: This is the most effective mitigation. Configure your XML parser to disallow external entity references altogether. How you do this depends on the parser being used.
    • libxml2 (C/C++): Set XML_OPTION_NOENT during parsing.
    • Java: Use a SAXParserFactory and set setFeature("http://apache.org/xml/features/disallow-external-entities", true);
    • Python (lxml): Use the parser=xml.etree.ElementTree.XMLParser(resolve_entities=False) option when creating an ElementTree object.
  2. Limit Recursion Depth: Some parsers allow you to configure a maximum recursion depth for entity expansion. Set this limit to a reasonable value (e.g., 10).
  3. Input Validation: Validate XML input against a strict schema to ensure it doesn’t contain malicious entities.
  4. Resource Limits: Implement resource limits on your server, such as memory and CPU usage, to prevent the attack from completely crashing the system.
  5. Keep Parsers Updated: Regularly update your XML parser library to benefit from security patches that address known vulnerabilities.

Code Example (Java – Disabling External Entities)

import javax.xml.parsers.*;
import org.xml.sax.*;
import java.io.*;

public class XXEPrevention {
    public static void main(String[] args) {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            factory.setFeature("http://apache.org/xml/features/disallow-external-entities", true); // Disable external entities
            SAXParser parser = factory.newSAXParser();
            parser.parse(new File("input.xml"));
        } catch (Exception e) {
            System.err.println("Error parsing XML: " + e.getMessage());
        }
    }
}

Further Resources

Exit mobile version