youpaishidifu
|
e6f6188ab8
|
加固-09(P0-07): 支付加固——Host 头投毒、卡密/代理余额原子核销、epay 库 PHP8 致命、回调落库幂等
1. Host 头投毒(R8):payment.php 的回调/跳转 URL 原用 $_SERVER['HTTP_HOST']
拼接,被污染的 Host 头可使 ePay notify/return 回调指向攻击者域名
- function/function_core.php 新增 wq_site_base_url():host 优先取配置
weburl 的 scheme+host 部分(配置由管理员维护,非攻击面),仅配置缺失
时回退 HTTP_HOST;路径取当前请求挂载目录并归一化 Windows dirname 的
反斜杠(兼容子目录部署)
- payment.php 免费订单跳转、czkm/yezf 支付成功跳转、mqyturn 的
notify/return 回调 URL 全部改用该 helper
2. 卡密/代理余额原子核销(双花消除):payment.php 的 czkm(卡密)与
yezf(代理余额)原为「读取-校验-写回」,并发下同一卡密/余额可被
重复扣减
- 订单占用:条件 UPDATE(WHERE status='1'),affected_num()==0 即
中止,防同订单并发重复支付
- 卡密核销:UPDATE ... WHERE kami=? AND status='1' AND lastmoney>=?
,前置条件并入 WHERE;affected_num()==0 时回滚订单占用并提示重试
- 代理余额:UPDATE ... WHERE status='1' AND money>=? 同理
- 顺带修复 yezf 原 bug:allspend 只读进内存从未落库,现随余额
原子累加
3. epay 库 PHP8 致命(R10):pay/epay/lib/epay_core.function.php
- 两处 get_magic_quotes_gpc()(PHP8 已移除,调用即致命)改为
function_exists 守卫
- createLinkstringUrlencode 的 count($arg)(对字符串,PHP8 TypeError)
改为 strlen($arg)-1(与 PHP7 下实际行为 substr(0,-1) 等价)
- 已在 PHP 8.2 实测:两函数正常拼接/验签准备,无致命
4. pay/epay/notify_url.php / return_url.php:
- 移除 notify_url.php 中用未定义 $lastmoney/$allspend 更新代理表的
语句(PHP7 下 null 隐式转空串,回调时把代理余额与 allspend 清零;
与 return_url.php 的既有行为对齐)
- 订单状态落库改为条件 UPDATE(WHERE status='1'),并发回调重复
落库防护;status=2 分支保持幂等 success
- return_url.php 对称条件化
回归(P0-07 全 PASS,8082 内置服务器 + 8081 nginx 双通道冒烟):
- 免费订单/czkm/yezf 跳转 URL 全部使用配置 host;Host:evil.example.com
投毒无效
- czkm 正常核销、余额不足拒绝;双进程并发两订单恰好一个成功,
卡密余额恰扣一次(无双花),核销日志 +1
- yezf 正常扣减 100->70;并发双订单恰好一个成功,余额 70->30 只扣
一次,allspend 只累加一次
- epay 库 PHP 8.2 下 createLinkstring / createLinkstringUrlencode 无致命
- 注:本地内置服务器为单 worker,并发请求实际串行处理;双花消除的
保证来自 WHERE 原子前置条件(真实多 worker 并发下亦至多一个
UPDATE 满足条件)
|
2026-10-10 13:07:10 +08:00 |
|