欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

在乌云上看到的,一个线程并发漏洞,有人愿给讲讲原理和修复方案吗?

程序员文章站 2022-05-09 22:52:08
...
在乌云上看到的,一个线程并发漏洞,有人愿给讲讲原理和修复方案吗?

http://www.wooyun.org/bugs/wooyun-2010-0102881

而是在发送的请求读数据时未及时锁住数据信息导致可多线程并发多次利用优惠劵。
这个BUG如何理解呢?难道是开多个浏览器同时使用优惠券吗?如何堵住BUG呢?

回复内容:

在乌云上看到的,一个线程并发漏洞,有人愿给讲讲原理和修复方案吗?

http://www.wooyun.org/bugs/wooyun-2010-0102881

而是在发送的请求读数据时未及时锁住数据信息导致可多线程并发多次利用优惠劵。
这个BUG如何理解呢?难道是开多个浏览器同时使用优惠券吗?如何堵住BUG呢?

这个bug是没及时修改优惠券状态所致的。
第二次请求的时候,第一次请求还没来得及把优惠券的状态改成”已使用“,导致第二次也可以使用优惠券。

这是一个逻辑不严谨导致的bug, 跟线程互斥没什么关系。

防止这个bug的方法,就是保证及时修改优惠券的状态。

关于如何制造这个bug的方法很多, 很多语言都有多线程\多进程功能, 开起来同时请求就行了。
甚至题主说的用多开浏览器请求也是可以的。

跟你简单的说吧,你现在去买东西,掏钱才给你开门,你掏了钱,门开了,忽然你的东西掉了(不要问怎么掉了),你低下头去捡东西(店门没关,线程没锁),这时候B君进来拿走了你要的东西,此时你抬头,也询问你的东西,店家还是乖乖给了你...而且这段门敞开的时间,多个线程都可能抢占,仅仅只有一个线程触发了交易完成,店家才知道,完成了交易,这时候,剩下的线程才进不来(具体那个线程触发这个关门操作都是随机的,跟计算机当时的状态都有关,因为线程执行是不断切换的)关闭店门,在这段时间内ABCDE君都可能免费拿到东西.

一般支付流程如下:

  1. 读取余额

  2. 判断是否大于0

  3. 余额减一

  4. 写回余额

当两个线程同时执行,假设余额为1,两个线程并发执行(假设第二个线程落后于第一个),第二个线程在第一个线程将写回余额之前读取了余额,那么线程二也会判断成功,照样会执行购买成功的流程。
设计的好一点儿的情况是,结果数据库里的结果是-1,坏一点儿的情况是数据库里的的结果是0 (因为第二个线程读取的是1,减一之后写回所以是0).

解决方案就是加锁,在线程一读取余额之前加锁,让要读取余额的线程二挂起等待线程一写回余额再读取。
所有数据库都可能存在这样的情况,有人用来取现的。http://www.wooyun.org/bugs/wooyun-2015-099622

相关标签: 乌云 php