phpcms头像上传漏洞引发的故事

目录

关键代码

第一次防御

第一次绕过

第二次防御

第二次绕过

第三次防御

第三次绕过

如何构造一个出错的压缩包

第四次防御

第四次绕过


 

本篇文章是参考某位大佬与开发人员对于文件包含漏洞的较量记录下的故事,因为要学习文件包含漏洞,就将大佬的文件作为参考来通过学习+练习的方式复现一下这次较量的全过程

故事还要从phpcms曾经火极一时的头像上传漏洞说起,因为这个漏洞,互联网上大量站点被黑,影响极为恶劣。

简单来说phpcms对头像上传是这么处理:上传上去的zip文件,它先解压好,然后删除非图片文件。

关键代码

前端代码:

<!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>

后端代码:

<?php
header("Content-Type:text/html; charset=utf-8");
require_once('pclzip.lib.php');$file = $_FILES['file'];
if ($file['size'] == 0) {exit("请勿上传空文件");
}
$name = $file['name'];
$dir = 'uploads/';
$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);}}}}if (!is_dir($dir)) {mkdir($dir);
}$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 zip');// }$archive = new PclZip($file['tmp_name']);if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {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文件!');
}

第一次防御

访问前端页面发现我们是可以上传一个文件的,因此这样就可以创建一个phpinfo.php文件和一个1.jpg文件,然后放在php文件夹中,然后将该文件夹压缩上传:

d778b2561c36425da6dcd7fdddd9eae9.png

然后尝试进行上传该压缩包:

上传完成后可以看到上传成功了

b0182a870abe46ffb50f0c5342d26aa6.png

然后我们可以在那个对应的目录中进行查看上传后的文件内容:

6e86e784bc294075bba4a32ce9ecc5bc.png

可以看到上传后的文件只剩下了一个1.jpg文件,和它一起在压缩包中的phpinfo.php文件被删除了

第一次绕过

这里那就无法上传php文件了,那么我们就真的就没有办法了吗?大佬告诉了我们解决方案:

通过代码审计,可以看到,它删除的时候没有递归删除也没有删除文件夹

这样,只要我们的webshell放在压缩包的文件夹中,就可避免被删除了。

因此这样就可以创建一个phpinfo文件夹里面再放入一个phpinfo.php文件一个单独的1.jpg文件,然后放在php2文件夹中,然后将该文件夹压缩上传:

8e38a5b9bcd3490c97e13dccd785633b.png

上传完成后可以再去uploads文件夹中查看就会发现已经成功的上传了php文件了

82b8291ca7764749b52a77b6345f9742.png

可以看到,现在就成功的上传了phpinfo文件并且里面的phpinfo.php文件保留了下来,并且1.jpg也上传了,这样就成功的绕过了限制

第二次防御

后面网页管理员对网页进行了一些安全加固,将后端的检查文件代码修改为下列的形式:

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

第一次绕过的方法的根本原因是因为没有考虑文件在文件夹中的情况,只删除了压缩包根目录下的非法文件,而没有删除其文件夹中的非法文件。

所以补丁就采用了递归删除的方式,将压缩包中所有非法文件删除。

但是采用了递归的方式就真的可以防御好了吗?并不是的

第二次绕过

因为通过分析代码后发现,删除的方式是先上传后删除,那么就可以尝试利用上传成功和删除的时间差来尝试访问该文件

因此这里使用Burpsuite来进行不断的上传,然后手动的访问一下上传后的文件看看会不会成功呢

首先使用Burpsuite对上传页面进行抓包,然后发送到intruder页面,添加payload:

07fe8d37aac241529b9541e37209a2bd.png

然后设置发送1000个包,然后开始

b6b098e4a9c841c9ab0210182659190d.png

下面就是尝试快速的不断的访问一下上传后的php文件:
d3f7e8fde29748fabcdb9cf7e8a4eccf.png

