Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: updated code examples

...

This noncompliant code example attempts to parse the file evil.xml, report any errors, and exit. However, a SAX (Simple API for XML) or a DOM (Document Object Model) parser will attempt to access the URI specified by the SYSTEM attribute, which means it will attempt to read the contents of the local /dev/tty file. On POSIX systems, reading this file causes the program to block until input data is supplied to the machine's console. Consequently, an attacker can use this malicious XML file to cause the program to hang.

Code Block
bgColor#FFcccc
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

class XXE {
  private static void receiveXMLStream(InputStream inStream,
                                       DefaultHandler defaultHandler)
      throws ParserConfigurationException, SAXException, IOException {
    SAXParserFactory factory = SAXParserFactory.newInstance();
    SAXParser saxParser = factory.newSAXParser();
    saxParser.parse(inStream, defaultHandler);
  }

  public static void main(String[] args)
 throws ParserConfigurationException,
    throws ParserConfigurationException, SAXException, IOException {
    try {
      receiveXMLStream(new FileInputStream("evil.xml"), new DefaultHandler());
    } catch (java.net.MalformedURLException mue) {
      System.err.println("Malformed URL Exception: " + mue);
   new DefaultHandler());}
  }
}

This program is subject to a remote XXE attack if the evil.xml file contains the following:

Code Block
bgColor#ffcccc
<?xml version="1.0"?>
<!DOCTYPE foo SYSTEM "file:/dev/tty">
<foo>bar</foo>

...

Compliant Solution (EntityResolver)

...

Code Block
bgColor#ccccff
import java.io.IOException;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

class CustomResolver implements EntityResolver {
  public InputSource resolveEntity(String publicId, String systemId)
      throws SAXException, IOException {

    // Check for known good entities
    String entityPath = "file:/homeUsers/username/java/xxe/fileonlinestore/good.xml";
    if (systemId.equals(entityPath)) {
      System.out.println("Resolving entity: " + publicId +
                         " " + systemId);
      return new InputSource(entityPath);
    } else {
      // Disallow unknown entities by returning a blank path 
      return new InputSource(); 
    }
  }
}

The setEntityResolver() method registers the instance with the corresponding SAX driver.  When parsing malicious input, the empty InputSource returned by the custom resolver causes a java.net.MalformedURLException to be thrown. Note that you must create an XMLReader object on which to set the custom entity resolver.

Code Block
bgColor#ccccff
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

class XXE {
  private static void receiveXMLStream(InputStream inStream,
                                       DefaultHandler defaultHandler)
 throws ParserConfigurationException,
    throws ParserConfigurationException, SAXException, IOException {
    SAXParserFactory factory = SAXParserFactory.newInstance();
    SAXParser saxParser = factory.newSAXParser();

    // Create an XML reader to set the entity resolver.
    XMLReader reader = saxParser.getXMLReader();
    reader.setEntityResolver(new CustomResolver());
    reader.setContentHandler(defaultHandler);

    InputSource is = new InputSource(inStream);
    reader.parse(is);
  }

  public static void main(String[] args)
 throws ParserConfigurationException,
    throws ParserConfigurationException, SAXException, IOException {
    try {
      receiveXMLStream(new FileInputStream("evil.xml"), new DefaultHandler());
    } catch (java.net.MalformedURLException mue) {
      System.err.println("Malformed URL Exception: " + mue);
   new DefaultHandler());}
  }
}

Risk Assessment

Failure to sanitize user input before processing or storing it can result in injection attacks.

...