CYH博客CYH博客

天行健,
君子以自强不息。

某充值功能前后精度处理逻辑不一致导致的折价充值

背景描述

最开始知道这种缺陷是之前听月神在360BugClound的分享,后来自己挖到后,自己的感触更深了一些。

漏洞概述

折价充值:指所支付的实际金额低于储值卡的面值。

某充值功能前后精度处理逻辑不一致导致的折价充值(图1)

一个储值卡购买的功能,100元的充值面额的实际支付是100元。

但是这个漏洞最大可实现实际支付100元,充值200元,折价50%的效果。

详细说明

点击去支付时,会先创建订单、再进入支付环节。

创建订单时,修改cardDenomination参数的值为0.019元

某充值功能前后精度处理逻辑不一致导致的折价充值(图2)

在微信支付中,最小精度是0.01,处理原则是去尾法,即若是你传给微信支付的数值是0.019元时,那么它实际需要支付的是0.01元。

某充值功能前后精度处理逻辑不一致导致的折价充值(图3)

在该充值功能中,最小精度也是0.01,但是处理原则却用的四舍五入,即若是你传给现金卡订单中的面额是0.019元时,那么它会认为你充值的是0.02元。

某充值功能前后精度处理逻辑不一致导致的折价充值(图4)

至此,便可以实现充值0.01元获得0.02元,折价50%的效果。

另外若是觉得比较慢的话,还有另一种方式快速获利。

在购买现金卡时可以修改购买的数量,假设将单价设置为0.015,将数量设置为1w

那么实际需要支付0.015*1w=150元,而实际充值了0.02*1w=200元,折价75%的效果。

某充值功能前后精度处理逻辑不一致导致的折价充值(图5)

充值成功后,点击上面这个【充入账户余额】可以将刚才设置的所有现金卡全部冲入账户余额,不用一张一张的点击充值。

某充值功能前后精度处理逻辑不一致导致的折价充值(图6)

真相

于是我到代码中去尝试寻找真相,一直追踪到数据库,大概发现了真相:

首先在代码中并没有做严谨的限制,导致保留2位小数这个功能更多的是依赖于数据库。

该项目在MySQL中用了decimal(20,2)数据类型,来限定金额保留2位小数,当插入的数据超过2位小数时,则会用四舍五入的形式进行保留。

测试一下看看

某充值功能前后精度处理逻辑不一致导致的折价充值(图7)

而微信支付的接口用的是去尾法。

另外我发现很多编程语言,默认使用的都是四舍五入的处理方式,下面是Python里面的format方法。

某充值功能前后精度处理逻辑不一致导致的折价充值(图8)


未经允许不得转载:CYH博客 » 某充值功能前后精度处理逻辑不一致导致的折价充值
分享到: 更多 (0)

CYH博客 带给你想要内容

联系我