phpcms v9.任意文件上传漏洞复现

目录

📔环境

📔绕过任意文件上传漏洞(压缩包文件无递归删除)复现 

📓原理

📓方法

📓步骤 

📔绕过任意文件上传漏洞(压缩包文件递归删除)复现

📓原理

📓方法

📓步骤 

📔绕过任意文件上传漏洞(文件名随机数.未递归删除)复现 

📓原理

📓方法 

📓步骤

1.生成

2.修改 

3.脚本测试 

4.注意 

5.上传验证 

📔绕过任意文件上传漏洞(文件名随机数.递归删除)复现  

📓原理

📓方法

📓步骤

1.生成

2.修改

3.上传验证

📔防御方式

📓建立三道防御


📔环境

phpStudy搭建的测试网站

📔绕过任意文件上传漏洞(压缩包文件无递归删除)复现 

📓原理

$temp_dir = $dir . 'member/1/'; //传入文件解压后放在member/1/的路径下
if (!is_dir($temp_dir)) {   //判断文件是否原本存在不存在就mkdir一个member/1的文件
    mkdir($temp_dir);
}
$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);
}

这里的效果是解压压缩文件并查验是否符合'jpg', 'gif', 'png'文件类型,如果不符合就直接unlink删除

📓方法

由于上面的只是删除了上传文件中的木马而并没有递归删除上传文件中文件夹下的木马所以我们可以在压缩文件夹中再放入一个文件夹(内含图片+一句话文件) 

📓步骤 

📔绕过任意文件上传漏洞(压缩包文件递归删除)复现

📓原理

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);
                }
            }
        }
    }
}

 这次与之前不同的是增加了一条判断语句,判断了解压的文件下是否还存在文件夹,如果存在就检查发现可以木马直接删除达到了递归删除的效果

📓方法

由于它的删除是按照先解压后删除所以我们可以利用时间竞争来绕过,首先需要在web.php中写入如下方法:

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

📓步骤 

  

   

  

总结:时间竞争漏洞利用原理其实就是在解压文件后与删除限制的文件之间的时间空隙来利用提前在限制的文件中写好的利用代码在非解压目录下生成新的不会被删除的新文件(木马),通过这个木马来拿下网站

📔绕过任意文件上传漏洞(文件名随机数.未递归删除)复现 

📓原理

$temp_dir = $dir.md5(time(). rand(1000,9999)).'/'; //随机数生成文件,无法确定文件路径及文件名

if (in_array($ext, array('zip', 'jpg', 'gif', 'png'))) {
    if ($ext == 'zip') { // 解压zip文件
        $zip = new ZipArchive; //新建一个ZipArchive的对象
        if(!$zip->open($file['tmp_name'])) { //打开zip文件
            echo "fail";    //打开失败
            return false;   //返回false
        }
        if(!$zip->extractTo($temp_dir)) {   //解压到临时目录
            check_dir($temp_dir);   //递归删除临时目录
            exit("fail to extract"); //解压失败
        }
#这里如果解压出错
if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {
            
       exit("解压失败");
 }

#下面的递归删除就不会执行
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);
                }
            }
        }
    }
}

原理:这里我们通过利用解压文件在解压过程出错会导致后面的递归删除操作不会执行的特点 

