文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

FineCMS任意头像上传漏洞复现:文件的四次上传

2023-09-24 12:33

关注

目录

文件上传

1、文件上传完整代码

PHP代码

<?phpheader("Content-Type:text/html; charset=utf-8");require_once('pclzip.lib.php');// echo "
";// var_dump($_POST['username']);exit;// // var_dump(file_get_contents("php://input"));exit;// // var_dump($GLOBALS['HTTP_RAW_POST_DATA']);exit;// if (!isset($GLOBALS['HTTP_RAW_POST_DATA'])) {//     exit('环境不支持');// }// // 创建图片存储文件夹// $dir = 'upload/';// if (!file_exists($dir)) {//     mkdir($dir);// }function check_dir($dir){    $handle = opendir($dir);    while(($f = readdir($handle)) !== false){        if(!in_array($f, array('.', '..'))){            if(is_dir($dir.$f)){                check_dir($dir.$f.'/');             }else{                $ext = strtolower(substr(strrchr($f, '.'), 1));                if(!in_array($ext, array('jpg', 'gif', 'png'))){                    unlink($dir.$f);                }            }        }    }}// // 创建图片存储的临时文件夹// $temp = $dir.'member/1/';// if (!file_exists($temp)) {//     mkdir($temp);// }// $filename = $temp.'avatar.zip'; // 存储flashpost图片// file_put_contents($filename, $GLOBALS['HTTP_RAW_POST_DATA']);// //第三次绕过// // $zip=new ZipArchive;//新建一个ZipArchive的对象 // // if(!$zip->open($filename)){// //     //check_dir($dir);// //     exit("fail to open zip file");// // }// // if(!$zip->extractTo($temp)) {// //     exit("fail to extract zip file");// // }// $archive = new PclZip($filename);// if ($archive->extract(PCLZIP_OPT_PATH, $temp, PCLZIP_OPT_REPLACE_NEWER) == 0) {//        check_dir($dir);//        exit("解压失败");// }// check_dir($dir);// exit('success');$file = $_FILES['file'];if (!$file) {    exit("请勿上传空文件");}$name = $file['name'];$dir = 'upload/';$ext = strtolower(substr(strrchr($name, '.'), 1));//递归删除  zip  1   web.php// function check_dir($dir)// {//     $handle = opendir($dir);//     while (($f = readdir($handle)) !== false) {//         if (!in_array($f, array('.', '..'))) {//             $ext = strtolower(substr(strrchr($f, '.'), 1));//             if (!in_array($ext, array('jpg', 'gif', 'png'))) {//                 unlink($dir . $f);//             }//         }//     }// }// mkdir($dir);if (!is_dir($dir)) {    mkdir($dir);}$temp_dir = $dir.md5(time(). rand(1000,9999)).'/';// $temp_dir = $dir . 'member/1/';if (!is_dir($temp_dir)) {    mkdir($temp_dir);}if (in_array($ext, array('zip', 'jpg', 'gif', 'png'))) {    if ($ext == 'zip') {        // $zip = new ZipArchive;        // if(!$zip->open($file['tmp_name'])) {        //     echo "fail";        //     return false;        // }        // if(!$zip->extractTo($temp_dir)) {        //     check_dir($temp_dir);        //     exit("fail to extract");        // }        $archive = new PclZip($file['tmp_name']);        // foreach($archive->listContent() as $value){        //     $filename = $value["filename"];        //     if(preg_match('/\.php$/', $filename)){        //          exit("压缩包内不允许含有php文件!");        //      }        // }                if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {            check_dir($dir);            exit("解压失败");        }        check_dir($temp_dir);        exit('上传成功!');    } else {        move_uploaded_file($file['tmp_name'], $temp_dir . '/' . $file['name']);        check_dir($temp_dir);        exit('上传成功!');    }} else {    exit('仅允许上传zip、jpg、gif、png文件!');}

HTML代码

DOCTYPE html><html lang="zh"><head>    <meta charset="UTF-8" />    <meta name="viewport" content="width=device-width, initial-scale=1.0" />    <meta http-equiv="X-UA-Compatible" content="ie=edge" />    <title>文件上传章节练习题title>    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">    <style type="text/css">        .login-box{            margin-top: 100px;            height: 500px;            border: 1px solid #000;        }        body{            background: white;        }        .btn1{            width: 200px;        }        .d1{            display: block;            height: 400px;        }    style>head><body>    <form method="post" action="upload.php" enctype="multipart/form-data">        <input type="file" name="file" value=""/>        <input type="submit" name="submit" value="upload"/>    form>body>html>

