title: How can I use PHP's various XML libraries to get DOM-like functionality and avoid DoS vulnerabilities, like Billion Laughs or Quadratic Blowup?
body: <p>I'm writing a web application that has an XML API in PHP, and I'm worried about three specific vulnerabilities, all related to inline DOCTYPE definitions: local file inclusion, quadratic entity blowup, and exponential entity blowup. I'd love to use PHP's (5.3) built in libraries, but I want to make sure I'm not susceptible to these.</p>
  
  <p>I found I can eliminate LFI with libxml_disable_entity_loader, but this doesn't help with inline ENTITY declarations, including entities that refer to other entities.</p>
  
  <p>The SimpleXML library (SimpleXMLElement, simplexml_load_string, etc) is great because it's a DOM parser and all my inputs are fairly small; it allows me to use xpath and manipulate the DOM pretty easily. I can't figure how to stop ENTITY declarations. (I would be happy to disable all inline DOCTYPE definitions, if possible.)</p>
  
  <p>The XML Parser library (xml_parser_create, xml_set_element_handler, etc) allows me to set the default handler, which includes entities, with xml_set_default_handler. I can hack it so for unrecognized entities it simply returns the original string (ie, "&ent;"). This library is frustrating though: because it is a SAX parser I have to write a bunch of handlers (as many as 9..).</p>
  
  <p>So is it possible to use the built in libraries, get DOM-like objects out, and protect myself from these various DoS vulnerabilities? thanks</p>
  
  <p>This page describes the three vulnerabilities, and provides a solution...if only I were using .NET: <a href="http://msdn.microsoft.com/en-us/magazine/ee335713.aspx" rel="nofollow noreferrer">http://msdn.microsoft.com/en-us/magazine/ee335713.aspx</a></p>
  
  <p>UPDATE:</p>
  
  <pre><code>&lt;?php
  $s = &lt;&lt;&lt;EOF
  &lt;?xml version="1.0?&gt;
  &lt;!DOCTYPE data [
  &lt;!ENTITY en "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...."&gt;
  ]&gt;
  &lt;data&gt;&amp;en;&amp;en;&amp;en;&amp;en;&amp;en;&amp;en;&amp;en;&amp;en;&amp;en;&amp;en;&amp;en;&amp;en;.....&lt;/data&gt;
  EOF;
  $doc = new DOMDocument();
  $doc-&gt;loadXML($s);
  var_dump($d-&gt;lastChild-&gt;nodeValue);
  ?&gt;
  </code></pre>
  
  <p>I tried <code>loadXML($s, LIBXML_NOENT);</code> as well. In both cases I end up dumping 300+ MB. Is there something I'm still missing?</p>