微信支付XXE漏洞修復解決辦法
阿新 • • 發佈:2018-11-21
@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更改成自己需要的。僅供參考,目前官方技術人員提示已經修復完成。