2、第一次上传 【无递归删除】

1、PHP代码【含代码解析】

header("Content-Type:text/html; charset=utf-8");require_once('pclzip.lib.php');$file = $_FILES['file'];if (!$file) {    exit("请勿上传空文件");}$name = $file['name'];$dir = 'upload/';$ext = strtolower(substr(strrchr($name, '.'), 1)); //拿出最后的后缀为.的后面内容function check_dir($dir){    $handle = opendir($dir);    while (($f = readdir($handle)) !== false) {        if (!in_array($f, array('.', '..'))) {            $ext = strtolower(substr(strrchr($f, '.'), 1));            if (!in_array($ext, array('jpg', 'gif', 'png'))) {                   unlink($dir . $f);  //直接删除            }        }    }}$temp_dir = $dir . 'member/1/';   //临时文件,这里1其实应该代表有用户IDif (!is_dir($dir)) {       //判断文件有无文件    mkdir($dir);}if (in_array($ext, array('zip', 'jpg', 'gif', 'png'))) { //判断文件后缀    if ($ext == 'zip') {     $archive = new PclZip($file['tmp_name']);//打开压缩包,后面进行解压    if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {            check_dir($dir);            exit("解压失败");        }        check_dir($temp_dir);  //运用check_dir函数,判断文件把不符合规则的文件类型删除        exit('上传成功!');    } else {        move_uploaded_file($file['tmp_name'], $temp_dir . '/' . $file['name']);       // check_dir($temp_dir);        exit('上传成功!');    }} else {    exit('仅允许上传zip、jpg、gif、png文件!');}

2、简述代码整体运行过程与破解

上述过程就是上传压缩包,然后打开压缩包看里面文件类型进行删除与保留。

此过程想要上传恶意代码很简单,因为它打开压缩包打开的内容包括各种文件。但是它只扫描它打开的这层文件中的内容。即不会扫描文件夹里的内容。

3、测试代码

1、压缩包包含php与图片文件上传 【被删除PHP文件】

在这里插入图片描述

上传压缩包,并且尝试在内容里面加入PHP文件

在这里插入图片描述

上传文件结果

在这里插入图片描述

查看结果:创建了upload文件,并且发现在文件夹1中只有图片,成功过滤了PHP文件

在这里插入图片描述
在这里插入图片描述

2、压缩包包含文件夹与图片文件上传 【没有删除PHP文件】

由代码查看发现他编码进行递归查询,如此就不会第二次打开文件夹的。为此我们才有包含文件夹进行绕过删除文件。

创建文件夹web1
在这里插入图片描述

将web1文件压缩同图片文件一起压缩
在这里插入图片描述
上传压缩包
在这里插入图片描述

弹出的第二行错显示了 Permission denied,表示它没有权限删除我们创建的文件夹web1。

查看上传内容:文件夹没有被删除,但是php文件被删除了。
在这里插入图片描述

继续查看web1文件夹的内容

在这里插入图片描述
我们发现web1文件没有删除为此就绕过删除了。

这不用时间竞争型漏洞,因为要试很多次。【也可以用,只是麻烦了】
有更好的把上传的压缩包包含文件夹
unlink:直接删除 【只能删除文件不能删除文件夹,因为没有递归删除】

4、防御第一次绕过

既然我们知道了它没有进行递归查询,没有检测文件夹内容。我们就修改函数使用递归

