CTF特训营:技术详解、解题方法与竞赛技巧
上QQ阅读APP看书,第一时间看更新

7.1 概述

在讲解之前,我们先来了解什么是条件竞争漏洞。条件竞争是指多个线程或者进程在读写一个共享数据时,结果依赖于它们执行的相对时间的情形。当多个线程或进程同时访问相同的共享代码、变量、文件等而没有锁或没有进行同步互斥管理时,则会触发条件竞争,导致输出不一致的问题。

在编写代码时,由于大部分服务端语言编写的代码是以线性方式执行的,而Web服务器往往是多个线程并行执行,因而很可能会出现一些问题。下面列举一个简单的例子。

有一个银行账户A和一个银行账户B里面各有1000元钱,现在有两名用户同时登录到了账户A,并且两人都想完成同一个操作:从账户A转100元到账户B,那么正常的操作结果应该是两名用户转账结束之后,账户A里面剩余800元,账户B里面剩余1200元。

但是,考虑下面这样一种情况,如果两名用户在同一个时刻发起了转账请求,那么服务器的处理过程如下。

1)用户甲发起转账请求,服务器验证账户A的余额为1000元,可以转账。

2)用户乙同时发起转账请求,服务器验证账户A的余额为1000元,可以转账。

3)服务器处理用户甲的请求,从账户A里面扣除100元(此时账户A余额为900元),并将其存入账户B(此时账户B余额为1100元)。

4)服务器处理用户乙的请求,从账户A里面扣除100元(此时账户A余额为900元),并将其存入账户B(此时账户B余额为1200元)。

5)处理结果:账户A余额为900元,账户B余额为1200元。

出现上述情况的原因就是条件竞争,正常情况下,因为账户A作为一个共享变量,在某一个时刻有且只有一个用户能够操作账户A的余额,但是由于服务器没有进行适当的加锁或是同步互斥管理,使得两个用户同时访问并修改账户A的余额,从而引发错误。

注意,这里所说的同时并非真正意义上的同时,而是两个操作之间时间间隔极小,对比服务端的延迟,可以近似于同时。当然上述示例只是一个说明性的例子,因为仅仅只有两个用户时是很难做到同时的,所以在真正实际操作的时候,往往会设置很大的进程数或线程数同时发起请求,从而使得某两个进程或线程能够幸运地做到同时。