资讯动态

业务逻辑漏洞挖掘实战:扫描器为何失明,手动测试如何破局

发布时间:2026/10/20 22:16:38 来源:尧图企业网站定制
一个甲方项目临近上线自动化扫描器跑了三轮报告干干净净最高危的不过是两个低危信息泄露。可就在发布前一周我做了一次针对业务链路的手动复核二十分钟内挖出了两个可以直接拿走他人账户余额的逻辑漏洞。那个项目最后延期了半个月大家虚惊一场但也让我彻底明白一件事扫描器从来都不是漏洞挖掘的“终点”在业务逻辑面前它甚至会集体失明。这篇文章我想把几年下来关于业务逻辑漏洞挖掘的思考、方法和实操经验整理出来。核心围绕“为什么扫描器会漏”“怎么从业务视角去挖”“哪些场景最容易翻车”这几个问题展开。内容适合已经开始接触Web安全、但总觉得自动化工具不够用的朋友也适合甲方安全团队想建立自测体系时参考。我会尽量少讲理论名词多讲能在真实项目中直接落地的思路和操作。1. 扫描器为何在逻辑漏洞面前“集体失明”1.1 扫描器的本质是“特征匹配机器”自动化扫描器的工作方式本质上就是“发请求、看响应、比对特征”。它对疑似注入点做变异测试对响应内容匹配已知的危险函数签名对报错信息判断是否存在异常处理缺陷。这种模式的优点很明显速度快、覆盖广、不需要人工干预。但它的缺点也同样致命——它只认识“长得像SQL注入的输入”不认识“这个订单金额为什么能被改成负数”。逻辑漏洞不是语法层面的问题而是语义层面的问题。一个请求可能在形式上是完全合理的参数类型对、格式对、权限头也在可它就是绕过了业务规则。比如某个兑换接口没有校验积分数值是否为负你可以传一个负数进去让积分资产不降反升。这个请求在扫描器眼里和正常人兑换商品一模一样没有恶意特征自然不会被报告。我测试过一个场景某系统的找回密码流程第一步发送验证码第二步校验验证码第三步重置密码。第三步的接口只校验了当前用户是否登录却没有校验是否已经走完第二步。于是我用一个普通账号直接调用第三步接口把管理员密码给改了。扫描器面对这个接口只会做简单的注入测试它根本不知道“第三步必须发生在第二步之后”是一条业务规则所以这种漏洞它永远看不见。1.2 逻辑漏洞的共同特征合法请求中的非法语义逻辑漏洞之所以难防也难测是因为它几乎没有统一的形态。比如说订单金额篡改这是参数层面的逻辑缺陷。越权访问他人数据这是身份验证与授权层面的逻辑缺陷。验证码没有绑定性、可重放这是状态管理层面的逻辑缺陷。优惠叠加、积分倒转这是计算和规则层面的逻辑缺陷。这些漏洞在HTTP层面上往往是“合法”的。一个越权接口返回了别人的订单详情响应里没有任何报错也没有特殊字符它是标准的200 OK正常JSON结构。扫描器判断这个响应是安全的因为没有匹配到任何已知漏洞的特征。但是站在业务的角度这个请求不应该返回别人的数据这是一条业务规则扫描器不知道也不关心。理解了这个本质你就能理解为什么手动测试永远不会被自动化工具完全替代。扫描器在做“广度覆盖”而逻辑漏洞需要“深度理解”。宽度与深度本来就是两种维度的事。2. 从“扫”到“挖”手动测试的思路切换2.1 先画业务地图再找风险口径手动测试逻辑漏洞的第一步不是打开Burp Suite开始抓包而是先搞清楚系统里到底有哪些业务功能。我习惯在测试前先把自己当成一个真实用户把关键业务流程完整走一遍注册、登录、浏览、下单、支付、售后、个人中心、积分兑换、优惠券领取、密码找回。每走一个流程就在文档里记录下涉及哪些接口、传递哪些参数、身份状态是什么。画完地图之后再给每个环节标注“风险口径”。哪些环节涉及到钱哪些环节涉及他人数据哪些环节存在用户可操控的状态。比如支付环节可操控的往往是金额、数量、优惠金额、运费、支付结果回调越权环节可操控的往往是ID类的参数密码找回可操控的往往是验证码、手机号、用户标识。这张业务地图和风险清单是后续所有测试动作的依据。没有它你只是在漫无目的地改参数测到哪里算哪里效率低且容易遗漏。我把这一步叫作“从扫描器的广度视角切换到产品经理的流程视角”你会发现视野完全不同。2.2 用“资源-权限”矩阵锁定越权测试点越权漏洞是逻辑漏洞里最常见、危害最直接的一类。很多测试人员做越权测试时很随意拿到一个接口就换个用户试试测过了就完了。但真正系统化的做法是先建立一个矩阵。矩阵的行是业务资源比如订单、收货地址、个人信息、积分明细、优惠券、工单列是访问者身份比如未登录游客、普通用户A、普通用户B、管理员。然后逐个组合去测游客能不能访问登录用户的数据用户A能不能访问用户B的数据普通用户能不能访问管理员的接口我从这个矩阵里吃到过不少甜头。一次测试中某系统的“发票信息查询”接口接收一个发票编号参数返回内容包含企业的开票信息。我把自己账号下的发票编号换成另一个测试账号的编号响应里直接出现了对方的企业账户资料。这个接口没有做归属校验属于典型的水平越权。扫描器不会去测不同用户之间的数据隔离因为它没有“两个登录账号”的概念但人知道。2.3 从“参数猎奇”转向“状态与流程”大多数扫描器关注的是参数值的变化比如在id后加个单引号、在搜索框里塞一段XSS payload。而逻辑漏洞的挖掘重点往往不在参数值而在请求的状态、顺序和依赖关系。举个很常见的例子多步骤流程。一个业务动作被拆分在三个接口里完成比如“创建订单-确认支付-完成交易”。正常流程下三步按顺序发生但业务代码不一定校验了状态依赖。你可以尝试跳过第一步直接请求第二步或者完成第二步之后重放第二步请求观察系统是否允许重复操作。这类“状态翻转”测试扫描器是完全不做的它没有流程的概念。另一个关注点是“是否真的发生了服务端校验”。很多系统在前端做了详细限制比如前端代码写死“优惠券只能使用一次”、写死“购买数量不能超过库存”但服务端完全没有校验。你只需要绕过前端直接发畸形请求后端就全盘照收。这种问题在真实项目中极其常见因为开发阶段很多人默认前端做了限制就够了后端校验很容易被漏掉。3. 核心实操手法拆解3.1 参数与状态篡改从盯住每个可操纵字段开始逻辑漏洞挖掘最基础的手法就是参数篡改。拿到一个请求后逐个审视里面的可操控字段思考一个问题这个字段的值发生变化会对业务结果产生什么影响以支付流程为例常见的可篡改字段包括商品ID、单价、数量、总价、优惠金额、运费、货币类型、积分抵扣、支付结果。我的习惯是每次只改动一个字段观察响应和后续状态的变化。比如把单价改小、把数量改成负数、把总价改成0.01观察系统最后入账的金额是否被修改后的参数控制。这里有一个关键判断点系统最终以哪个字段为准有的系统会在创建订单时读取前端传参把单价直接存库有的系统会传商品ID后后端根据ID去数据库查真实价格。前者存在价格篡改漏洞后者不存在。测试时先通过修改参数看响应再结合数据库里的订单状态去判断就能确认漏洞是否真实存在。我在一个测试项目里遇到过这样的情况某旅游平台的“支付确认”接口把应付金额作为隐藏字段放在前端表单里。我把它改成0.01元并提交系统居然生成了支付金额为0.01的订单完成了全部出票流程。这就是典型的前端信任问题后端没有任何逻辑去“重新计算”应收金额。3.2 业务流程状态机翻转把合法的接口用非法顺序调一遍状态机翻转测试的核心思路是打破业务流程的顺序约束把所有接口尝试以不同的顺序调用一遍。具体操作起来分几个阶段。第一阶段是“前置依赖绕过”。正常注册需要“验证码校验成功”后才能提交那就抓取验证码校验请求和提交注册请求尝试直接调用后者不携带任何验证码。如果接口返回成功说明后端没有建立会话状态校验。第二阶段是“步骤重放”。拿同一个请求连续发送多遍观察系统是否允许重复执行。最典型案例一个“确认发货”接口被调用两次或者一个“优惠券激活”请求被重放多次。前者可能导致订单状态错乱后者直接能把一张券激活成N张。第三阶段是“跳步探测”。多步骤流程里抓取所有步骤的请求然后从第二步直接开始、从第三步直接开始、甚至反过来从第三步逆向走回第一步观察系统的反应。很多初级的找回密码模块就是因为漏掉了步骤间的状态绑定导致任意账号密码被重置。我在某内部管理系统的测试里发现它的“创建工单”功能分为三步填信息、传附件、确认提交。第三步接口依赖第二步生成的临时附件编号但这个编号没有做会话绑定只要我在第三步手工指定任意有效编号都能成功创建工单。这意味着任何登录用户都可以伪造别人的工单编号创建数据属于越权与时序双重问题。这类问题在开发眼里很难想象因为正常用户根本不会这样操作但攻击者就喜欢这么干。3.3 并发与竞态探测同一请求多线程打过去业务逻辑里有一类漏洞依赖于“检查和执行之间存在时间窗口”俗称竞态条件。典型场景是优惠券使用、库存扣减、积分兑换、抽奖次数限制。系统逻辑是“先查询是否已使用再执行使用”如果两个请求在同一时刻都完成了“查询未使用”这一步然后都执行了“使用”就产生了一券复用。测试竞态条件不需要什么高深工具思路很简单把目标请求复制到一个可以直接并发发送的脚本或工具里开几十个线程同时发送。看最终结果是否出现多次成功或者资产是否被多次扣减。我常用的一个快速验证脚本是在命令行工具里循环创建多个异步任务向同一个接口发送请求。不用写得很复杂关键是模拟“同时到达”。如果接口响应显示成功次数超过了应有的上限就说明存在竞态问题。不过竞态测试很有风险它会把系统真实的数据状态改变所以一定要在授权范围内、用测试数据去操作不要随便拿生产数据试。3.4 签名逻辑分析绕过前端加签的常见套路现在很多业务系统为了保护接口安全会给请求加上签名参数。前端把若干参数拼接后做一次哈希或加密后端验证签名后再处理业务。逻辑漏洞挖掘中签名机制也可能成为突破口。常见的问题有几个方向。第一是签名因子中是否包含了关键参数。如果一个支付请求的签名只覆盖了商品ID、数量没有覆盖金额那么攻击者即使无法重新计算签名也可以通过修改未签名参数来攻击。第二是签名后端是否严格校验了所有需要签名的字段还是只校验“签名存在且格式正确”。第三是签名使用的密钥是否可预测或是否被硬编码在前端代码中前端代码反混淆后就能拿到密钥攻击者可以自己生成任意参数的合法签名。还有一个方向是“签名降级”。有些系统存在多个API版本新版接口有签名校验旧版接口没有。攻击者把请求地址改成旧版本校验逻辑可能直接跳过。这类问题在接口迭代时很常见扫描器完全不会去关注版本差异但手测时会发现旧接口和新接口的逻辑不一致从而找到绕过点。4. 典型业务逻辑漏洞的技术剖析4.1 越权访问最容易挖到的高危逻辑漏洞越权访问分为水平越权和垂直越权。水平越权是A用户访问B用户的数据垂直越权是普通用户访问管理员的接口。不管是哪种根源都只有一个后端接口没有对“当前登录者的身份”与“被操作资源的归属”做严格绑定。测试水平越权最直接的方式是准备两个真实账号然后挨个接口换着来。Burp Suite里有两个常用功能一个叫Proxy History一个叫Comparer。Proxy History的同时可以记录两个账号的请求流找到A账号的资源请求后把参数中的A资源ID改成B的用B的会话发送。如果响应里出现了B的数据漏洞就坐实了。垂直越权的测试思路类似但是目标是管理员的后台接口。如果普通前台账号根本无法登录后台那就尝试直接请求后台功能接口。很多系统的后台和前台共用一套应用代码只是前端隐藏了入口。技术手段上可以在前端源码里搜索包含admin、manage、internal、dashboard这些关键字的JS代码直接找到后台接口的定义。再拿着普通用户的Cookie请求这些接口如果后端没有做角色校验就形成了垂直越权。4.2 支付与价格操纵围绕钱做文章支付相关的逻辑漏洞危害很大而且形态五花八门。最基础的是改商品价格、改总价、改数量、改优惠金额。很多系统确实做了服务端价格查询但它们可能漏掉了多个商品明细之间的联动关系或者漏掉了折扣计算的边界条件。比如某商城的“满减”逻辑优惠金额是在前端算好传参提交的服务端直接存了这个优惠金额。攻击者可以把满300减50的优惠金额改成满0减500让订单实付金额变成负数。系统如果允许负金额支付环节就会向其账户充值形成“反向购买”。另一个常见问题是“多商品混合支付”。系统在前端显示商品总价后端对每个商品单独校验库存和状态但总价这个字段没有重新计算。攻击者把一个1元商品的请求复制多份把一个9999元商品的价格字段全部改成1元最终系统按修改后的价格计算总额。测试支付漏洞时需要特别小心不要真的把订单支付成功否则会形成资金损失事件。我的习惯是在测试环境验证或者把金额改到最低如0.01元然后走完整流程。同时要与负责该系统的开发保持沟通测试前说明可能产生的数据变化测试后清理数据。4.3 验证码与身份校验绕过别让“证书”变成“摆设”验证码相关的逻辑漏洞在业务系统中占比很高。典型问题有几种一是验证码不失效同一个验证码可以反复使用二是验证码不绑定会话A会话里收到的验证码可以在B会话里提交成功三是验证码不绑定手机号或账号任何人都可以用别人的手机号流程时填入自己会话获取的验证码四是验证码校验只在前端后端接口根本不校验。短信验证码还常出现“爆破”问题。如果验证码是4位或6位数字且后端没有做尝试次数限制攻击者可以用高并发去暴力遍历所有可能组合。测试时要先确认验证码的存活时间和尝试次数如果系统没有限制这就又是一类严重漏洞。密码找回流程尤其危险。某系统的密码找回分三步第一步验证手机验证码第二步执行重置。第二步的请求包含一个临时凭证代表“验证码已通过”。如果后端只校验了这个凭证存在没有校验凭证是否和当前用户匹配攻击者就可以通过替换用户名来重置任意账户密码。我在手动测试中最喜欢分析这类“凭证依赖”往往能很快挖到高危。4.4 加密签名与参数校验缺失看似安全实则裸奔有些系统做了很多层安全防护既有签名又有加密但真到了业务层面反而几个关键参数裸奔。典型的反差是登录接口做了极高的频率限制但订单创建接口完全没有转账接口做了短信验证但收款人姓名参数不校验是否与银行卡号匹配。分析这类问题时可以思考一个原则系统安全投入的集中点是否覆盖到了数据变更的核心操作如果一个接口能改变核心资产状态但它没有独立的二次校验那它就是高风险。我遇到过某系统的退款接口校验了用户是否登录、退款金额是否小于等于订单金额但没有校验“发起退款的人”是不是“订单的购买者”。于是攻击者可以扫描大量订单号向任意订单发起退款把别人的钱退回到自己账户。这类漏洞远比扫描器报告的反射型XSS影响大得多。5. 实战案例复盘两条完整的挖掘链路5.1 案例一某积分商城的负数积分兑换这个案例是某个购物平台的积分系统。流程是用户用积分兑换虚拟商品兑换页面会先显示当前积分余额和商品所需积分。我按常规思路走了一遍流程正常兑换了一个低价商品抓到了兑换接口的完整请求。请求里有个字段叫points先正常传了100兑换成功。根据经验这种接口往往会信任前端传值我直接把100改成了负数-100再提交。响应竟然显示兑换成功并且积分余额增加了。原因也很简单后端执行的是“余额余额-点数”的逻辑传入负数等于给余额加上100形成了一个积分无限刷取的口子。复盘这条链路时我发现更关键的问题在于后端连“点数是否为正数”这种最基本的业务规则都没有。这算不上多复杂的手法但如果没有手动去改那个字段扫描器永远不可能发现。这也验证了我的一个判断逻辑漏洞的挖掘考验的不是工具能力而是你对业务参数敏感度的把握。5.2 案例二某后台管理系统的工作流越权另一个案例来自一家企业内部的管理系统。该系统有一个“审批流程”功能普通员工可以发起费用申请部门主管审批。后端接口设计上发起申请和审批是两个不同的权限角色。我的测试账号是普通员工正常发起了一个费用申请。按照流程主管登录后能看到这个申请然后点“审批通过”。我抓取审批通过的接口后发现它只接收一个申请单ID并没有校验当前登录人的审批权限。于是我用自己的员工账号直接构造了那个审批请求把申请单ID改成自己刚发的那条记录返回结果显示审批成功状态变为通过。后续我又尝试了越权审批别人的申请单发现同样可行。这个系统的问题在于权限判断的前置条件放在前端“你有没有审批按钮”而后端接口本身完全裸奔。测试过程只需要“抓到接口、改造请求、替换ID”三步。自动化扫描器可能会发现这是一个未授权接口但不会理解它背后的审批业务语义更不会想到用普通员工身份去通过一条需要主管权限的申请。这两条链路都不复杂但都真实发生在我参与的测试项目里。它们有一个共同点开发人员都把业务信任建立在“用户不会乱来”的假设上。而安全测试要做的事就是亲自验证这个假设是否成立。6. 常见问题与排查技巧实录6.1 新手最容易踩的五个坑坑一只测有输入框的地方。很多新手只盯着表单和搜索框忽略了HTTP请求头、Cookie、JSON嵌套字段等逻辑入口。要记住逻辑漏洞的载体不止是用户输入任何一个能被操控的字段都是攻击面。坑二不看响应只盯状态码。逻辑漏洞的成败往往隐藏在响应体的业务代码和状态字段里。接口返回200不代表一定安全返回403也不代表一定失败。我遇到过多个系统在拦截非法请求时依然返回200只是在业务码里写了个errorCode测试时必须结合业务码判断。坑三不准备测试数据。越权测试至少要准备两个差异化的账号竞态测试要准备可控的优惠券或资产数据。临时去注册账号、临时去凑数据容易让测试链条中断也不便于复现。坑四只在应用层测试不关注数据库状态。很多逻辑漏洞的效果不会直接体现在响应里而是体现在数据库状态变更上。比如积分是否真的增加了、订单状态是否真的变了要搭配数据库查询来确认漏洞影响。坑五测试完不清理数据。你在测试环境里创建了一堆垃圾数据或把订单状态改乱了会给开发留下额外负担。规范的测试流程是记录所有操作测试结束后与开发协同清理或还原数据。6.2 排查技巧速查表关注项测试要点判断标准ID类参数替换为自己的另一个账号ID或无关ID是否返回他人数据金额字段改负数、改0.01、改极大值、删除字段后端是否基于修改值计价步骤跳过跳过前置步骤直接请求后续接口业务是否继续执行顺序翻转调换多步骤请求的顺序是否存在状态依赖重复触发将同一请求连续重放是否产生多次成功结果Cookie作用域修改Cookie中的用户角色字段接口是否信任前端身份业务封闭性用普通权限请求管理端接口是否返回未授权或成功验证码状态重复使用、跨会话使用同一验证码是否校验绑定关系这张表是我每次做逻辑漏洞测试之前都会过一遍的清单。它不是万能的但能帮助你建立基本覆盖避免因为“忘了测某类问题”而漏掉严重漏洞。6.3 关于工具选型的经验手动测试不等于完全不用工具。Burp Suite是核心我主要在它身上做抓包、重放、对比和宏处理。Requests库适合快速写测试脚本批量修改参数并统计响应状态。当涉及竞态测试、大批量接口权限探测时脚本工具的优势会非常明显。但工具始终是辅助最关键的是“头脑里的逻辑模型”。我第一次开始认真思考“这个字段为什么在这里出现”“这个流程为什么这样设计”之后已经超越了使用工具的层面。任何工具都只是帮你更快地验证假设而假设的质量决定了漏洞挖掘的上限。另外如果条件允许翻翻目标系统的前端代码、接口文档、开发注释也会有很多收获。接口文档能告诉你哪些参数是可选、哪些是必填、是否存在隐藏字段。前端代码能告诉你哪些校验只存在于UI层。这些信息都是逻辑漏洞挖掘的绝佳情报源扫描器根本不会去读代码和文档但一个细心的人会。逻辑漏洞挖掘这件事本质上考验的不是技术高低而是好奇心和对业务的理解深度。你要不断地问自己系统认为什么是正常的如果我偏不按正常来会怎样这套思维一旦形成你会发现扫描器只是起点真正的攻击面藏在业务流程的每一个“理所当然”里。希望这篇文章能帮你迈出那一步。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