如何保护javax.xml.transform.TransformerFactory免受XML外部攻击

10

我已经对这个主题进行了研究,但没有找到相关信息。

我们需要采取任何安全措施来保护javax.xml.transform.Transformer免受XML外部实体攻击吗?

我已经做了以下操作,似乎扩展了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());

输出包含文件中的值。

<username>test</username>
2个回答

5

您的代码看起来是正确的。当我运行这个稍微修改过的JUnit测试用例时:

@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());
}

我得到了以下输出:
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.'

setFeatureJavaDocs中可以了解到:

所有实现都需要支持XMLConstants.FEATURE_SECURE_PROCESSING特性。当该特性为:

  • true:实现将限制XML处理以符合实现限制,并按照实现定义的安全方式进行操作。例如,解析用户定义的样式表和函数。如果由于安全原因限制XML处理,则会通过调用注册的ErrorListener.fatalError(TransformerException exception)进行报告。请参阅setErrorListener(ErrorListener listener)。
如果我注释掉transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);,那么错误将消失,但测试失败,因为实体已被解析。
请尝试向TransformerFactory和Transformer添加ErrorListener。
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());

我现在看到以下新的控制台输出:

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.

也许你的实现将其视为警告?否则,可能是你使用的实现方式?看起来JavaDoc规范不够精确,因此一个实现可能会与另一个实现有所不同。我很想知道哪些实现存在问题!

0

我知道这是一个旧帖子,但对于那些来到这里的人,我希望它能有所帮助 :)

在应用下面的解决方案后,SonarQube仍然抱怨“禁用XML解析中的外部实体访问”安全问题 :(

factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");

最终,我采用了以下解决方案,最终为我修复了这个问题。
TransformerFactory factory = TransformerFactory.newInstance();
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接