Imagine that your Drupal or WordPress website crashes, and your server ramps up to 100-percent CPU and RAM usage. The MySQL database underpinning your website is being pummeled by a denial-of-service (DoS) attack. If you’re running a self-hosted website on WordPress 3.5 to 3.9 or on Drupal 6.x to 7.x, then you might find yourself in this situation sooner than you think. A researcher from Salesforce.com named Nir Goldschlager recently discovered an XML vulnerability that allows small XML payloads created by attackers to completely disable Drupal and WordPress sites.
What Is XML?
XML is a markup language used to describe and structure dynamic data. It packages data for use by many kinds of applications. The same XML document containing someone’s name, address, and phone number could be displayed by an HTML website and a mobile application as well as being interpreted by a machine that reads aloud to blind people. By structuring data in a consistent format, XML simplifies sharing and allows many applications to pull from the same sources.
One way to package information is to create an XML entity. Imagine this simple scenario: On your business website, you want to display your company name, address, and telephone number at the top of every page. However, if your business moves to a new location, you don’t want to manually retype your address on every Web page you’ve created, particularly if you’ve published hundreds of blog posts or created thousands of product descriptions. This very simple scenario uses XML entities to solve your address problem:
- Create an XML entity. In your document type definition (DTD), you create the code <!ENTITY address “My Address”>. You’d have similar entities for both your company name and your phone number.
- Write the entity into your HTML code. On the address line, you’d type <p>&address</p> instead of typing in your address on every Web page.
- Update your entity. After you move to your new location, you go back into your DTD and change “My Address” to “My New Address.” Every place that uses the code “&address” will now display “My New Address.” In other words, your new business address populates across all of your Web pages even though you update it in only one place.
XML and DoS
DoS attacks occur when one computer sends so many communications requests of a target, such as a Web server, that it consumes all of the target’s resources. If the target server is a server hosting a website and the network isn’t protected by network security protection tools, then the website becomes unavailable to users. One popular way to carry out a DoS attack is to create an XML bomb. XML bombs look like normal, well-structured XML entities, but they’re designed to crash any application that tries to interpret them.
One type of XML bomb, an Exponential Entity Expansion XML bomb, nests entities inside one another so that interpreting one entity requires interpreting thousands, millions, and even billions of other entities. The endless strings of requests consume all of the target machine’s processing power. The Billion Laughs attack is an example of an Exponential Entity Expansion Bomb in action.
XML Quadratic Blowup
Goldschlager’s WordPress and Drupal vulnerability allows attackers to take down websites with another type of XML bomb called an XML Quadratic Blowup. Instead of nesting entities inside one another, an XML Quadratic Blowup uses a long string of entities that refer back to one another. For example, an entity may contain a string of 55,000 other entities, which the target server will devote all of its resources to trying to parse.
MySQL has a Max Connections memory limit of 151 MB. The PHP language upon which Drupal and WordPress are based has a memory allocation limit of 128 MB, which means that WordPress and Drupal could allocate 128×151, or 19,328 MB, of memory to XML Quadratic Blowup requests. The attacker has to design the file so that it doesn’t overwrite the PHP limit; otherwise, the server will reject the request. With careful programming, an attacker can create a 200 KB payload that expands to 2.5 GB while it’s being parsed.