java web项目,如何过滤xml 非法字符,避免出现xxe漏洞?

java web项目,如何检验XML中的参数是否合法,避免出现xxe漏洞?

/**
* 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
* @param strxml
* @return
* @throws JDOMException
* @throws IOException
/

public static Map doXMLParse(String strxml) throws JDOMException, IOException {

//过滤关键词,防止XXE漏洞攻击
strxml = XMLUtil.filterXXE(strxml);
//
strxml = strxml.replaceFirst("encoding=\".
\"", "encoding=\"UTF-8\"");

    if(null == strxml || "".equals(strxml)) {  
        return null;  
    }  

    Map m = new HashMap();  

    InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));  
    SAXBuilder builder = new SAXBuilder();  
    Document doc = builder.build(in);  
    Element root = doc.getRootElement();  
    List list = root.getChildren();  
    Iterator it = list.iterator();  
    while(it.hasNext()) {  
        Element e = (Element) it.next();  
        String k = e.getName();  
        String v = "";  
        List children = e.getChildren();  
        if(children.isEmpty()) {  
            v = e.getTextNormalize();  
        } else {  
            v = XMLUtil.getChildrenText(children);  
        }  

        m.put(k, v);  
    }  

    //关闭流  
    in.close();  

    return m;  
}  


/**
 * 防止 XXE漏洞 注入实体攻击
 * 过滤 过滤用户提交的XML数据
 *       过滤关键词:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。
 */
public static String filterXXE(String xmlStr){
xmlStr = xmlStr.replace("DOCTYPE", "").replace("SYSTEM", "").replace("ENTITY", "").replace("PUBLIC", "");

return xmlStr;
}

//*****************以下为测试 攻击代码***** 内部调试用**************************

// public static void main(String[] args) {
// String strxml = XMLUtil.readFileByLines("C:\text.xml");
// try {
// XMLUtil.doXMLParse(strxml);
// } catch (JDOMException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }

// }

C:\text.xml 的文件内容如下:


<!DOCTYPE a[<!ENTITY b SYSTEM "c:\123.txt">]>

&b;
login

<![CDATA[SUCCESS]]>
<![CDATA[OK]]>
<![CDATA[wx8775cbf90e1544d5]]>
<![CDATA[1406957502]]>
<![CDATA[RyXFitfwAY0iqotC]]>
<![CDATA[B60953438AB16569220DC885E15F8E39]]>
<![CDATA[SUCCESS]]>
<![CDATA[wx05104307622483a7349606c80845112418]]>
<![CDATA[APP]]>

可以试试过滤关键词:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。
比如 xmlStr = xmlStr.replace("DOCTYPE", "").replace("SYSTEM", "").replace("ENTITY", "").replace("PUBLIC", "");
return xmlStr;
可以参考https://blog.csdn.net/golddaniu/article/details/80928537,亲测可用

转自微信:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_5
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; // catching unsupported features
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
String FEATURE = null;
try {
// This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all XML entity attacks are prevented
// Xerces 2 only - http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl
FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
dbf.setFeature(FEATURE, true);

// If you can't completely disable DTDs, then at least do the following:
// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
// JDK7+ - http://xml.org/sax/features/external-general-entities 
FEATURE = "http://xml.org/sax/features/external-general-entities";
dbf.setFeature(FEATURE, false);

// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
// JDK7+ - http://xml.org/sax/features/external-parameter-entities 
FEATURE = "http://xml.org/sax/features/external-parameter-entities";
dbf.setFeature(FEATURE, false);

// Disable external DTDs as well
FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
dbf.setFeature(FEATURE, false);

// and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);

// And, per Timothy Morgan: "If for some reason support for inline DOCTYPEs are a requirement, then 
// ensure the entity settings are disabled (as shown above) and beware that SSRF attacks
// (http://cwe.mitre.org/data/definitions/918.html) and denial 
// of service attacks (such as billion laughs or decompression bombs via "jar:") are a risk."

// remaining parser logic

} catch (ParserConfigurationException e) {
// This should catch a failed setFeature feature
logger.info("ParserConfigurationException was thrown. The feature '" +
FEATURE + "' is probably not supported by your XML processor.");
}
catch (SAXException e) {
// On Apache, this should be thrown when disallowing DOCTYPE
logger.warning("A DOCTYPE was passed into the XML document");
}
catch (IOException e) {
// XXE that points to a file that doesn't exist
logger.error("IOException occurred, XXE may still possible: " + e.getMessage());
}
DocumentBuilder safebuilder = dbf.newDocumentBuilder();