条件竞争漏洞小结

admin 2025-12-25 03:11:46 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文深入解析条件竞争漏洞原理,即多线程并发操作共享资源未加锁引发的数据异常。通过购买超限、绕过次数限制及文件上传竞争等实战案例,揭示了其在Web层面的危害。建议对关键业务对象加锁、完善文件检查流程并保护共享数据,以有效防范此类并发风险。 综合评分: 91 文章分类: WEB安全,漏洞分析,安全开发,渗透测试


cover_image

条件竞争漏洞小结

原创

initsec

初始安全

2022年3月1日 17:35

本文内容仅供学习交流使用,请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,初始安全团队以及文章作者不为此承担任何责任。

Author:d4m1ts

前言

介绍

条件竞争漏洞发生在多个线程同时访问同一个共享代码、变量、文件等,但没有进行锁操作或者同步操作的场景中。这个漏洞存在于操作系统、数据库、web 等多个层面,像有名的脏牛(dirty cow)。

条件竞争漏洞属于服务器端漏洞,由于大多服务端框架在处理不同用户的请求时是并发进行的,而开发者在进行代码开发时常常倾向于认为代码会以线性的方式执行,而忽视了并行服务器会并发执行多个线程,这就会导致意想不到的结果;

[!tip]

简单来说,就是多线程同时操作一个对象,而没有对对象进行加锁等保证一致性的操作

举例

以 python 多线程代码举一个不恰当的例子

#!/usr/bin/env python

from concurrent.futures import ThreadPoolExecutor

def test():
    global globalNum
    if globalNum >= 5:
        print("globalNum >= 5 now")
        globalNum -= 1

if __name__ == '__main__':
    globalNum = 5
    pool = ThreadPoolExecutor(max_workers=10)
    for _ in range(5):
        pool.submit(test)

咋一看,globalNum初始值为 5,一个 5 次的 for 循环,每次globalNum-1,那么按理说只有第一次调用test函数的时候print会有输出才对,但是我们运行起来看看结果,却有 2 次print输出

示例代码结果

而产生这种结果的原因,就是多线程同时操作变量globalNumglobalNum还没来得及完成修改就被带入到另一个test()函数中,也就是对并发操作的敏感变量没有加锁保护等。

应用场景

[!note]

结合参数在后端的处理过程,所有后端应该对数据进行加锁或者同步的功能点,都可能存在此漏洞,如购买、签到、转账、兑换等

总的来说有如下几类:

  1. 购买/兑换操作
  2. 绕过次数限制
  3. 绕过多过程处理

下面举几个例子抛砖引玉

购买

假设:用户 A 有 100 元,要买一件 100 元的商品

且后端处理流程:判断A的余额是否>=100 ==> A的余额-100,商品数量+1 (没有对 A 的余额进行加锁操作)

正常情况下,A 购买完一件商品余额就清零了,但攻击者通过并发发起 20 个请求,后端接收到后,也会并发发起 20 次上述的处理流程,而在同一时间(A的余额-100之前)去判断A的余额是否>=100,肯定都是满足的,那么商品数量就会多次+1,也就达到了 100 元购买多件 100 元商品的目的

[!tip]

这个漏洞具有偶现性,很受环境因素的影响,比如网络延迟、服务器的处理能力等,所以只执行一次可能并不会成功,尽量多尝试几次

绕过次数操作

最容易想到的就是绕过签到次数限制,大多数平台都是一天只允许签到一次,如果后端对是否签到的判断不严,那么我们就可以通过并发达到一天签到多次的目的。这里举一个之前类似的挖到的某网盘绕过大小限制的操作。

某云盘

前提:该云盘普通用户只允许上传 10G 空间,想要获得更大的空间就需要开会员

猜测后端处理过程:识别上传文件大小 ==> 当前已用空间+上传文件大小是否>=10G ==> <=10G,上传成功 / >10G,上传失败

我的测试过程:怀疑上传过程中,后端可能没有对已用空间做加锁机制来防止并发操作带来的条件竞争问题,因此我先上传了 1G 的文件,然后 50 个线程并发复制这 1 个文件,最终成功上传了超过 10G 的文件到服务器中。

绕过多过程处理

这个也是大家听说过最多的,常用的场景:上传 webshell 时,服务端会先存储该文件,然后判断文件内容是否包含恶意内容,如果包含就删除;

我们可以通过并发不停的向服务器上传 webshell,虽然服务器会不断的检查并删除我们上传的文件,但由于我们在一直不间断的上传,服务器可能会还没来得及删除 webshell,我们就已经执行了相关的命令达到目的了。

天下武功,唯快不破

修复建议

  1. 对于业务端条件竞争的防范,一般的方法是给对象加锁;
  2. 对于文件上传,一定要经过充分完整的检查之后再上传;
  3. 在操作系统的角度,共享数据要进行上锁保护。

扩展

前面一直在说加锁加锁,到底什么是加锁?

线程编程中,为了保证数据操作的一致性,操作系统引入了锁机制,用于保证临界区代码的安全。通过锁机制,能够保证在多核多线程环境中,在某一个时间点上,只能有一个线程进入临界区代码,从而保证临界区中操作数据的一致性

临界区指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。

参考

  • 条件竞争(Race condition)漏洞挖掘技巧及实战案例[1]

参考资料

[1]

条件竞争(Race condition)漏洞挖掘技巧及实战案例: https://cloud.tencent.com/developer/article/1516412


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:初始安全 initsec《条件竞争漏洞小结》

评论:0   参与:  0