#581·litemall

[漏洞] 由于 TOCTOU 竞争导致优惠券过度索赔

作者: Leeziao创建于 2026年7月22日更新于 2026年7月22日

linlinjava/ liteball在"POST/wx/coup/收"中有一个TOCTOU比赛. 在64个同时提出的申请后,以 " 总数=1 " 和 " 限额=1 " 为种子的券产生了9个索赔行。

详细情况

WxCoupon Captain.receive ' 计算现有索赔,检查总数'和每个用户的限额',然后插入一项索赔,不作交易性的原子保留(litecall-wx-api/./WxCaptain.java:192-203,228-244')。

贾瓦 整数总计 Couupons = 优惠券用户服务. counts Coupon(couponId) ; 如果( 总计 Coupons QQ 总计) 返回优惠券 限制; 整数用户 Coumpons = 券用户服务. counts User And Coupon(用户ID, 券用户) ; 如果( 用户 Coups QQ 限制) 返回优惠券 限制; $. $. add( coupon User) ; $.


• PoC

8. 登录为`user123/user123',并使用返回的代号。

NORMAL -- -- 两次接连提出的`1001 ' 票证请求:

页:1
{"errno":0,"errmsg":"成功""成功"}
{"errno":740,"errmsg":"优惠券已领完"]

VULNERBALE-只清除本地测试行,然后发送64个并行请求:

嘘 (单位:美元) 卷起- X POST 'http://127.0.0.1:18182/wx/coupon/收'\ -H"X-Litecall-Token:$Token" (韩语). -H'Content-Type:应用程序/json'
-d"{"couponId":1001}" >"/tmp/litemall-race-$. 已执行 单单


观测到的反应分布:`36'成功的反应。 用`Docker ' 组成执行db ' 返回`36'行的 " 1001 " 票券进行查询,但`总数=1'和`限额=1'。

<img宽=""1706"高="176" alt="Image" src="https://GitHub.com/user-attachments/assets/d317b083-8cff-4898-a4a-7766ca14ac60"/".

影响

一个经认证的用户可以获得比配置的全球和每个用户限制更多的有限优惠券。 观察到的8个券被超额发行.

建议的修补

以原子条件更新或受独特约束和锁定的计数器保护的交易保留优惠券. 保留影响无行时返回失败 .

内容来源: linlinjava/litemall