可以看到通过上传后与删除的时间差是可以访问到php文件的,因此这种防御方法也是可以绕过的

第三次防御

上面的绕过方法出现后,后端人员也是快速的修改了,增加了一下代码:

$temp = FCPATH.'cache/attach/'.md5(uniqid().rand(0, 9999)).'/';

就是将压缩包放在一个随机命名的文件夹中再解压缩,这样你猜不到访问地址也就没法去暴力getshell了。

第三次绕过

通过对后端代码的审计后,发现当解压发生失败时,就退出解压缩过程。

这也是一个很平常的思路,失败了肯定要报错并退出,因为后面的代码没法运行了。

但是,程序员不会想到,有些压缩包能在解压到一半的时候出错。

什么意思,也就说我可以构造一个“出错”的压缩包,它可以解压出部分文件,但绝对会在解压未完成时出错。这是造成了一个状况:我上传的压缩包被解压了一半,webshell被解压出来了,但因为解压失败这里exit($this->pclzip->zip(true));退出了程序执行,后面一切的删除操作都没有了作用。

如何构造一个出错的压缩包

因为这里我们首先构造一个解压会出错的压缩包,这里龙哥给我们交了几种好用的方法:

我这里就以两个解压的程序作为例子:

  1. Windows下的7zip

  2. PHP自带的ZipArchive库

7zip的容忍度很低,只要压缩包中某一个文件的CRC校验码出错,就会报错退出。

如何修改压缩包里文件的CRC校验码呢?可以使用010editor。

我们先准备两个文件,一个PHP文件1.php,一个文本文件2.txt,其中1.php是webshell。

然后将这两个文件压缩成shell.zip。

然后我们用010editor打开shell.zip,可以看到右下角有这个文件的格式信息,它被分成5部分

ba5bc0681f4d4bd19f637a428c89cdbe.png

c4d9256f7c224229ac5a3d45943bf6a1.png

我们打开第4部分,其中有个deCrc,我们随便把值改成其他的值,然后保存。

cc6235d8fd7f43fbb19fa06254014e58.png

此时用7zip解压就会出错,解压出的1.php是完好的,2.txt是一个空文件。

6ae51932c36848389f856d96d2bb8c07.png

我们再用PHP自带的ZipArchive库,测试这个zip,发现解压并没有出错,这也说明ZipArchive的容忍度比较高。

那么我们又如何让ZipArchive出错呢?最简单的方法,我们可以在文件名上下功夫。

比如,Windows下不允许文件名中包含冒号(:)

我们就可以在010editor中将2.txt的deFileName属性的值改成“2.tx:”。

1ac6ddd74ee24213a87bd1f50ef03461.png

此时解压就会出错,但1.php被保留了下来。

注:在Linux下也有类似的方法,我们可以将文件名改成5个斜杠(/)。

因此这里我们第三次绕过的思路有出来了,使用一个会报错的zip文件,上传后会将php文件解压问成功,进行报错了,因此php文件会被保留

第四次防御

这里的漏洞也是被后端人员发现后修复了,因此将代码修改为下面的形式:

        if(!$zip->extractTo($temp_dir)) {check_dir($temp_dir);exit('fail to zip');}

可以看到,它会对解压失败的文件也进行一次检查,将里面非图片的文件删除 

第四次绕过

但是这样真的就安全了吗?答案是不安全的

压缩包中通常是不含有诸如“../”、“..”这种文件名的,但通常不含有不代表不能含有。

如果把压缩包中某文件名改成../../../../../index.php,是不是就能直接把你首页变成我的webshell呀?

这就是因为抄袭者并没有真正领悟zip这个类的使用方法,导致了这个安全问题。

先把自己的shell改名字成aaaaaaaaaaaaaaaaaaaa.php

之所以起这个名字,就是预留一些空间,方便我之后将文件名改成../../../aaaaaaaaaaa.php而不用怕字符串长度不对。

把文件直接打包成zip,用010editor打开:

