逻辑漏洞挖掘实战:从越权到竞态条件,比SQL注入更难防

发布时间:2026/10/10 12:43:26
逻辑漏洞挖掘实战:从越权到竞态条件,比SQL注入更难防 1. 逻辑漏洞到底是什么为什么它比SQL注入还难防做了这么多年安全测试我有个特别深的感触很多团队把WAF、RASP、漏洞扫描器堆了一整套SQL注入、XSS这种常规问题倒是堵得死死的结果业务上线没几天就被一个看起来不像漏洞的漏洞打了脸——逻辑漏洞。逻辑漏洞Logic Vulnerability说白了就是业务逻辑层面的缺陷。它不是数据库语法出了问题也不是代码执行了不该执行的命令而是程序处理业务请求时对状态的判断、对流程的约束、对权限的校验不到位导致攻击者可以用合法的方式做非法的事。我经常拿一个比喻来解释SQL注入像是有人从窗户翻进你家而逻辑漏洞更像是你给了外卖小哥门禁密码结果他顺手把密码贴在了楼道里——所有操作看着都合理但系统不该允许它发生。传统漏洞和逻辑漏洞最大的区别在于前者是工程问题代码写错了修掉就行后者是设计问题代码可能一行都没写错但业务规则本身就有漏洞。比如订单金额由前端传参决定代码逻辑完全正常但业务设计就是错的。这也是为什么漏洞扫描器几乎扫不出逻辑漏洞——它不了解你的业务而业务恰恰是逻辑漏洞的主战场。这篇文章适合谁看如果你在学渗透测试、在做安全评估、或者你是后端开发想了解自己系统哪里容易被薅羊毛都值得往下看。我尽量把这么多年踩过的坑、总结出的方法论一次讲透。2. 逻辑漏洞常见类型盘点每种背后的业务原因逻辑漏洞的类型说多不多说少不少但万变不离其宗。我按业务场景把它们分成六大类每一类背后都有明确的业务缺陷原因。2.1 越权漏洞最经典也最容易批量发现的一类越权分两种水平越权平行越权和垂直越权纵向越权。水平越权就是你操作了和你同级别的人的资产。最常见的就是改了ID就访问到别人的数据。比如一个查看订单详情的接口URL是/api/order/detail?id1001服务端只校验了用户是否登录但没有校验这个订单是不是属于当前用户。那我登录自己的账号把id改成1002、1003一路遍历下去就能看到别人的订单、手机号、收货地址。垂直越权就是你干了比你权限高的人才能干的事。比如普通用户调用了管理员的接口/api/admin/deleteUser服务端没做角色校验。这类漏洞在管理后台和用户前台共用一套后端服务的系统里特别常见。越权漏洞的根因就一句话服务端只校验了你是谁没有校验你有没有权限碰这个资源。所谓基于对象的授权校验缺失英文叫Broken Object Level AuthorizationBOLA在OWASP API Top 10里常年排第一不是没道理的。2.2 支付与订单逻辑薅羊毛的重灾区支付逻辑漏洞应该是逻辑漏洞里含金量最高的因为直接影响钱。最常见的有金额参数前端可控下单时把价格参数放在请求体里比如{goods_id:1, price:100}。攻击者直接把price改成0分钱下单甚至改成负数比如-100这样不但不花钱账户还可能到账100块。有些系统最终和支付平台结算时用的又是另一套计算逻辑两边一不一致就出大问题。优惠券/积分重复使用一个优惠码理论上只能用一次但服务端只在前端做了禁用判断或者用session存储已用状态换个会话就能再次使用。订单金额篡改先加购物车价格100然后篡改购物车接口的单价再去结算。如果结算接口信任购物车数据而不重新计价就白嫖了。支付状态回调查验不严支付回调接口只校验签名正确不校验订单号与金额是否匹配或者只校验is_paidtrue没校验业务订单状态攻击者直接构造回调请求就能把未支付订单变成已支付。这一类漏洞的根因是前端传参和服务端计算边界混淆。凡是业务规则里可被用户影响的数据都不能作为计费依据。2.3 密码重置与身份校验绕过密码重置流程里的逻辑漏洞也是高频点而且往往能直接打到账号接管。步骤可跳过正常的重置流程是输入手机号 - 验证码校验 - 设置新密码但有的系统每个步骤都是独立接口攻击者调第一步、绕过第二步、直接调第三步就能给别人账号重置密码。验证码不失效验证码校验通过后服务端不销毁验证码状态同一个验证码可以反复用。更离谱的是有的系统验证码只有4位数字服务端不限制尝试次数直接爆破10分钟就能爆出来。响应包可控有的系统在step2接口的响应里返回了success: true或者直接把token放在响应体里攻击者改一下响应包就能通过前端校验。修改参数指向他人校验验证码接口传入的是phone自己的手机号设置新密码接口传入的却是phone目标手机号两步之间的手机号没有做绑定校验就能用自己手机收到的验证码改别人的密码。这类问题的根因是流程状态共识缺失。一个多步骤流程每一步之间没有建立统一的会话状态凭证每一步都是独立的自然就能跳步和错位绑定。2.4 竞态条件Race Condition并发下的逻辑失控竞态逻辑漏洞在支付、秒杀、优惠券、签到场景里很常见而且是出了名地考验耐心。核心原理是多个请求同时到达服务端竞争访问同一个资源服务端在检查状态和更新状态之间存在时间窗口攻击者利用这个窗口重复发起请求把只能执行一次的操作执行多次。经典的例子一个账户余额100元提现接口逻辑是查询余额 - 判断余额100 - 扣减余额 - 打款。攻击者同时发送10个提现100元的请求如果并发足够高10个请求可能同时通过判断余额这一步然后各自执行扣减和打款结果就是余额被扣成负数但打款打了10笔。我用一句话概括竞态漏洞的根因检查与操作不是原子的中间存在可被并发插入的间隙。服务端的锁没锁住事务没隔离好或者压根没上锁。2.5 短信验证码、邮件轰炸与接口滥用说白了就是业务接口没做频率限制。一个发送短信验证码的接口服务端不限制同一手机号的发送频率攻击者写个脚本循环调用就能让某个手机号收到几百条垃圾短信运营商那边还以为是用户自己在刷。邮件轰炸同理。更隐蔽的是配合业务逻辑的滥用。比如有的系统注册接口会先判断手机号是否已注册攻击者可以利用这个接口做手机号碰撞——批量探测哪些手机号是平台用户为后续钓鱼和撞库做准备。这类问题的本质是业务资源的无限制消耗既不涉及越权也不涉及金额但危害是实打实的——骚扰用户、消耗短信成本、拖慢服务。2.6 接口数据篡改与越权叠加这类要结合具体业务来看。比如一个积分商城兑换商品接口参数是{product_id: 88, points_cost: 100}攻击者把积分消耗改成0就免费换到了商品。再比如一个简历编辑接口参数里带了user_type1代表普通用户改成user_type2代表VIP就能解锁VIP专属功能。这类漏洞的根因更直接服务端相信了不该相信的客户端数据。但凡关键业务参数能从前端传进来就有被篡改的可能。3. 逻辑漏洞挖掘的实操流程与方法论很多人觉得逻辑漏洞难挖是因为没有方法论不知道从哪下手。我总结了一套自己的测试流程从信息收集到深入验证按这个顺序走基本不会漏太多东西。3.1 第一步先摸清业务边界别急着发包拿到一个目标系统先注册账号、登录进去以正常用户身份把核心业务流程完整走一遍。走的时候重点记录三件事每个步骤对应的URL和参数每一步之间是否有状态关联服务端通过Cookie、Token还是Session维护会话这一步的意义在于建立业务基线。你必须知道正常流程长什么样才能发现异常流程。很多新手一上来就乱改包结果改的接口根本不涉及核心逻辑浪费时间。我一般会用Burp Suite把所有流量过一遍全程开着记录。对每一个关键接口我会单独在Repeater里存好方便后面反复改参测试。3.2 第二步梳理接口清单标记敏感参数打开Burp的HTTP History把登录后的流量全部筛选出来每看到一个接口就问自己三个问题这个接口的参数里有没有ID、type、role、status、price、amount这类高价值字段这个接口返回的数据里有没有包含其他用户的数据特征这个接口背后连接的资源是否属于当前登录用户凡是有ID的参数都要试水平越权——登录A账号拿B账号的资源ID去替换看能不能访问。凡是有type/role参数的都要试垂直越权——把普通用户的type改成管理员看看后端是否做校验。这里有个很实用的经验优先测查询类接口再测操作类接口。查询类越权只影响数据泄露测试成本低、风险小操作类接口可能删数据、改状态需要谨慎。3.3 第三步重点测试多步骤流程的状态绑定密码重置、绑定手机号、更换邮箱、实名认证这类流程是最容易出现逻辑漏洞的地方。我的测试方法是正常走一遍完整流程记录每一步的请求包尝试跳过中间步骤直接请求最后一步尝试乱序请求比如先调第三步再调第二步尝试跨用户用A的验证码去给B重置密码尝试重放重复发送同一个验证请求看验证码状态是否被销毁每一步我都会对照响应结果判断是否成功而不是只看HTTP状态码。有些系统前端做了跳转限制但接口层面实际已经执行了要会用Burp直接观察返回数据里的业务字段。3.4 第四步并发测试要会用工具做竞态测试手工点击肯定不行。我用Burp的Intruder或者Turbo Intruder插件来打并发。基本思路找到检查操作两步逻辑的接口把操作请求发送到Turbo Intruder设置高并发线程同时发送几十个甚至上百个请求观察资源状态的变化比如测试优惠券是否能重复使用就抓取使用优惠券的请求用Turbo Intruder一次性打50个并发然后去订单列表看是否生成了多笔优惠订单。如果只有一笔说明服务端处理得当如果出现多笔恭喜你中奖了。3.5 第五步不要忽略低频接口和管理端接口很多时候核心接口防护做得很好但边缘接口全是洞。比如后端管理接口没有做权限控制任何人可访问测试接口/test、/debug遗留在生产环境第三方回调接口支付回调、登录回调没有良好的验签逻辑我会在收集阶段专门用字典爆破管理后台路径顺便看响应头的特征。一旦发现没有权限控制的接口先用低权限账号试探确认是否存在垂直越权。4. 实战案例拆解四个真实场景的完整走查前面讲了方法论这一节我用四个我在实际测试中遇到过的场景把完整的过程走一遍。细节我会模糊掉但思路完全保留。4.1 案例一水平越权遍历订单数据某电商平台有个我的订单功能点击订单详情时前端发起GET /api/order/detail?order_id12345请求。我登录自己账号后替换order_id为12346响应直接返回了另一个用户的订单信息包括收货人、手机号、详细地址。我当时的验证思路是这样的先用自己的两个账号互查确认可以互相访问再用第三个不相关的账号去访问确保不是账号间互相信任的问题。确认越权后我进一步测试了批量导出——写脚本遍历order_id从10000到100000看响应是否存在规律最终确认可以批量拉取订单数据。这个案例的根因很典型服务端只做了登录校验没做资源归属校验。后端的查询语句大概率是select * from orders where id {order_id}压根没带user_id条件。修复方案也很简单查询条件改成select * from orders where id {order_id} and user_id {当前用户id}。4.2 案例二支付金额负数与优惠券复用某内容平台有个打赏功能打赏金额由前端传入/api/reward?amount10anchor_idxxx。我直接把amount改成-1发现账户余额居然增加了1块钱。这里有个细节值得说明负金额能成功是因为后端只做了if amount 0 then reject的校验但用的是前端传入的amount直接更新钱包余额没有用符号判断绝对值校验的组合。我把amount改成-1后服务端逻辑是余额 余额 amount变成了充值1元。另一个案例是优惠券。某外卖平台的优惠券接口使用后返回code:0表示成功。我把同一个请求在Burp里手动重放了几次发现第一次返回成功第二次也返回成功第三次才提示优惠券已使用。原因是服务端先判断优惠券状态再核销两步之间存在延迟重放速度快就能卡住窗口期。用Turbo Intruder并发测试后确认50个并发的请求里有11个成功核销了同一个优惠券。这类问题的修复思路是加状态更新的原子性判断比如SQL写update coupon set status1 where id? and status0影响行数为0就说明已被使用。4.3 案例三密码重置流程跳步某网站找回密码分三步第一步输入手机号获取验证码第二步校验验证码第三步设置新密码。我抓包发现前两步验证通过后服务端在响应中返回了一个reset_token第三步设置新密码时提交这个token。绕过思路很明显了我先用自己的手机号走完前两步拿到reset_token然后把第三步请求里的手机号参数改成目标的手机号token保持不变直接提交。结果目标账号的密码被重置成功了。问题出在token只和验证码校验结果绑定没有和手机号绑定。服务端应该在生成token时关系该手机号第三步设置密码时同时校验token归属手机号但我测试的系统完全没做这层绑定。这个案例告诉我们多步骤流程里的每一步都必须携带统一的流程凭证且凭证必须与发起用户强绑定。4.4 案例四管理接口无鉴权某SaaS系统主站是app.example.com我发现有个子域名internal.example.com可以直接访问打开是一个管理控制台登录页。顺手试了一下常见弱口令没进去。然后在Burp里抓主站的登录请求发现登录后的Token是JWT格式解码后发现payload里带了role:user字段。我把JWT的role改成admin重新编码替换到管理台的请求里发现服务端直接用JWT的role字段做权限判断没有和数据库里的真实角色做比对管理台直接放行了。JWT的坑在于如果服务端不校验签名或者秘钥是弱秘钥改payload是很容易的。这个案例里我甚至不需要知道秘钥——服务端压根没验签名改了payload直接就能通过。5. 逻辑漏洞挖掘避坑指南与修复建议最后这部分我把平时测试中容易踩的坑和测试完之后的修复思路一并说清楚方便做安全建设和漏洞修复的同学直接参考。5.1 测试中的三大坑误报、连锁、合规第一个坑是误报。逻辑漏洞和常规漏洞不一样很多看起来像漏洞的现象其实是业务设计。比如积分排行榜里能看到别人的昵称这不一定是越权可能是产品功能。我判断一个逻辑漏洞是否成立标准只有一个这个操作或数据访问是否超出了当前用户应有的权限范围。在报告里一定要结合业务场景描述影响而不是单纯列现象。第二个坑是连锁影响。测试越权时如果一个接口返回了别人的手机号就涉及个人信息泄露如果还能进一步修改比如改别人的收货地址那就从信息泄露升级到了业务中断。写报告时要把危害等级拉高但测试时要格外小心——别真的把别人的数据改了我在测试时会尽量避免对他人数据的写操作只做最小化的读取验证。第三个坑是合规边界。逻辑漏洞测试本质上是在模拟攻击者前提必须是你有授权。在授权范围外做测试哪怕初衷是好的也可能出问题。我的原则是白盒测试先在测试环境做充分验证黑盒测试尽量用自己创建的账号和数据不动真实用户资源。5.2 逻辑漏洞修复的五个关键动作修复逻辑漏洞不能头痛医头。我建议按以下五条线同时推进所有对象级操作必须校验归属服务端在查询、修改、删除任何资源之前先判断当前用户是否有权操作该资源。这是最基础也最重要的一条。统一实现一个权限校验中间件不要在每个接口里手写。关键业务参数服务端计算金额、积分、价格、折扣等涉及钱的参数一律由服务端根据商品ID和用户身份实时计算前端传什么就拒绝什么。前端只能传业务对象的ID不能传价格。多步骤流程加入全局会话状态用Redis或数据库维护流程状态生成一次性token每一步都校验token与当前会话和当前用户是否匹配步骤完成后立即销毁token。拒绝通过独立接口跳步。并发场景使用原子操作凡是检查-更新两步逻辑必须保证原子性。数据库层面用条件更新update ... where status 0代码层面用分布式锁避免并发穿透。敏感接口全量加频率限制短信、邮件、验证码、登录、注册、找回密码等接口必须限频。同一手机号、同一IP、同一账号分别做限制前端限制只是锦上添花服务端限频才是关键。5.3 一个压箱底的测试小技巧最后分享一个我自己的压箱底经验。挖逻辑漏洞的时候别总盯着主流程多注意功能之间的跳转。比如支付完成后的回调、第三方登录后的跳转、下单成功后的页面跳转这些跳转点经常携带关键参数比如订单号、用户ID、token。我见过很多系统主流程的接口防护做得滴水不漏但在跳转带参这个环节里把用户的ID直接拼在URL上交给前端。测试方法很简单用抓包工具观察每次跳转的URL参数凡是在URL里出现的用户标识类参数全部尝试篡改一遍。这个技巧帮我发现了不少在甲方眼里想不到的漏洞比闷头测主流程效率高多了。逻辑漏洞这门功课说到底拼的是对业务的理解深度。技术手段翻来覆去就那几板斧但对业务流程的敏感度是需要在一次次实战里磨出来的。希望这篇内容对你有实际帮助下次再遇到业务逻辑问题的时候能有个清晰的排查方向。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询