Skip to main content

XML injection (XXE)

Need

Prevention of XML injection attacks

Context

  • Usage of Ruby for building dynamic and object-oriented applications
  • Usage of Nokogiri for HTML and XML parsing and manipulation

Description

Non compliant code

require 'nokogiri'

def parse_xml(input)
document = Nokogiri::XML(input)
# process the document
end

The above Ruby code uses the Nokogiri library to parse XML input. However, it is vulnerable to XML External Entity (XXE) injection because it does not disable the parsing of external entities in XML documents.

An attacker could craft an XML document with a malicious external entity that could lead to data exfiltration, Denial of Service (DoS), Server Side Request Forgery (SSRF), or even Remote Code Execution (RCE).

For example, an attacker could inject the following XML:

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<foo>&xxe;</foo>

The SYSTEM "file:///etc/passwd" part of the payload tells the XML parser to fetch the content of the /etc/passwd file, which contains sensitive information about user accounts on a Unix-like system. The parser then replaces the &xxe; entity with the content of the file. If the application processes and displays the parsed XML, the attacker would be able to see the content of the /etc/passwd file.

Steps

  • Sanitize user input: Validate and sanitize any user input before passing it to the XML parser.
  • Disable external entity expansion: Configure the XML parser to disable external entity expansion to prevent XXE attacks.
  • Use a whitelist approach: Only allow specific XML elements and attributes that are necessary for the application's functionality.
  • Implement input validation: Validate the structure and content of the XML input to ensure it conforms to the expected format.
  • Use a secure XML parsing library: Choose a secure XML parsing library that has built-in protections against XXE attacks.
  • Keep software up to date: Regularly update the XML parsing library and the underlying framework to ensure any security patches are applied.
  • Implement access controls: Restrict access to sensitive resources and limit the privileges of the XML parsing functionality.
  • Educate developers: Provide training and guidelines to developers on secure coding practices and the risks associated with XML injection vulnerabilities.

Compliant code

require 'nokogiri'

def parse_xml(input)
document = Nokogiri::XML(input) do |config|
config.options = Nokogiri::XML::ParseOptions::NOENT | Nokogiri::XML::ParseOptions::NONET
end
# process the document
end

The original code was vulnerable to XML External Entity (XXE) injection, which could allow an attacker to view files on the application server, interact with any back-end or external systems that the application itself can access, or perform a denial-of-service attack.

The updated code mitigates this vulnerability by configuring the XML parser to disable the expansion of external entities (NOENT) and prevent network connections (NONET) during parsing. This is done by setting the options attribute of the Nokogiri::XML parser.

Here's a breakdown of the changes:

  • Nokogiri::XML::ParseOptions::NOENT: This option prevents the parser from expanding entities. Entities are a way of representing an item in XML that can be used to define external resources. By disabling entities, we're preventing the parser from accessing external resources.

  • Nokogiri::XML::ParseOptions::NONET: This option prevents the parser from opening connections to any URI. This means that even if an entity is somehow processed, it won't be able to access any resources over the network.

These changes ensure that the XML parser is not susceptible to XXE attacks, as it will not process external entities or open network connections.

References