java.lang.非法参数异常:不支持:http://javax.xml.XMLConstants/property/accessExternalDTD

toe95027  于 2023-03-28  发布在  Java
关注(0)|答案(2)|浏览(812)

我从Java代码的扫描报告中获得了漏洞缺陷,做了一些研究,并找到了解决此类问题的建议:
XML外部实体引用限制不当(CWE ID 611)
这是包含修复XXE攻击问题的代码:

public static String convertNodeToString(Node node) {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer;
        try {
            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
            transformer = tf.newTransformer();
            // below code to remove XML declaration
            // transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            StringWriter writer = new StringWriter();
            transformer.transform(new DOMSource(node), new StreamResult(writer));
            String output = writer.getBuffer().toString();
            return output;
        } catch (TransformerException e) {
            e.printStackTrace();
        }

        return null;
    }

好消息是JUnit测试是成功的,但是,当我在运行的示例上部署代码时,我得到了这个错误:
java.lang.非法参数异常:不支持:http://javax.xml.XMLConstants/property/accessExternalDTD
根据我的经验,这是因为正在运行的示例使用了一些依赖项,导致了这样的冲突并导致了这个错误。
以下是控制台堆栈跟踪的一部分:
java.lang.非法参数异常:不支持:http://javax.xml.XMLConstants/property/accessExternalDTD at org.apache.xalan.processor.TransformerFactoryImpl.setAttribute(TransformerFactoryImpl.java:571)
我如何找到哪个依赖项导致了这样的错误?我可以做些什么来解决这样的错误?我也怀疑我错过了包括依赖项。请帮助我解决这个问题。

编辑1:

我做了进一步的研究,我认为这是因为用于启动实际示例的java.exe命令中的这个引用:
java.exe -Xbootclasspath/p:../lib/xalan.jar;../lib/xercesImpl.jar;...
现在,我需要找出如何克服这个问题。我遇到了一些文章,建议确保使用正确的包创建工厂示例。我认为上面的代码最终使用了错误的包。
现在的问题是如何使用java代码来确保使用正确的包来创建TransformerFactory示例。

编辑二:

第一个答案帮助我取得了一些进展。我发现已部署示例的类路径在xalan.jar中引用了org.apache.xalan.processor.TransformerFactoryImpl,似乎TransformerFactory.newInstance()使用它来创建转换器工厂。我认为问题是如何进行必要的更改以确保使用正确的类来创建转换器。

编辑三:

我遵循了here的建议并添加了以下代码:

TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);

该错误已在运行示例中解决,但扫描工具仍报告此漏洞缺陷XXE Attack。根据this article,发生此情况是因为类路径上存在过时的XML处理器(例如Xerces,Xalan),这正是我的情况。
我想我遇到了一篇文章,建议更改一些系统属性,这些属性将指示工厂使用正确的类创建转换器示例。我现在正在尝试找到这篇文章。
谢谢你的帮助。

mbyulnm0

mbyulnm01#

我遇到了同样的问题,这是另一个实现对我有效:

import com.sun.org.apache.xalan.internal.xsltc.trax.TranformerFactoryImpl;
...
TranformerFactoryImpl tf = new TranformerFactoryImpl();
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");

编辑1:也可以尝试强制:

import javax.xml.transform.TransformerFactory;

TransformFactory tf = new TransformFactory.newInstance(“com.sun.org.apache.xalan.internal.xsltc.trax.TranformerFactoryImpl”, null);
6ie5vjzr

6ie5vjzr2#

感谢@Gabriel帮助我找到了答案。这是使用系统属性解决问题的另一种方法。另一种方法是使用TransformerFactory.newInstance();方法指定正确的类的名称。正确的类是com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl

tf = TransformerFactory.newInstance("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", NameOfContainerClass.class.getClassLoader());

下面是最终的答案,它为我工作,扫描报告是干净的。

private final static String JAVAX_TRANSFORMER_PROP = "javax.xml.transform.TransformerFactory";
private final static String JAVAX_TRANSFORMER_PROP_VAL = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";

public static String convertNodeToString(Node node) throws Exception  {
        TransformerFactory tf=null;
        Transformer transformer;
        String errMsg=null;
        String output=null;
        //Prevent XXE Attack: Ensure using the correct factory class to create TrasformerFactory instance
        //  This will instruct Java to use to version which supports using ACCESS_EXTERNAL_DTD argument.
        // Use:
        //   - com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl
        //  instead of:
        //   - org.apache.xalan.processor.TransformerFactoryImpl
        if (System.getProperty(JAVAX_TRANSFORMER_PROP) == null || 
            !System.getProperty(JAVAX_TRANSFORMER_PROP).equals(JAVAX_TRANSFORMER_PROP_VAL))
            System.setProperty(JAVAX_TRANSFORMER_PROP, JAVAX_TRANSFORMER_PROP_VAL);
        try {
            tf = TransformerFactory.newInstance();
        } catch (TransformerFactoryConfigurationError  e) {
            e.printStackTrace();
            errMsg="Error 'TransformerFactoryConfigurationError' in convertNodeToString() while creating 'TransformerFactory' instance: " + e.toString();
        } catch (Exception  e) {
            e.printStackTrace();
            errMsg="Error in convertNodeToString() while creating 'TransformerFactory' instance:: " + e.toString();
        }
        if (errMsg != null)
            throw new Exception(errMsg);
        //Prevent XXE Attack: Set attributes to prevent XXE Attack vulnerabilities.
        try {
            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
            tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            errMsg = "Error 'IllegalArgumentException' in convertNodeToString() while attempting to prevent XXE Attack: " + e.toString();
        } catch (Exception e) {
            e.printStackTrace();
            errMsg = "Error in convertNodeToString() while attempting to prevent XXE Attack: " + e.toString();
        }
        if (errMsg != null)
            throw new Exception(errMsg);
        //tf.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
        try {
            transformer = tf.newTransformer();
            // below code to remove XML declaration
            // transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            StringWriter writer = new StringWriter();
            transformer.transform(new DOMSource(node), new StreamResult(writer));
            output = writer.getBuffer().toString();
        } catch (TransformerException e) {
            e.printStackTrace();
            errMsg = "Error 'TransformerException' in convertNodeToString() while converting the node to string: " + e.toString();
        } catch (Exception e) {
            e.printStackTrace();
            errMsg = "Error 'TransformerException' in convertNodeToString() while converting the node to string: " + e.toString();
        }
        if (errMsg != null)
            throw new Exception(errMsg);
        return output;
}

参考:https://stackoverflow.com/a/50219550/4180447

相关问题