最近测试了某单位的他们自己内部日常用来吃饭下单的微信小程序,功能很简单,就是常规的点单->下单->扫码付款->获取核销二维码->吃饭,也没有其他的功能模块测试,接手时听说这个小程序每季度都会按列测试一遍,到我这也是不知道经过几手了,本想着应该没有什么价值漏洞,估计就是走个流程,但接下来抓包分析,感觉这整个流程好像是有点逻辑问题了,最后也是成功发现了一个隐藏比较深的逻辑支付漏洞,找到关键性的args后就可以随便修改商品价格吃任何东西了,比如原本30块的牛肉面,一毛钱就可以吃了~
数据包的分析
漏洞界面如下
点击提交订单后,会发送三个数据包,其中两个数据包中携带订单消息

重点来了,这里不少人看到这两个数据包的订单金额,都会全部修改来测试是否存在支付漏洞,但经过我测试全部修改会直接导致服务器响应异常,提示订单异常,无法下单。到这里可能大部分人就觉得没戏了。但仔细分析一下数据包逻辑,就会发现一点端倪。经过分析,第一个数据包是用来将订单凭证存入服务器,并且这个数据包没有任何的防篡改签名机制,所以这个修改这个数据包的金额是直接可以修改商品价格,而第二个数据包是是用来查询商品消息并返回给客户端的,所以这条数据包中订单的信息是不能修改的,以为如果修改会导致服务器查询不到对应的商品信息,从而导致下单失败。
有了上述的这个逻辑,接下来就开始验证,直接修改第一个数据包的参数,将30元改成0.1后放过,第二个数据包不做任何改动直接放过
这样就顺利的将订单凭证存入服务器而不触发异常,直接跳出付款二维码 ,用微信付款
后续所有数据包都不需要修改,就可以看到生成的订单信息

分析
这个漏洞利用非常简单,但想要发现这个漏洞可能会有点难度,因为按照常规思维,提交订单后,发现发送的两个数据包中都写到订单参数,很多人都会下意识的把这个两个参数全部都修改,那基本就发现不了这个漏洞了。同时这个订单凭单的生成和处理逻辑问题真的很大,没有任何的安全处理措施,只要能分析出第一步(只修改第一个数据包,后面所有数据包全都保持不动),将修改后金额存入服务器缓存后,那真就如入无人之境,顺便下单吃喝了。
修复建议
- 针对重要数据添加非堆成加密,同时数据包附带签名防止篡改
- 订单金额应由服务端根据商品ID和数量重新计算,禁止直接信任客户端提交的价格参数
- 对订单状态和支付金额进行二次校验,确保支付金额与订单金额一致