function check_dir($dir){    $handle = opendir($dir);    while(($f = readdir($handle)) !== false){        if(!in_array($f, array('.', '..'))){            if(is_dir($dir.$f)){//判断是否还有文件夹                check_dir($dir.$f.'/');   //再次调用函数             }else{                $ext = strtolower(substr(strrchr($f, '.'), 1));                if(!in_array($ext, array('jpg', 'gif', 'png'))){                    unlink($dir.$f);                }            }        }    }}

函数内再次检测了文件,对文件夹进行检测。

3、第二次上传 【有递归查询】

1、PHP 代码 【修改第一次上传的函数内容】

function check_dir($dir){    $handle = opendir($dir);    while(($f = readdir($handle)) !== false){        if(!in_array($f, array('.', '..'))){            if(is_dir($dir.$f)){//判断是否还有文件夹                check_dir($dir.$f.'/');   //再次调用函数             }else{                $ext = strtolower(substr(strrchr($f, '.'), 1));                if(!in_array($ext, array('jpg', 'gif', 'png'))){                    unlink($dir.$f);                }            }        }    }}

2、简述代码整体运行过程与破解

上述代码进行解压压缩包,对文件再次检索查看是否有文件夹。当有文件夹再次运行函数打开文件夹,再在文件夹中再次检索。直到没有文件夹检索为至。

这个方法虽然解决了第一次上传文件夹不背扫描问题,但是并没有解决第一个上传仍然存在的时间竞争漏洞。为此我们可以采用时间竞争漏洞绕过

3、测试代码

1、压缩包包含文件夹与图片文件上传 【PHP文件被删除】

选择新建文件夹.zip
在这里插入图片描述
成功上传我们查看文件夹web1 是否内部php被过滤
在这里插入图片描述
我们发现它成功过滤了文件夹内的PHP文件
在这里插入图片描述

2、时间竞争型漏洞绕过
1、编写竞争代码

在删除之前访问上传的php文件,从而执行上传文件中的php代码。

竞争型文件上传过程介绍
文件上传过程:
服务器获取文件>>>保存上传临时文件>>>重命名移动临时文件

编写PHP代码,将要删除前重命名实现移动文件【跳三层到xss_location目录】

fputs(fopen('../../../payload.php','w'),'');?>

上传web1.zip 【其中1.php代码修改为了上述代码】
在这里插入图片描述

2、Burp Suite抓取上传包
1、准备工作

开启抓包
在这里插入图片描述
将手工代理开启【代理端口与Burp Suite设置的一样】
在这里插入图片描述

在这里插入图片描述

将本地地址改为本机IP一致
在这里插入图片描述

2、开始抓包

上传文件抓包
在这里插入图片描述
上图成功被拦截,并且拦截的是压缩包 【拦截中的PK代表压缩包】
在这里插入图片描述
将其抓取内容放到爆破中
在这里插入图片描述
先clear掉符号
在这里插入图片描述
随后找个数字进行添加字符
在这里插入图片描述
让其运行2000次
在这里插入图片描述

如果想手动访问也可以就要访问169.254.2.70/xss_location/mermber/1/1/web1.php,手动刷新页面。【要关拦截】

开始访问
在这里插入图片描述

结果查看
在这里插入图片描述

4、防御第二次上传

因为时间竞争型漏洞是猜到了存储文件的,为此我们将其创建文件名方式进行修改。使用对文件随机数进行命名。

$temp_dir = $dir.md5(time(). rand(1000,9999)).'/';// $temp_dir = $dir . 'member/1/';

3、第三次上传 【随机命名防止时间竞争漏洞】

1、PHP代码改进 【文件随机命名】

$temp_dir = $dir.md5(time(). rand(1000,9999)).'/';// $temp_dir = $dir . 'member/1/';

2、简述代码整体运行过程与破解

不同之前是将上传文件创建的 文件夹随机命令。导致无法猜测到文件名进行恶意代码上传。
在这里插入图片描述

从结果上来看我们确实是无法在解压后运用条件绕过了删除,那我们就可以考虑在解压过程中下手。即实现当解压一半出错,它直接跳转解压失败不进行条件判断删除PHP文件了。

3、解压一个出错的zip【知识点补充】

这个问题其实需要看具体情况,看解压的那个程序的容忍程度,我这里就以两个解压的程序作为例子:

  1. Windows下的7zip
  2. PHP自带的ZipArchive库
  3. 先说7zip。7zip的容忍度很低,只要压缩包中某一个文件的CRC校验码出错,就会报错退出。 如何修改压缩包里文件的CRC校验码呢?可以使用010editor。
    在这里插入图片描述
    4.我们先准备两个文件。【简单点我就用现在的文件夹】我们用010editor打开zip,可以看到右下角有这个文件的格式信息,它被分成几部分,我们打开第6部分【png那个】,其中有个deCrc,我们随便把值改成其他的值,然后保存.
    在这里插入图片描述

修改内容并且保存
在这里插入图片描述

进行解压
在这里插入图片描述

如此我们发现出错了。但是PHP依旧解压了
此时用7zip解压就会出错,解压出的PHP是完好的,另一个文件是图片出现错所以无法显示了,【如果是txt,会显示文件但是因为报错内容无法显示就只有txt文件】
在这里插入图片描述

接下来我们说一下PHP的解压。
采用一个PHP的解压代码测试【为了方便我把压缩包移动到同级目录下】
在这里插入图片描述

    function unzip($zipname, $path) {        $zip = new ZipArchive;        if(!$zip->open($zipname)) {            echo "fail";            return false;        }        if(!$zip->extractTo($path)) {            echo "fail to extract";            return false;        }        $zip->close();        return true;    }    if(unzip('./web1.zip', './')) {        echo "success zip";    }else {        echo "failt to unzip";    }

采用在Windows中使用PHP来解压
在这里插入图片描述
他成功解压了并且中目录里
在这里插入图片描述

如果压缩入txt文件【文件内容为zzzzzz,压缩包为hhhh.zip,修改php内容文件为hhhh.zip】 同样先修改deCrc
在这里插入图片描述
依旧成功
在这里插入图片描述
并且不同Windows会是txt文件没有内容
在这里插入图片描述

综上我们发现在PHP中是好像无采用压缩包报错绕过,但是如果文件内容无法修改就文件

这也说明ZipArchive的容忍度比较高。 那么我们又如何让ZipArchive出错呢?最简单的方法,我们可以在文件名上下功夫。
比如,Windows下不允许文件名中包含冒号(:),我们就可以在010editor中将2.txt的deFileName属性的值改成“2.tx:”,

在这里插入图片描述
再次解压
在这里插入图片描述
发现对文件解压时出错了。【目录下也解压出来php,没有txt】
Linux下也有类似的方法,我们可以将文件名改成5个斜杠(/)

总结;
1.Windows系统下7zip的容忍度很低,只要压缩包中某一个文件的CRC校验码出错,就会报错退出
2.PHP代码中 .。
使用zip解压时deCrc,我们随便把值改成其他的值,然后保存就可以出错。
使用7z情况下修改文件名Windows下不允许文件名中包含冒号(:),我们就可以在010editor中将2.txt的deFileName属性的值改成“2.tx:”
3.linux系统将文件名改成5个斜杠(/)【前提这个压缩至少有五个字符可以修改】

4、测试代码

1、上传错误压缩包绕过删除

采用上述的压缩包上传。
因为使用PHP类要修改一下

// //第三次绕过$zip=new ZipArchive;//新建一个ZipArchive的对象 if(!$zip->open($filename)){    //check_dir($dir);    exit("fail to open zip file");}if(!$zip->extractTo($temp)) {    exit("fail to extract zip file");}// $archive = new PclZip($filename);// if ($archive->extract(PCLZIP_OPT_PATH, $temp, PCLZIP_OPT_REPLACE_NEWER) == 0) {//        check_dir($dir);//        exit("解压失败");// }

结果表示未能提取【上传了hhhh.zip,包含php文件,与txt文件】
查看上传文件是否成功有php
在这里插入图片描述

发现成功上传php,但是因为txt出错没有被上传。并且因为出错绕过了判断而没有删除

5、防御第三次绕过

既然我们知道他是在是解压过程在避开递归删除
如此对应防御:如果在解压到php后就先递归删除再解压下一个文件,就算退出但是第一个已经递归删除过了就解决问题了

  if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {            check_dir($dir); //解压成功一个后进行递归删除            exit("解压失败");        }

4、第四次绕过 【在之前基础上对解码后的文件进行递归删除】

1、PHP代码 【在解码后进行递归删除】

  if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {            check_dir($dir); //解压成功一个后进行递归删除            exit("解压失败");        }

2、简述代码整体运行过程与破解

代码的之前代码基础上当解码失败后,不会直接保存而是再进行删除递归后才真正的结束、

相较于第三次的防御解决方法 可以尝试命名php为的value为…/…/aaa.php
即解压完后修改名称,如此是解压到上级目录 使用工具修改aaaaaaaaa.php改为…/…/aaa.php

3、测试代码

1、上传修改了value的php文件

同之前一样修改【改为txt:,与…/…/aaa.php】

在这里插入图片描述
php的修改只要是有aaaaaaaaaaaaaa.php原来名字的文件都修改

在这里插入图片描述
查看上上级目录是否有对应php文件
在这里插入图片描述

总结

第一次绕过代码没有文件再次检测,采用传包含文件夹的压缩包绕过或使用时间竞争漏洞绕过
2、第二个绕过代码添加了递归对文件夹再次检测,但由于没有间竞争漏洞绕过问题。使用间竞争漏洞绕过
3、第三次绕过代码进行随机命名文件无法猜文件名间竞争漏洞绕过失效,但是可以采用解压一半报错保存php文件
4、第四次绕过代码对报错保留的文件进行了递归删除,但是我们可以欺骗系统将解码的文件判定为上级目录文件规避了递归在当前目录下是所有检测。

其实这种漏洞补一处出现处,要从根本解决。
根本原因:它是在网站的根目录下解压文件,用户可以访问。
解决:为此在临时文件夹中解压,再把需要的文件提取到网站目录下。

来源地址:https://blog.csdn.net/Miracle_ze/article/details/126347577

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