if (in_array($ext, array('zip', 'jpg', 'gif', 'png'))) {
    if ($ext == 'zip') { // 解压zip文件
        $zip = new ZipArchive; //新建一个ZipArchive的对象
        if(!$zip->open($file['tmp_name'])) { //打开zip文件
            echo "fail";    //打开失败
            return false;   //返回false
        }
        if(!$zip->extractTo($temp_dir)) {   //解压到临时目录
  
            exit("fail to extract"); //解压失败
        }

📓方法 

 如果我们让上传的压缩包在解压过程出现错误那么就不会删除掉我们的php文件,前提是这个解压软件容忍程度要低,能够在出现错误后解压失败,终止解压,而容忍程度高会导致一些小错误忽略,成功解压文件,这样就达不到我们的需求,所以在Windows系统下7zip解压软件的容忍度相对其他软件较低,而这里是php中解压我们的文件,所以就依赖于PHP自带的ZipArchive库了,由于该库容忍程度较高,所以我们接着就考虑软件部分,这里我们需要使用010editor工具来构造一个校验码错误的压缩文件,致使该文件在php的ZipArchive库在解压时出现错误,由于Windows下不允许文件名中包含冒号(:),所以我们考虑修改在工具中将a.txt的deFileName属性的值改成"a.tx+冒号"的方法使其php解压时出现错误

📓步骤

1.生成

2.修改 

3.脚本测试 

3.验证前我们需要写一个php软件目录下的解压脚本,作用是验证解压失败的过程

<?php
    function unzip($zipname,$path) {  //解压缩函数
        $zip = new ZipArchive;  //新建一个ZipArchive的对象
        if(!$zip->open($zipname)) {      //打开压缩包
            echo "fail";     //如果打开失败,则终止函数
            return false;    //返回false,表示解压缩失败
        }

        if(!$zip->extractTo($path)) {  //解压缩到指定的文件夹
            echo "fail to extract"; //解压失败
            return false;         //返回false
        }

        $zip->close(); //关闭处理的zip文件
        return true; //解压缩成功
    } 

    if(unzip('./test.zip','./')) { //解压缩到当前文件夹
        echo "success zip"; //解压成功
    }else { 
        echo "failt to unzip"; //解压失败
    }

按照正常的逻辑这里解压失败后文件夹中还是会将php文件解压出来,但是却没有 

4.注意 

如果你也出现上面的情况请试试下面说的方法:这里有一个小坑注意,你在压缩前面的文件时要注意他们在压缩文件中的顺序,意思就是你创建的一个php文件在创建的txt文件的上面就可以成功,只有这样在解压失败后它还是能够保留并将php文件成功解压出来 

  

只有先创建txt文件后创建php文件才会有如下图的位置

5.上传验证 

上传我们处理过的压缩包验证木马是否上传成功

📔绕过任意文件上传漏洞(文件名随机数.递归删除)复现  

📓原理

$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文件
        $zip = new ZipArchive; //新建一个ZipArchive的对象
        if(!$zip->open($file['tmp_name'])) { //打开zip文件
            echo "fail";    //打开失败
            return false;   //返回false
        }
        if(!$zip->extractTo($temp_dir)) {   //解压到临时目录
            check_dir($temp_dir);   //递归删除临时目录
            exit("fail to extract"); //解压失败
        }

在之前的漏洞基础上它补充了一个递归删除的方法,这样做会将解压后的文件夹中的文件再进行递归删除

    $archive = new PclZip($file['tmp_name']);  //新建一个PclZip的对象
        // foreach($archive->listContent() as $value){   //获取解压后的文件列表
        //     $filename = $value["filename"];  //获取文件名
        //     if(preg_match('/\.php$/', $filename)){  //如果是php文件
        //          exit("压缩包内不允许含有php文件!");    //退出
        //      }
        // }
        
        if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {
            check_dir($dir);
            exit("解压失败");
        }

📓方法

虽然它对解压后的文件又进行了递归删除那么我们还可以考虑在压缩包解压的那一刻就让我们的php文件直接上传到非解压路径就可以避免被删除了,这里还是需要使用010editor工具来进行修改

../../php文件

📓步骤

1.生成

2.修改

这里需要修改掉php文件解压后的目标路径 ,还要同时修改掉txt文件的后缀让其解压失败然后保留php文件

3.上传验证

上传修改后端压缩包并在修改后的路径下查看是否有php文件生成


查看解压后文件路径 

查看修改后的路径下是否有php文件生成

 

📔防御方式

📓建立三道防御

1.使用imagecreatejpeg()函数,处理上传的图片通过打乱图片结构使恶意图片马无法生效

2.不要给文件执行权限,让上传的马所在文件无执行的权限

3.将上传文件放入临时文件夹中,这样即便木马上传成功但是它在临时文件夹中不会对我们网站造成危险

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 支持PHP8 2. 支持HTTPS环境 3. 支持MySQL8+ 4. 修改PHPCMS目录为CMS 5. 验证码修改 6. 支持H5上传,移除Flash上传 7. 修改后台缩略图裁切图片,移除Flash裁切改为H5裁切 8. 后台附件上传修改为H5上传,会员头像上传修改为H5上传 9. 修改后台界面,修改后台登录界面、后台锁屏界面、后台内容界面 10. 修改前台界面 11. 修复已知BUG 12. 修复已知安全漏洞 13. 增加安装时自定义后台管理登录地址 14. 去掉PHPSSO模块、去掉Video及视频库相关、去掉Upgrade在线升级 15. 去除了已被废弃的视频模块和视频模型 16. 修复安装时DNS解析错误提示 17. 手机电脑同时生成Html 18. 安装文件不检查index.html 19. 安装完删除安装目录 20. 安装删除友情链接、广告数据 21. 添加开启附件分站状态 22. 整合UEditor编辑器 23. UEditor整合上传水印 24. UEditor上传储存数据 25. 附件选择框UI 26. 优化附件选择器界面 27. 添加讯飞关键词获取API、百度关键词获取API,原官方关键词接口已失效 28. 后台添加复制,可复制一条新的到任何栏目或站点 29. 添加头像字段 30. 修改头像,重新写入库 31. 添加组图模式,图片模式、文本模式 32. 百度编辑器上传视频播放器由embed改成video标签 33. 添加本地关键词获取API,原官方关键词接口已失效 34. 添加站点自定义字段、栏目自定义字段、单网页自定义字段 35. 添加一键导入微信文章字段 36. 添加Word导入编辑器字段 37. 增加编辑器可下载微信图片本地化功能 38. 编辑器远程下载图片时加入对尺寸的压缩处理 39. 后台登录密码传输改为加密模式 40. 添加生成静态页进度条 41. 编辑器添加本地图片自动上传 42. 升级为CK4.16.1编辑器 43. 无用文件清理 44. 修改生成缩略图函数thumb 45. 修改获取用户头像函数get_memberavatar 46. 修改原来上传类处理文件,删除原上传类处理文件,新增Upload上传类处理文件 47. 修改原来图片处理类文件 48. 修改IP库类处理文件 49. 新增二维码处理类文件 50. 新增Input类处理文件 51. 新增判断是否是移动端终端is_mobile函数 52. 新增二维码qrcode函数 53. 新增秒转化时间sec2time函数 54. 新增友好时间显示函数dr_fdate 55. 新增时间显示函数dr_date 56. 新增递归创建文件夹create_folder函数 57. 新增调用远程数据dr_catcher_data函数 58. 新增获取远程附件扩展名get_file_ext函数 59. 新增栏目面包屑导航dr_catpos函数 60. 新增手机栏目面包屑导航dr_mobile_catpos函数 61. 新增手机分页函数mobilepages 62. 新增重新日志记录函数log_message 63. 新增目录扫描dr_dir_map函数 64. 新增文件扫描dr_file_map函数 65. 新增数据返回统一格式dr_return_data函数 66. 新增格式化输出文件大小format_file_size函数 67. 新增附件信息get_attachment函数 68. 新增统一返回json格式并退出程序dr_json函数 69. 新增将数组转换为字符串dr_array2string函数 70. 新增将字符串转换为数组dr_string2array函数 71. 新增根据文件扩展名获取文件预览信息dr_file_preview_html函数 72. 新增IP转为实际地址ip2address函数 73. 新增当前IP实际地址ip_address_info函数 74. 新增清除HTML标记clearhtml函数 75. 新增提取关键字dr_get_keywords函数 76. 新增提取描述信息dr_get_description函数 77. 新增获取内容中的缩略图get_content_img函数 78. 新增HTML实体字符转换code2html函数 79. 新增判断存在于数组中dr_in_array函数 80. 新增字符长度dr_strlen函数 81. 新增将路径进行安全转换变量模式dr_safe_replace_path函数 82. 新增站点手机配置 83. 新增是否需要检查外部访问 84. 新增关联字段 85. 新增信息表格字段 86. 新增单文件上传字段 87. 水印图片的透明度设置 88. 增加内容编辑时的更新时间字段

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值