竞争条件漏洞原理
竞争条件
- 指多个线程或者进程在读写一个共享数据时结果依赖于它们执行的相对时间的情形。
- 在Web中沿用这个概念,当多个php进程对同一数据进行数据库读写操作时,可能会由于时序问题,造成一些逻辑错误的异常情况。
超卖问题
- 在真实情景中,开发人员可能会更熟悉超卖问题。
- 超卖问题指在秒杀或抢购活动中,成功下订单买到商品的数量超过商品数量的上限的情况,这是任何抢购活动都要面临的难题。
- 其实超卖问题本质就是我们这里所说的竞争条件(Race Condition ),我们可以参考超卖问题的分析与解决方案,来研究竞争条件漏洞.
业务安全紧贴业务场景
支付逻辑
- 攻击者利用多线程并发请求,在数据库中的余额字段更新之前,多次兑换积分或购买商品,从中获得利益。
超卖
- 攻击者利用多线程并发请求,秒杀或限量抢购业务中,实现超买,从中获利。
文件上传
- 文件上传时,先上传、再检测、不合条件时再删掉的场景,攻击者利用多线程并发不断上传一个可以写webshell的脚本,然后马*问这个刚上传的文件,当服务端判断并删除的时间大于客户端线程访问的时间时,客户端可以在删除之前访问到这个脚本并成功运行写入webshell。
漏洞利用场景
单个请求示例
并发多个请求示例
漏洞修复
原理:数据库支持锁定数据
数据库支持:事务+悲观锁(for update)
数据库层测试
- 1、使用InnoDB引擎作为表类型
- 2、开启两个终端窗口连接mysql数据库
- 3、窗口A开启事务begin,执行select…for update查询
- 4、窗口B执行select不受影响,执行select…or update查询将会被阻塞
- 5、窗口A执行commit提交事务,窗口B的阻塞消失
实际业务代码
- 用事务来包裹上面的SELECT+UPDATE操作
- 透过的事务机制来确保逻辑正确
- 使用了select…for update的方式,通过数据库实现悲观锁。
- 此时在user表中,id为1的那条数据就被我们锁定了,其它的事务必须等本次事务提交之后才能执行。
这样我们可以保证当前的数据不会被其它事务修改。
摘抄
有一天你会明白,善良比聪明更难。
聪明是一种天赋,而善良是一种选择。
– 杰夫・贝佐斯