微信支付SDK JAVA版今天曝出了XXE漏洞,主要原因是在使用DOM处理回传的XML格式的支付结果通知时,未禁用外部实体、参数实体、内联DTD等,导致存在XXE漏洞。
0x01 原理分析
作者原文分析提到在看微信支付JAVA SDK的说明文档时,发现了结果通知代码示例:
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import java.util.Map;
public class WXPayExample {
public static void main(String[] args) throws Exception {
String notifyData = "...."; // 支付结果通知的xml格式数据
MyConfig config = new MyConfig();
WXPay wxpay = new WXPay(config);
Map notifyMap = WXPayUtil.xmlToMap(notifyData); // 转换成map
if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
// 签名正确
// 进行处理。
// 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功
}
else {
// 签名错误,如果数据里没有sign字段,也认为是签名错误
}
}
}
其中notifyData是攻击者可控的,再看微信支付JAVA SDK中的WXPayUtil.xmlToMap()方法,代码片段如下:
public class WXPayUtil {
/**
* XML格式字符串转换为Map
*
* @param strXML XML字符串
* @return XML数据转换后的Map
* @throws Exception
*/
public static Map xmlToMap(String strXML) throws Exception {
try {
Map data = new HashMap();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
//未使用setFeature()方法来禁用外部实体、参数实体、内联DTD等。
DocumentBuilder documentBuilder = documentBuilderF