我伪造了一条支付宝回调,0元买到了iPhone:支付结果通知验签缺失的致命漏洞
原创
逍遥
逍遥
昆仑AI安全实验室
2026年8月15日 02:38
广东
在小说阅读器读本章
去阅读
上个月在某电商平台挖SRC,我发现了一个让我兴奋得手抖的接口。正常下单后不支付,抓包分析支付回调流程,发现了一个隐藏在订单服务里的API:POST /api/v1/order/pay/callback。这个接口不校验来源、不验签、不验证金额,只要收到请求就无条件把订单状态改成“已支付”。我构造了一个简单的JSON请求发过去,订单状态瞬间从“待支付”变成了“已支付”。价值8999元的手机,就这么“买”下来了。
这不是什么高深的技术,也不需要绕过任何防火墙。这就是2026年仍然在大量平台上存在的支付结果通知伪造漏洞。今天把这套攻击链完整复盘,从原理、利用、到防御,全公开。
一、支付回调的工作流程,以及它为什么是个漏洞重灾区
当一个用户在电商平台下单并选择支付宝/微信支付时,系统会经过以下流程:
- 前端调用下单接口,后端生成订单,调用支付宝API创建支付订单。
- 支付宝返回支付页面或支付二维码,用户完成支付。
- 支付宝异步通知平台后端,发送一个POST请求到平台配置的回调地址。
- 平台后端收到通知后,验证签名、验证金额、验证订单号,确认无误后更新订单状态为已支付。
问题出在第4步。开发者在实现回调接口时,经常漏掉验签这一步。 他们可能觉得“反正支付宝回调的地址只有支付宝知道,攻击者怎么会找到这个地址?”于是把回调接口写成了不验签、不验证来源、不验证金额的“三无”接口。
但现实是,回调接口的地址很容易被猜到或通过JS文件泄露。很多平台的回调地址就是/api/order/callback、/api/pay/notify、/api/alipay/return这种固定格式。通过分析前端JS里的API路由,或者干脆用字典爆破,都能找到它。
二、实战:从下单到伪造回调的完整攻击链
以下是授权测试的脱敏案例。
第一步:抓包分析下单和支付流程
我注册账号,提交订单买一个商品。打开Burp Suite,观察整个流程:
- 下单请求:
POST /api/v1/order/create,返回了订单号order_id=20260816001。 - 跳转支付宝:前端调用了
GET /api/v1/order/pay?order_id=20260816001,返回了支付宝的支付链接。 - 我没有支付,而是观察前端在支付完成后的行为。果然,前端在支付完成后会调用
GET /api/v1/order/status?order_id=20260816001来轮询订单状态。
第二步:寻找回调接口
通过分析前端JS文件,搜索callback、notify、pay_result等关键词,我找到了一个隐藏的API:POST /api/v1/order/pay/callback。请求体模板如下:
{ \"order_id\": \"20260816001\", \"trade_no\": \"2026081622001\", \"total_amount\": \"8999.00\", \"sign\": \"xxx\"}
第三步:构造伪造的回调请求
我把请求体里的order_id改成我的订单号,trade_no随意生成一个,total_amount填0.01,然后发送。服务器返回:
{\"code\":200,\"message\":\"支付成功\",\"data\":null}
我刷新订单页面,状态已经从“待支付”变成了“已支付”。整个过程只花了两分钟,没有触发任何风控。
三、为什么验签缺失会导致这么大漏洞?
支付回调的本质是“信任”。平台必须确认三件事:
- 来源可信:这个请求确实是支付宝/微信发来的,而不是攻击者伪造的。
- 金额一致:支付金额和订单金额必须完全相等。
- 订单号一致:支付对应的订单号和平台内部订单号必须匹配。
验签缺失,意味着第1件事完全失控。攻击者无需知道支付宝的任何信息,只需要知道回调接口的地址,就能随意伪造支付结果。
更糟的是,很多平台即使做了验签,也存在两个致命问题:
- 验签逻辑用了错误的公钥:比如用支付宝开放平台的应用公钥去验签,而应该用支付宝公钥。结果是验签永远失败,开发者在调试时直接禁用了验签。
- 验签只验证了签名存在,没验证签名内容:简单判断
if (sign != null)就算验签通过,而不是真正用RSA算法去比对。
四、实战案例:一次真正“0元购”的全过程
在上面那个电商平台的测试中,我不仅伪造了回调,还发现了更大的问题。
越权支付:回调接口不校验order_id的归属。我把order_id改成另一个用户的待支付订单,同样能把它标记为已支付。这意味着我可以给任意订单“免费付款”。
金额篡改:平台在回调时不校验total_amount是否和订单金额一致。我甚至可以不传金额字段,直接传order_id,系统照样把订单置为已支付。
组合利用:我先创建一个订单,把收货地址改成自己,然后伪造回调,0元购成功。再结合一个水平越权漏洞,我可以查看其他用户的订单详情,挑选高价值商品来“购买”。完整攻击链:越权查看订单 → 伪造回调 → 0元购 → 发货到自己地址。
测试了三个订单,包括一部手机、一台笔记本电脑和一套化妆品,全部“支付成功”。当然,最终全部在SRC报告中提交,平台修复后给了丰厚赏金。
五、如何系统性地挖掘这类漏洞?
第一步:找到支付功能。 注册账号,走一遍完整的支付流程,抓包分析所有与支付相关的接口。
第二步:枚举回调接口。 常见路径:
/api/pay/callback、/api/pay/notify、/api/pay/return/api/order/callback、/api/order/notify/api/alipay/callback、/api/wechat/callback/notify/alipay、/notify/wechat
第三步:分析请求体结构。 如果平台使用支付宝,回调参数通常是out_trade_no、trade_no、total_amount、sign等。微信支付则是transaction_id、out_trade_no、total_fee、sign。但不同平台的内部封装可能不同,关键是从前端JS或API文档中寻找线索。
第四步:测试验签是否缺失。 构造一个伪造的回调请求,不携带sign字段,或者携带一个随机字符串作为sign。如果服务器返回成功,则验签缺失。
第五步:测试金额校验。 如果验签存在但金额校验缺失,那么修改total_amount字段为极小值,看看系统是否接受。
第六步:测试订单归属。 如果验签和金额校验都通过,那么测试order_id是否可被替换为其他用户的订单号。
第七步:组合利用。 将回调伪造与其他漏洞(越权、信息泄露)结合,扩大危害范围。
六、防御:正确的回调验签方案
服务端强制验签:
- 使用支付平台官方提供的SDK或验签方法。
- 使用正确的公钥(支付宝公钥,不是应用公钥)。
- 验签失败直接拒绝,不返回任何业务数据。
金额一致性校验:
- 将回调中的金额与服务端订单金额进行比对,不一致则拒绝并告警。
订单归属校验:
- 从服务端数据库中查询订单,确认订单存在且状态为待支付。
防止重放:
- 记录已处理的回调流水号,防止同一回调被重复处理。
日志与监控:
- 对回调接口的每次调用做详细日志,异常的验签失败应触发告警。
七、写在最后
支付回调伪造是电商系统最古老、最致命、也是出现频率最高的逻辑漏洞之一。2026年的今天,它依然在各大平台上肆虐。原因很简单:开发人员总是低估攻击者的侦察能力,以为一个“不为人知”的回调地址就能高枕无忧。
如果你在做SRC测试,遇到支付功能,花半小时分析一下回调接口。说不定,下一个0元购的漏洞就在等着你。如果你在开发支付系统,请务必使用官方SDK的验签方法,不要自己造轮子,更不要把验签当成可有可无的装饰品。
毕竟,你的一个疏忽,可能让平台一夜之间损失数百万。
严正声明
本文所述技术仅用于合法授权的安全测试,所有案例均已脱敏。利用支付漏洞进行未授权操作属于违法行为,与作者无关。请在SRC平台授权范围内进行测试,遵守法律法规。
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论