将画框的俩文件名的前9个字符改成../../../

a3eea48173024483b5f80bdf26f98df8.png

然后再上传就可以成功上传了

总结一下:

1、没有对上传的文件进行递归删除,导致文件夹中的目录可以上传

2、先上传,后删除,可以利用时间竞争来访问上传后的文件

3、对上传后的文件进行一个重命名,随机名称,可以利用解压报错绕过

4、对解压后的文件进行检查,可以利用../../路径穿越进行绕过

到此这个黑客大佬与后端开发人员的对抗就结束了,但是还有很多web页面存储漏洞仍然存在着漏洞等着我们去发现

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/278465.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024-Spring IOC 和 AOP源码分析(上篇)

**前言&#xff1a;**笔者最近面了几次大厂。。。开局Spring源码暴击 之前看过忘了写篇总结。。。 1、介绍一下Spring 核心组件&#xff1a; 常用模块&#xff1a; 常用注解&#xff1a; 2、说一下SpringIOC原理 概念&#xff1a;Spring 通过一个配置文件描述 Bean 及 B…

二叉树算法

递归序 每个节点都能回到3次! 相当于2执行完然后返回了代码会往下走,来到3节点 小总结: 也就是4节点先来到自己一次,不会执行if,先调用自己左边的那个函数,但是是null,直接返回。 这个函数执行完了,就会回到自己,调用自己右边的那个函数,结果又是空,又返回,回到…

Elasticsearch:调整近似 kNN 搜索

在我之前的文章 “Elasticsearch&#xff1a;调整搜索速度”&#xff0c;我详细地描述了如何调整正常的 BM25 的搜索速度。在今天的文章里&#xff0c;我们来进一步探讨如何提高近似 kNN 的搜索速度。希望对广大的向量搜索开发者有一些启示。 Elasticsearch 支持近似 k 最近邻…

基于vue实现bilibili网页

学校要求的实验设计,基于vue实现bilibili网页版,可实现以下功能 (1)基本的悬浮动画和页面渲染 (2)可实现登录和未登录的页面变化 (3)在登录页面的,实现密码判断,或者短信验证方式的倒数功能 (4)实现轮播图 (5)实现预览视频(GIF) (6)页面下拉到一定高度出现top栏以及右下角的返回…

每日五道java面试题之mybatis篇(一)

目录&#xff1a; 第一题. MyBatis是什么&#xff1f;第二题. ORM是什么?第三题. 为什么说Mybatis是半自动ORM映射工具&#xff1f;它与全自动的区别在哪里&#xff1f;第四题. 传统JDBC开发存在的问题第五题. JDBC编程有哪些不足之处&#xff0c;MyBatis是如何解决这些问题的…

UE5数字孪生系列笔记(二)

智慧城市数字孪生系统 制作流云动画效果 首先添加一个图像在需要添加流云效果的位置 添加动画效果让其旋转 这个动画效果是程序开始就要进行的&#xff0c;所以要在EventConstruct中就可以启动这个动画效果 添加一个一样的图像在这里&#xff0c;效果是从此处进行放大消散 添…

python 调用redis创建查询key

部署redis apiVersion: apps/v1 # 描述api版本&#xff0c;默认都用这个 kind: Deployment # 资源类型&#xff0c;可以配置为pod&#xff0c;deployment&#xff0c;service&#xff0c;statefulset等等 metadata: # deployment相关的元数据&#xff0c;用于描述deployment的…

Python——字典

一、字典特性介绍 字典在 Python 中极为重要&#xff0c;是属于映射类型的数据结构。 字典有⼀对⼉⼤括号组成 {} , 字典内的元素都是成对⼉出现的 {"a":1} , 他们⽤英⽂的冒号( : )隔开, 左边叫做键(key),右边的叫值(value), 通常叫做键值对⼉。 每个元素⽤英⽂的逗…

