XML Bombs are an easy way for an attacker to perform a denial-of-service attack against your server, if it accepts XML uploads.
A malicious XML file could take your server offline, causing the loss of critical functions and the loss of revenue. Protecting yourself is a matter of making sure your XML parser is properly configured.
Disable Parsing of Inline DTDs
Inline DTDs are a rarely used feature. However, XML bombs remain a common vulnerability, because many XML parsing libraries do not disable this feature by default. If you use XML parsing, make sure your parser configuration disables this feature. See the code samples below, or consult your API documentation to see how.
Consider Making XML Parsing Asynchronous
Parsing large XML files can take a lot of time and memory. If your architecture doesn’t do so already, consider making the parsing of large XML files asynchronous. As XML files are uploaded, move them over to a queue, and have a separate process pop them off the queue and handle the parsing duties.
This approach will improve the scalability and stability of your system, because onerous parsing jobs won’t take your web server offline. (AJAX requests are the exception here – they need to be handled by the web server, since they are part of the HTTP request-response cycle.)
Throttle Uploads Per Client
If you are accepting XML uploads from identified accounts, it is a good idea to restrict the number of simultaneous parsing jobs per account. This will protect you from accidental denial-of-service attacks, should a downstream system start to overload your system.
The following code samples indicate how to disable inline DTDs in the major XML-parsing libraries.
# Open the XML file, perform config by pass a block. doc = Nokogiri::XML(File.open("data.xml")) do |config| config.strict.noent end
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setExpandEntityReferences(false);
.NET 3.5 and Before
// Disable directly on the reader... XmlTextReader reader = new XmlTextReader(stream); reader.ProhibitDtd = true; // ...or on the settings object. XmlReaderSettings settings = new XmlReaderSettings(); settings.ProhibitDtd = true; XmlReader reader = XmlReader.Create(stream, settings);
.NET 4.0 and After
// Will throw an error if a !DOCTYPE element occurs. XmlReaderSettings settings = new XmlReaderSettings(); settings.DtdProcessing = DtdProcessing.Prohibit; XmlReader reader = XmlReader.Create(stream, settings);