微信支付XXE漏洞修复解决办法

@tz

根据微信官方回复消息

1、您更新的只是官方SDK的部分代码,没有完全更新,或者在SDK外还使用了XML的解析没有防XXE

2、您可能有多个回调地址,而你只修复了其中一个

3、您可能有多个服务器,你只发布了其中一台或者修改了没有正式发布

4、实际做xml解析的不是修改的地方

5、xml解析器和httpclient存在多个版本,有冲突,pom.xml可以查看jar版本号。

修改过程

public final class WXPayXmlUtil {
    public static DocumentBuilder newDocumentBuilder(){
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = null;
        try {
			documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
			documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
	        documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
	        documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
	        documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
	        documentBuilderFactory.setXIncludeAware(false);
	        documentBuilderFactory.setExpandEntityReferences(false);
	        documentBuilder  = documentBuilderFactory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		return documentBuilder;
    }

    public static Document newDocument() {
        return newDocumentBuilder().newDocument();
    }
/**
	 * 解析微信发来的请求(XML)
	 * 
	 * @param request
	 * @return
	 * @throws Exception
	 */
	public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
		
		// 将解析结果存储在HashMap中
		Map<String, String> data = new HashMap<String, String>();
		try {
            DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
            InputStream stream = request.getInputStream();
            org.w3c.dom.Document doc = documentBuilder.parse(stream);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getDocumentElement().getChildNodes();
            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                Node node = nodeList.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                    data.put(element.getNodeName(), element.getTextContent());
                }
            }
            stream.close();
        } catch (Exception ex) {
        	System.out.println("Invalid XML, can not convert to map. Error message: {}.XML content: {}"+ ex.getMessage());
        }
		return data;
	}
/**
     * XML格式字符串转换为Map
     *
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static Map<String, Object> parseXml2Map(String strXML) {
    	Map<String, Object> data = new HashMap<String, Object>();
        try {
            DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
            org.w3c.dom.Document doc = documentBuilder.parse(stream);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getDocumentElement().getChildNodes();
            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                Node node = nodeList.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                    data.put(element.getNodeName(), element.getTextContent());
                }
            }
            stream.close();
        } catch (Exception ex) {
        	System.out.println("Invalid XML, can not convert to map. Error message: {}.XML content: {}"+ ex.getMessage()+ strXML);
        	System.out.println(ex.getMessage());
        	System.out.println(strXML);
        }
		return data;
    }
/**
     * 将Map转换为XML格式的字符串
     *
     * @param data Map类型数据
     * @param rootElement 文件类型
     * @return XML格式的字符串
     * @throws Exception
     */
    public static String parseMap2XML(Map<String, Object> data,String rootElement) {
        org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
        org.w3c.dom.Element root = document.createElement(rootElement);
        document.appendChild(root);
        for (String key: data.keySet()) {
        	String value = String.valueOf(data.get(key));
            if (value == null) {
                value = "";
            }
            value = value.trim();
            org.w3c.dom.Element filed = document.createElement(key);
            filed.appendChild(document.createTextNode(value));
            root.appendChild(filed);
        }
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = null;
        StringWriter writer = null;
        String output  = null;
		try {
			transformer = tf.newTransformer();
			DOMSource source = new DOMSource(document);
	        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
	        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
	        writer = new StringWriter();
	        StreamResult result = new StreamResult(writer);
			transformer.transform(source, result);
			output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
			writer.close();
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}
        return output;
    }

项目使用部分SDK,直接修改需要对XML转换处理根据SDK更改成自己需要的。仅供参考,目前官方技术人员提示已经修复完成。

猜你喜欢

转载自blog.csdn.net/qq_26387907/article/details/83270973
今日推荐