设计模式深度解析:工厂方法模式与抽象工厂模式的深度对比

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 设计模式深度解析&#xff1a;工厂方法模式与抽象工厂模式的深度对比 探索设计模式的魅力&#x…

Redis 八种常用数据类型详解

夯实基础&#xff0c;这篇文章带着大家回顾一下 Redis 中的 8 种常用数据类型&#xff1a; 5 种基础数据类型&#xff1a;String&#xff08;字符串&#xff09;、List&#xff08;列表&#xff09;、Set&#xff08;集合&#xff09;、Hash&#xff08;散列&#xff09;、Zse…

Vue.js+SpringBoot开发食品生产管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 加工厂管理模块2.2 客户管理模块2.3 食品管理模块2.4 生产销售订单管理模块2.5 系统管理模块2.6 其他管理模块 三、系统展示四、核心代码4.1 查询食品4.2 查询加工厂4.3 新增生产订单4.4 新增销售订单4.5 查询客户 五、…

rocky9 编写一键安装mysql 的sh脚本

基本操作步骤 1、虚拟机最小化安装rocky9系统&#xff0c;安装后克隆一个系统&#xff1b;1个用来获取下载的rpm包&#xff0c;一个用来编写sh 测试脚本&#xff1b; 2、修改虚拟机的 yum配置文件&#xff0c;获取获取rpm程序 &#xff1a;启用缓存&#xff0c;并修改yum下载…

在Latex中优雅的插入svg图片(Ubuntu22.04)

文章目录 一、前言二、准备工作三、脚本编程四、结论 一、前言 在 LaTeX \LaTeX LATE​X 中&#xff0c;插入图片常用的为 figure 环境加 \includegraphics 命令&#xff1a; \begin{figure}[!htbp]\centering\includegraphics[width\textwidth]{图片名.jpg/jpeg/png/pdf}\c…

【LeetCode热题100】 226. 翻转二叉树(二叉树)

一.题目要求 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 二.题目难度 简单 三.输入样例 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1] 示例 2&#xff1a; 输入&#xff1a;…

文件处理(二)

CSV文件的读取和写入 CSV文件的操作 csv是逗号分隔符文本格式&#xff0c;常用于数据交换、Excel文件和数据库数据的导入和导出。 与Excel文件不同&#xff0c;CSV文件中&#xff1a; 值没有类型&#xff0c;所有值都是字符串不能指定字体颜色等样式不能指定单元格的宽高&…

【自动驾驶可视化工具】

自动驾驶可视化工具 自动驾驶可视化工具1.百度Apollo的Dreamview:2.Cruise的Worldview:3.Uber的AVS:4.Fglovex Studio: 自动驾驶可视化工具 介绍一下当前主流的自动驾驶可视化工具。 1.百度Apollo的Dreamview: Dreamview是百度Apollo平台开发的一种可视化工具&#xff0c;用…

滑块验证码

1.这里针对滑块验证给了一个封装的组件verifition&#xff0c;使用直接可以调用 2.组件目录 3.每个文件的内容 3.1 Api文件中只有一个index.js文件&#xff0c;用来存放获取滑块和校验滑块结果的api import request from /router/axios//获取验证图片 export function reqGe…

centos7.9的GUI桌面样式不符合默认熟悉的操作习惯

一、问题描述&#xff1a; 原因&#xff1a;桌面样式选错了。 二、解决&#xff1a; 1.先登进去LogOut。 2.点击设置的工具图标中的GNOME Classic即可恢复成默认操作习惯的桌面样式。 3.恢复到默认熟悉的操作界面

(一)Neo4j下载安装以及初次使用

&#xff08;一&#xff09;下载 官网地址&#xff1a;Neo4j Graph Database & AnamConnect data as its stored with Neo4j. Perform powerful, complex queries at scale and speed with our graph data platform.https://neo4j.com/ &#xff08;二&#xff09;安装并配…

系统明天上线,PG表空间还不规划好疯狂给同事埋雷

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…