【Web安全】逻辑漏洞之支付漏洞:原理、场景与防御
摘要: 支付漏洞是Web安全中危害严重的逻辑漏洞,攻击者通过篡改订单生成阶段的参数(如金额、商品ID、折扣等),利用服务器校验缺陷实现低价或免费支付。常见场景包括隐藏商品购买、付费功能绕过、订单类型篡改等。检测方式包括黑盒测试(参数篡改)和白盒审计(校验逻辑排查)。防御核心在于服务器端严格掌控关键参数,如金额重算、参数签名、权限校验等。开发需遵循“不信任客户端”原则,确保支付流程安全可靠。
文章目录
往期文章
前言
在Web应用的逻辑漏洞体系中,支付漏洞因其直接关联资金安全而成为攻击者的重点目标。这类漏洞并非依赖复杂的代码执行,而是利用支付流程中对关键参数(如金额、商品标识、订单状态)的校验缺陷,让攻击者以非正常方式完成支付(如低价购买高价商品、免费获取付费服务)。本文将深入解析支付漏洞的原理、典型场景及防御策略。
一、漏洞本质
支付漏洞的核心是服务器对支付流程中关键参数的校验逻辑失效。正常支付流程中,商品金额、订单状态、支付方式等核心信息需经过严格的合法性与一致性校验;而存在漏洞时,系统可能直接信任客户端传递的参数、省略关键环节的验证,或对业务规则的边界判断模糊,导致攻击者可通过篡改参数等方式绕过正常支付逻辑,获取不当利益。
简单来说,就是“该算的钱算错了,该拦的支付放过了”。
二、攻击原理
正常支付流程
- 用户选择商品并提交购买请求;
- 服务器生成订单(包含商品ID、金额、折扣、订单类型、状态等关键信息),返回订单详情;
- 用户发起支付(如调用支付接口、跳转第三方支付);
- 服务器校验支付信息(金额是否匹配订单、订单状态是否为“待支付”等);
- 支付完成后,服务器更新订单状态为“已支付”,并触发商品交付逻辑。
漏洞触发流程
支付漏洞的核心在于某一环节的校验缺失,典型链路如下:
- 攻击者在订单生成阶段抓取请求(如包含
price=100
的订单创建请求); - 篡改关键参数(如将
price=100
改为price=1
); - 服务器未重新校验参数合法性(如未根据商品ID重新计算金额),直接按篡改后参数生成订单;
- 攻击者按篡改后金额完成支付,获取原价商品或服务。
攻击链路可概括为:攻击者 → 抓取订单生成请求 → 篡改支付相关参数 → 服务器未校验 → 以异常价格完成支付
三、抓包的时机选择:生成订单时
支付流程中,订单生成阶段是抓包的关键时机。原因在于:
订单生成时,系统会将商品信息(ID、单价)、用户信息(会员等级、优惠券)、活动规则(折扣、满减)等整合为订单参数(如goods_id=101&price=299&discount=0.9&order_type=1
),这些参数直接决定后续支付金额和权益。
若此时未对参数进行服务器端固化,攻击者可通过 BurpSuite 工具抓取请求,篡改参数后重放,而后续的支付、订单确认等环节可能基于已篡改的订单信息处理,最终导致支付漏洞。
例如:用户购买“299元运动鞋”,生成订单的请求为POST /api/createOrder {goods_id:101, price:299}
,攻击者抓包后将price
改为9.9
,若服务器直接信任该参数,订单金额就会被改为9.9元,攻击者支付后即可获得商品。
四、风险场景
支付漏洞的风险场景因业务逻辑不同而多样,以下为典型场景:
1. 隐藏商品购买(开发人员预留的测试商品)
开发阶段,工程师常预留测试商品(如0元商品、内部折扣商品)用于功能测试,若测试完成后未删除或隐藏,且后端未限制访问权限,攻击者可能通过篡改商品ID访问这些隐藏商品。
典型案例:
某电商平台开发时预留测试商品goods_id=9999
(原价1000元,测试价0元),但未从商品列表中移除。攻击者通过抓包发现正常商品请求为goods_id=100-200
,尝试将goods_id
改为9999
后提交订单,服务器未校验该商品是否对普通用户可见,直接生成0元订单,攻击者支付0元即可获得商品。
2. 付费功能免费使用(添加付费参数:JS中查询、先买个会员抓包查看)
付费功能(如会员服务、高级工具)的权限控制常依赖参数标识(如is_vip=0
代表非会员,service_type=free
代表免费服务),若服务器未校验参数与用户实际权限的一致性,攻击者可通过篡改参数绕过付费验证。
两种常见实现方式:
- JS中查询参数:前端JS代码可能隐藏付费参数(如
pay_status=0
代表未付费),攻击者通过查看JS源码发现后,在请求中改为pay_status=1
,服务器直接信任该参数,允许免费使用付费功能(如高清视频、高级模板)。 - 抓包对比参数:攻击者先正常购买低价会员(如1元体验会员),抓取会员权限请求(如
vip_level=1
),后续将普通账号的请求参数改为vip_level=3
(高级会员),若服务器未校验用户实际会员等级,即可免费享受高级权益。
3. 修改订单类型(0 改成 -1、1、2、3)
订单类型参数(如order_type
)通常关联不同的价格规则(如0=普通订单
、1=会员折扣单
、2=活动特惠单
、-1=测试订单
),若服务器未限制order_type
的合法取值范围,攻击者篡改类型值可触发异常价格计算。
典型案例:
某平台order_type=0
时商品按原价计算(100元),order_type=-1
为内部测试订单(默认价格0元)。攻击者在生成订单时,将order_type=0
改为order_type=-1
,服务器未校验该类型是否允许普通用户使用,直接按0元生成订单,导致攻击者免费获取商品。
注:实际在SRC挖掘该类型漏洞时,不要把 1 改成 0 发现没用就放弃,可以多尝试几个值。
4. 修改通用参数(自动计算最终折扣)
系统常根据优惠券、会员等级自动计算最终折扣(如discount=0.8
代表8折、coupon_id=100
代表减50元),若服务器未校验折扣参数的合法性(如是否存在该优惠券、折扣是否符合规则),攻击者可篡改参数降低支付金额。
典型案例:
用户购买1000元商品,使用8折券后应付800元,请求参数为discount=0.8&coupon_id=100
。攻击者抓包后将discount
改为0.1
,并伪造coupon_id=999
(不存在的1000元优惠券),服务器未重新校验折扣合理性及优惠券有效性,直接计算金额为1000×0.1 - 1000 = -900元(甚至倒赚),导致支付逻辑异常。
五、检测方式
1. 黑盒测试:模拟攻击流程
- 识别关键参数:在订单生成环节,抓取请求并标记支付相关参数(如
goods_id
、price
、order_type
、discount
、coupon_id
)。 - 执行参数篡改:
- 篡改金额(如
price=100
→price=1
); - 替换商品ID(尝试非公开ID,如
9999
、0000
); - 修改订单类型(如
0
→-1
、3
); - 伪造折扣参数(如
discount=0.01
、coupon_id=9999
)。
- 篡改金额(如
- 验证结果:提交篡改后请求,若订单金额异常、可访问隐藏商品或免费使用付费功能,说明存在漏洞。
2. 白盒审计:代码层校验逻辑排查
- 检查订单生成接口(如
createOrder
)是否对关键参数进行服务器端重算:- 金额是否基于
goods_id
从数据库查询后计算,而非直接使用客户端price
; order_type
是否限制在合法枚举值内(如仅允许0、1、2
);- 折扣和优惠券是否通过服务器端接口验证有效性(如
coupon_id
是否存在、是否在有效期内)。
- 金额是否基于
- 检查支付回调逻辑:是否验证支付金额与订单金额的一致性(避免支付1元却确认100元订单)。
六、防御方案
支付漏洞的防御核心是服务器端“绝对掌控”关键参数,不依赖客户端传递的数据,具体措施如下:
1. 严格校验关键参数
- 金额与商品强绑定:服务器端根据
goods_id
从数据库查询单价,结合商品数量、活动规则重新计算金额,忽略客户端传递的price
参数。 - 限制参数取值范围:对
order_type
、discount
等参数设置白名单(如order_type
仅允许0、1、2
),拒绝非法值。 - 校验权限与参数匹配性:会员等级、优惠券等参数需与当前用户信息比对(如
vip_level
必须从用户数据库查询,而非使用客户端值)。
2. 订单信息固化与签名
- 生成订单时,对关键参数(
goods_id
、计算后金额、order_type
)进行加密签名(如使用安全的哈希算法(如SHA256)加盐),并将签名存入订单记录。 - 后续支付、确认环节需验证签名,若参数被篡改,签名不匹配则拒绝处理。
3. 管理商品与订单合法性
- 维护“合法商品列表”,拒绝不在列表中的
goods_id
(如删除测试商品,或标记为“仅内部可见”并校验访问权限)。 - 订单状态流转需严格校验(如“已支付”状态只能由支付回调接口更新,禁止客户端直接修改)。
4. 日志与监控
- 记录所有订单生成、支付、参数修改的操作日志(包含用户ID、IP、参数原值与篡改值、操作时间)。
- 对异常行为实时告警(如金额骤降90%、使用不存在的商品ID、频繁修改
order_type
)。
七、总结
支付漏洞是逻辑漏洞中危害最直接的类型,其本质是服务器对支付流程中关键参数的校验缺失。从隐藏商品的非法访问到折扣参数的恶意篡改,攻击者的核心手段始终围绕“篡改订单生成阶段的参数”,而防御的关键在于让服务器成为参数的唯一决策者。
开发人员需牢记:客户端传递的任何支付相关参数都不可信,必须通过服务器端的重新计算、权限校验、签名验证来确保支付逻辑的完整性。只有将“不信任客户端”的原则贯穿支付流程设计,才能有效防范支付漏洞,保障资金安全。
本文是「Web安全基础」系列的第 6 篇,点击专栏导航查看全部系列内容。
更多推荐
所有评论(0)