渗透测试中的10个常见逻辑漏洞及修复方案(附实战案例)
逻辑漏洞不同于SQL注入、XSS这些技术型漏洞,它们不依赖代码缺陷,而是利用业务流程设计的不合理。WAF、防火墙对逻辑漏洞几乎无效。我在渗透测试中遇到的最严重的漏洞,80%都是逻辑漏洞。
漏洞1:越权访问(IDOR)
危害等级:严重
越权是逻辑漏洞中的王者。攻击者通过修改请求参数,访问到不属于自己的数据。
实战案例:某电商平台订单接口 GET /api/order/detail?order_id=20260518001,把order_id改成20260518002,直接看到别人的订单(含收货地址、手机号)。写脚本遍历,2小时拖了17万条订单数据。
修复方案:
# 错误:只检查order_id是否存在order=Order.query.get(order_id)returnjsonify(order.to_dict())# 正确:同时校验用户归属@app.route('/api/order/detail')@login_requireddeforder_detail():order=Order.query.get(request.args.get('order_id'))iforder.user_id!=current_user.id:abort(403)returnjsonify(order.to_dict())漏洞2:支付金额篡改
危害等级:严重
实战案例:某在线课程平台,前端传价格到后端 {“price”: 998}。抓包改price为0.01,1分钱买了998元的课。
修复方案:价格只能从服务端数据库读取,不接受前端传参。
course=Course.query.get(request.json['course_id'])price=course.price# 从数据库读,绝不用前端传的值漏洞3:短信/邮件轰炸
危害等级:中等
实战案例:某App注册接口无图形验证码、无频率限制。Burp Intruder循环调用,一个号码一夜收到3000多条短信。
修复方案:IP频率限制(3次/分钟) + 手机号限制(60秒间隔) + 每日上限(5次/天)。
@limiter.limit('3 per minute')defsend_sms():ifredis.get(f'sms_limit:{phone}'):returnjsonify({'error':'发送太频繁'}),429redis.setex(f'sms_limit:{phone}',60,'1')ifint(redis.get(f'sms_daily:{phone}')or0)>=5:returnjsonify({'error':'今日上限已满'}),429漏洞4:密码重置漏洞
危害等级:严重
实战案例:某SaaS平台验证码6位数字无次数限制,10分钟爆破成功。验证码校验和用户绑定不严,可能用A的验证码重置B的密码。
修复方案:5次尝试限制 + 5分钟过期 + 验证码与用户强绑定 + 统一错误信息(不泄露用户是否存在)。
漏洞5:条件竞争(Race Condition)
危害等级:高
实战案例:某积分商城,积分只有1000,Burp Turbo Intruder同时发20个兑换请求,成功兑换17个礼物。校验和扣减不是原子操作。
修复方案:数据库行锁 with_for_update() 或 Redis分布式锁。
# 数据库行锁user=User.query.with_for_update().get(current_user.id)ifuser.points<gift.cost:returnjsonify({'error':'积分不足'})user.points-=gift.cost# Redis分布式锁lock=redis.lock(f'exchange_lock:{user_id}',timeout=5)ifnotlock.acquire(blocking=False):returnjsonify({'error':'操作太频繁'}),429漏洞6:业务流程绕过
危害等级:高
实战案例:某商城下单:选商品->填地址->付款->发货。跳过付款直接调用发货接口,商家把货发出去了还没收到钱。
修复方案:状态机校验前置状态。
VALID_TRANSITIONS={'pending':['paid'],'paid':['shipped'],'shipped':['completed']}iforder.statusnotinVALID_TRANSITIONS.get(order.status,[]):returnjsonify({'error':'订单状态无法执行此操作'}),400漏洞7:验证码绕过
危害等级:高
常见绕过:验证码返回给前端、永不过期、写死测试值(123456)、只校验是否为空。
修复方案:不返回前端 + 5分钟过期 + 用完即删(一次性)。
漏洞8:用户枚举
危害等级:中等
实战案例:登录接口返回"用户名不存在"vs"密码错误"两种提示,攻击者可遍历判断哪些手机号注册了账号。
修复方案:统一返回"用户名或密码错误"。
漏洞9:接口未鉴权
危害等级:严重
实战案例:某App管理后台API直接暴露公网,GET /api/admin/users 返回所有用户数据(含密码hash),无token、无IP白名单。
修复方案:中间件统一鉴权 + 管理接口只在内网可访问 + Nginx/API网关拦截。
defadmin_required(f):@wraps(f)defdecorated(*args,**kwargs):token=request.headers.get('Authorization')ifnottokenornotverify_admin_token(token):abort(403)returnf(*args,**kwargs)returndecorated漏洞10:数据批量导出
危害等级:高
实战案例:GET /api/users?page=1&size=999999 一次拉走全量用户数据。
修复方案:限制分页上限 max_page_size=100,且对大量查询加审计日志。
MAX_PAGE_SIZE=100size=min(int(request.args.get('size',20)),MAX_PAGE_SIZE)pagination=User.query.paginate(page=page,per_page=size)总结:逻辑漏洞检测清单
| 漏洞类型 | 检测方法 | 修复核心 |
|---|---|---|
| 越权访问 | 修改ID参数 | 服务端校验数据归属 |
| 金额篡改 | 抓包修改价格 | 价格只从服务端获取 |
| 短信轰炸 | 循环调用发送接口 | 频率限制+图形验证码 |
| 密码重置 | 爆破验证码 | 次数限制+统一错误信息 |
| 条件竞争 | 并发提交 | 数据库锁/分布式锁 |
| 流程绕过 | 跳步调用 | 状态机校验前置状态 |
| 验证码绕过 | 复用/空值/固定值 | 一次性+过期+不返回 |
| 用户枚举 | 遍历用户名 | 统一错误信息 |
| 接口未鉴权 | 直接访问管理接口 | 中间件鉴权+网关拦截 |
| 批量导出 | 修改page_size | 限制分页上限 |
核心原则:永远不要信任前端传入的数据,所有业务逻辑校验必须在服务端完成。
作者:渗透测试工程师,5年安全从业经验。有问题欢迎评论区交流或私信咨询。觉得有用请点赞收藏。
