解决微信支付XXE漏洞
近期腾讯打电话过来和运维说,公司的运营系统微信支付存在XXE漏洞,刚开始以为是什么难的问题,经过查资料原来是xml注入漏洞,腾讯也早有意识到这方面的问题,并且提供了解决方案:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=23_5。
查阅了相关博客描述,主要原因大致方向是:在微信回调接口中,解析XML转为Map时方法不安全。所以针对这个问题修改toMap方法。
修改这个方法,加上一些安全过滤属性,包括: 禁用xml中的inline DOCTYPE,xml外部实体注入,禁用实体参数Entity,解析xml时忽略dtd声明。
微信官方已更新最新的SDK解决方案是通过DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();的方式,而公司用的是微信比较旧版本的SDK,解析XML使用DocumentHelper,存在XXE漏洞
后面我改成SAXReader解析xml方式,具体代码如下。
public static Map toMap(String xml){
Map map=new HashMap();
try {
SAXBuilder builder = new SAXBuilder();
SAXReader reader = new SAXReader();
InputSource source = new InputSource(new StringReader(xml));
Document document = reader.read(source); //DocumentHelper.parseText(xml);
String FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
builder.setFeature(FEATURE, true);
FEATURE = "http://xml.org/sax/features/external-general-entities";
builder.setFeature(FEATURE, false);
FEATURE = "http://xml.org/sax/features/external-parameter-entities";
builder.setFeature(FEATURE, false);
FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
builder.setFeature(FEATURE, false);
Element nodeElement = document.getRootElement();
if(nodeElement!=null){
map.put(nodeElement.getName(),null);
List node = nodeElement.elements();
if(node!=null){
map.put(nodeElement.getName(),new HashMap());
for (Iterator it = node.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
((Map)map.get(nodeElement.getName())).put(elm.getName(), elm.getText());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
SAXReader 需要依赖导入jdom.jar包。
发布到项目中,部署公网后,使用微信企业账号登录微信官网,到[安全医生]模块进行站点安全扫描,结果通过安全检测。
finally, 问题解决!
--------------------------------------------------------------------->>[Every problem has its solutions]