优惠卷类型漏洞---优惠卷的并发使用

优惠卷的并发使用 主要是在形成订单的那个数据包那里,进行并发,如果可以创建多个订单并且显示在前端页面,尝试刷新页面防止前端误报,若还是存在,则存在漏洞。基本到可以创建订单就差不多了,也可以尝试去支付,但最好金额不要太大。

漏洞的原理

这个漏洞属于条件竞争漏洞,核心本质是多个进程或线程同时争夺一个资源,最后的结果取决于一些"运气"(执行的先后顺序和微妙的时间差)。

后端服务器(Nginx,Apache HTTP Server,Tomcat)基本都是多线程(或进程)去处理请求的

当你并发几十个请求一起发送到后端服务器,后端服务器会并发的处理这些请求,但是并发并不是物理意义上的一起处理,是按照一定的顺序,先处理这个请求一部分,在处理这个请求一部分,这样循环的。

加上对于优惠卷使用的检查流程大概是这样的:先检查数据库这个用户是否有优惠卷,然后请求使用优惠券,最后才会修改数据库的数据。

这样就会导致每个请求和数据修改之间会有一个微妙的时间差,也就是TOCTOU(检查时与使用时之间的时序漏洞),在请求一通过了检查,但是还没有修改数据库的时候,这是如果轮转到了请求二,那因为此时还没有修改数据库,所以检查仍然通过,这就导致了优惠卷重复使用。

根据此原理,主要的修补方案有两种:数据库方面加锁 和 分布式锁。

一、数据库层面加锁

一般来说查询数据用的sql语句是

sql 复制代码
SELECT is_used FROM coupons WHERE id = 123

而修改查询语句使用FOR UPDATE就可以解决这个问题

sql 复制代码
SELECT is_used FROM coupons WHERE id = 123 FOR UPDATE

当线程1执行到这条查询的时候,数据库会把id=123这一行锁住,其他的线程查询会显示在使用,只有线程1完全完成才会把id=123这条放开,此时数据库已经更改完成,线程2去请求则不会出现条件竞争的情况

二、分布式锁

在如今的现实中通常都是分布式的高并发情况,一般会采用Redis做一个分布式锁

Redis是单线程的、基于内存的、高性能的键值对(Key-Value)数据库服务器

一般不会用普通数据库比如MySQL数据库,因为它们的数据都是存放在硬盘上的,读写硬盘涉及大量的I/O操作速度相对较慢,高并发很容易卡死;而Redis是全部存在内存(RAM)里的,读写速度比硬盘快成千上百倍,官方显示Redis一秒钟可以处理10万次以上的读写操作请求。而且Redis是单线程执行命令的,无论多少请求都得一个个处理,很适合做锁,但是因为现在都是分布式高并发,为了适应那些的速度,Redis的处理速度必须很快,不过好在Redis并不去处理很复杂的东西,只是快速判断是否存在该键值对,有就等待或丢弃,没有就创建然后返回给后台的分布式服务器去执行服务,执行完后再回Redis销毁该键值对。

比如说你并发了50个请求,然后Redis会先让第一个请求进去,然后根据用户或者商品创建一个key,比如是按照用户创建的,那第二个请求进入的时候会发现已经创建了一个改用户的key,此时就会停止,停止后有两种可能(看后端开发式怎么写的),一是直接返回错误,二是等待每隔一段时间再去请求直到空闲,然后再去处理第二个请求。但是不管哪一种,都不再存在条件竞争,在key一样的情况下会被强制等待或丢弃。

整体的流程大概是这样的

Redis的锁,颗粒度很小很精准,所住的是具体某个用户的特定资源,而不是整个业务。而且锁的时间相对于整个的过程来说时间很短。

Redis只锁同键,不锁异键。

当然Redis锁什么也很有思考,比如购物时锁的如果是商品ID,那全网购买这个商品的用户都会被强制等待,就算你用bp的Turbo Intruder也没用,因为你并发多少次也都是那个商品ID;但是如果他锁的是用户的ID,就可以尝试用多个用户并发去尝试,因为他锁的是用户ID,那多个不同的用户并发就不会受到Redis锁的影响,就回去同时去向底层的MySQL数据库去扣库存(多个线程并发扣)就可能导致最后被扣成负数。

这些就是关于优惠卷并发使用的一些原理,当然上述说的都是可能成功,并发和网速的关系也很大,网速快成功概率和成功并发的数量都会更多(因为是在短时间内发大量包,网速越快,发的越多,就越可能抓住 TOCTOU 也就是检查和使用之间的这个时间差)。

相关推荐
小二·2 小时前
MySQL 8.0 性能优化与索引原理
android·mysql·性能优化
AC赳赳老秦2 小时前
OpenClaw + 华为云自动化:批量管理云资源、生成月度云账单分析与成本优化报告
java·开发语言·javascript·人工智能·python·mysql·openclaw
我是一颗柠檬2 小时前
【Java项目技术亮点】读写分离+主从延迟处理:MySQL高并发下的性能优化方案
java·分布式·mysql·性能优化
霸道流氓气质3 小时前
MySQL 大数据量场景下的表结构与索引设计指南
数据库·mysql
lsyeei3 小时前
MySQL常用索引
数据库·mysql
雨辰AI3 小时前
生产级实战|SpringBoot3 + 达梦DM9 数据库权限收敛与三权分立完整落地方案
数据库·mysql·oracle·政务
Gong-Yu3 小时前
MySQL数据库运维——性能优化进阶1️⃣
运维·数据库·mysql·性能优化
拄杖忙学轻声码3 小时前
mysql脚本查询 xxx分钟、xxx小时、xxx天之前的数据(使用 interval、subdate()等 对日期时间增减操作),写法和案例
mysql
峥无3 小时前
MySQL 系统学习之路 第一篇:服务安装、基础概念与架构全解
学习·mysql·架构