Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to secure javax.xml.transform.TransformerFactory from XML external attacks

Tags:

java

security

xml

I have researched on the subject but couldn't find any relevant info regarding that

Do we need to take any security measurements to secure javax.xml.transform.Transformer against XML external entity attacks?

I did the following and it seems to expand the dtd.

String fileData = "<!DOCTYPE acunetix [  <!ENTITY sampleVal SYSTEM \"file:///media/sample\">]><username>&sampleVal;</username>";
TransformerFactory transformerFactory = TransformerFactory.newInstance();
transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer transformer = transformerFactory.newTransformer();
StringWriter buff = new StringWriter();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new StreamSource(new StringReader(fileData)), new StreamResult(buff));
System.out.println(buff.toString());

output contains the value from the file

<username>test</username>
like image 647
Rajith Avatar asked Aug 19 '15 03:08

Rajith


People also ask

Which of the following will prevent external XML entities injection XXE?

The safest way to prevent XXE is always to disable DTDs (External Entities) completely. Depending on the parser, the method should be similar to the following: factory. setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

Which one of the following is the primary vulnerability exploited by XML external entities attacks?

Aside from retrieval of sensitive data, the other main impact of XXE attacks is that they can be used to perform server-side request forgery (SSRF). This is a potentially serious vulnerability in which the server-side application can be induced to make HTTP requests to any URL that the server can access.

Does not prevent or limit external entities resolution?

Using XML processors that do not prevent or limit external entities resolution can expose the application to XML External Entities attacks. XML External Entities attacks benefit from an XML feature to dynamically build documents at runtime. An XML entity allows inclusion of data dynamically from a given resource.


1 Answers

Your code seems correct. When I run this slightly modified JUnit test case:

@Test
public void test() throws TransformerException, URISyntaxException {
  File testFile = new File(getClass().getResource("test.txt").toURI());
  assertTrue(testFile.exists());
  String fileData = "<!DOCTYPE acunetix [  <!ENTITY foo SYSTEM \"file://" + 
                    testFile.toString() +
                    "\">]><xxe>&foo;</xxe>";
  TransformerFactory transformerFactory = TransformerFactory.newInstance();
  System.out.println(transformerFactory.getClass().getName());
  transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
  Transformer transformer = transformerFactory.newTransformer();
  StringWriter buff = new StringWriter();
  transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
  transformer.transform(new StreamSource(new StringReader(fileData)), new StreamResult(buff));
  assertEquals("<xxe>&foo;</xxe>", buff.toString());
}

I get the following output:

com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
[Fatal Error] :1:182: External Entity: Failed to read external document 'test.txt', because 'file' access is not allowed due to restriction set by the accessExternalDTD property.
ERROR:  'External Entity: Failed to read external document 'test.txt', because 'file' access is not allowed due to restriction set by the accessExternalDTD property.'

From the setFeature JavaDocs:

All implementations are required to support the XMLConstants.FEATURE_SECURE_PROCESSING feature. When the feature is:

  • true: the implementation will limit XML processing to conform to implementation limits and behave in a secure fashion as defined by the implementation. Examples include resolving user defined style sheets and functions. If XML processing is limited for security reasons, it will be reported via a call to the registered ErrorListener.fatalError(TransformerException exception). See setErrorListener(ErrorListener listener).

That error goes away if I comment out transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); and then the test fails because the entity is resolved.

Try adding an ErrorListener to both the TransformerFactory and Transformer:

transformerFactory.setErrorListener(new ErrorListener() {

  @Override
  public void warning(TransformerException exception) throws TransformerException {
    System.out.println("In Warning: " + exception.toString());
  }

  @Override
  public void error(TransformerException exception) throws TransformerException {
    System.out.println("In Error: " + exception.toString());
  }

  @Override
  public void fatalError(TransformerException exception) throws TransformerException {
    System.out.println("In Fatal: " + exception.toString());
  }
});

Transformer transformer = transformerFactory.newTransformer();
transformer.setErrorListener(transformerFactory.getErrorListener());

I see the following new console output now:

In Error: javax.xml.transform.TransformerException: External Entity: Failed to read external document 'test.txt', because 'file' access is not allowed due to restriction set by the accessExternalDTD property.

Maybe your implementation is treating it as a warning? Otherwise, maybe it's the implementation you're using? It looks like the JavaDoc spec isn't precise, so one implementation might do something different than another. I'd be interested to know faulty implementations!

like image 50
coastalhacking Avatar answered Nov 15 '22 00:11

coastalhacking