网络安全基础之php开发文件上传的实现

前言

php是网络安全学习里必不可少的一环,简单理解php的开发环节能更好的帮助我们去学习php以及其他语言的web漏洞原理

正文

在正常的开发中,文件的功能是必不可少,比如我们在论坛的头像想更改时就涉及到文件的上传等等文件功能。但也会出现漏洞,或者一些bug。这部分是php开发部分的文件上传、删除部分,为啥不写完?感觉有点多。

文件上传代码

在开发中,对于这种功能型的代码一般有两种办法来开发。一种比较复杂,另外一种比较简单。

自己写代码

这种办法是比较复杂、比较费时费力的。甚至在某些情况下是单纯的吃力不讨好。比如你花几个星期开发一个文本编辑器,最后开发出的文本编辑器性能还不怎么样,但是开源社区或者其他地方有符合你最终需求的文本编辑器代码,性能还优秀,这种情况下就真的吃力不讨好了。

PS:在开发时一点要做好技术选型这些,尽量避免重复造轮子
创建一个file_upload.php文件来实现一个简单文件上传功能,先编写一个html页面来方便查看结果,在file_index.php中写入下面的html代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Head</title><link rel="stylesheet" href="index.css">
</head>
<body>
<div class="header"><a href="index.html" class="logo"><h1>wushiyiwuzhong</h1></a><nav class="navbar"><ul><li><a href="#">文件功能导航</a></li><li><a href="#">文件上传</a></li><li><a href="#">文件下载</a></li><li><a href="#">文件删除</a></li><li><a href="#">文件读取</a></li><li><a href="#">文件写入</a></li></ul></nav>
</div>
<div class="content"></div>
</body>
</html>

页面展示效果如下:
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来我们开始实现简单的文件上传功能,在file_upload.php中编写代码,同样,我们先设计前端代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Head</title><link rel="stylesheet" href="index.css">
</head>
<body>
<div class="header"><a href="index.html" class="logo"><h1>wushiyiwuzhong</h1></a><nav class="navbar"><ul><li><a href="file_index.php">文件功能导航</a></li><li><a href="file_upload.php">文件上传</a></li><li><a href="#">文件下载</a></li><li><a href="#">文件删除</a></li><li><a href="#">文件读取</a></li><li><a href="#">文件写入</a></li></ul></nav>
</div>
<div class="content">
<h1>文件上传 功能页面</h1>
<!--  编写form表单上传文件  --><form action="" method="post"><!-- action留空,由当前页面处理  --><input type="file" name="file"><!--  文件上传框  --><input type="submit" name="上传"><!--  提交按钮 --></form>
</div>
</body>
</html>

页面效果如下:

开始php后端部分的编写,现在前端这些代码只负责让用户上传文件,并不负责验证这个是不是病毒等等有害文件、能不能上传、上传后放在那里。像后面这些功能都是有后端决定的。

前置知识

在PHP中,文件上传功能的实现步骤:
(1)在网页中上传表单,单击“上传”按钮后,选择的文件数据将发送到服务器。
(2)用$_FILES获取上传文件有关的各种信息。
(3)用文件上传处理函数对上传文件进行后续处理。

说明:
(1)如果表单中有文件上传域,则定义表单时必须设置enctype=“multipart/form-data”,且必须为POST方式发送。
(2)限制文件大小可在表单中添加一个隐藏域,该隐藏域必须放在文件上传域之前,否则会设置失效。

若文件上传域的name属性值为upfile,则可以使用$_FILES[‘upfile’]访问文件的有关信息。
相关信息:
$_FILES[‘upfile’][‘name’]; //客户端上传文件的原名称,不包含路径
$_FILES[‘upfile’][‘type’]; //上传文件的MIME类型
$_FILES[‘upfile’][‘tmp_name’]; //已上传文件在服务器端保存的临时文件名,包含路径
$_FILES[‘upfile’][‘error’]; //上传文件出现的错误号,为一个整数
F I L E S [ ′ u p f i l e ′ ] [ ′ s i z e ′ ] ; / / 已上传文件的大小,单位为字节说明:若同时上传多个文件,则上传域的 n a m e 属性值应为 u p f i l e [ ] , 此时 _FILES['upfile']['size']; //已上传文件的大小,单位为字节 说明:若同时上传多个文件,则上传域的name属性值应为upfile[],此时 FILES[upfile][size];//已上传文件的大小,单位为字节说明:若同时上传多个文件,则上传域的name属性值应为upfile[],此时_FILES变成三维数组,保存第一个文件名的数组元素是$_FILES[‘upfile’][‘name’][0]。

保存上传文件到指定目录
move_uploaded_file(文件原来的路径和文件名,文件的目的路径和文件名);
功能说明:
(1)将上传的文件移动到网站指定目录内,并为它重命名。
(2)检查并确保由第一个参数指定的文件是合法的上传文件(即通过HTTP POST上传机制所上传),这对于网站安全是至关重要的。

下面是具体的代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Head</title><link rel="stylesheet" href="index.css">
</head>
<body>
<div class="header"><a href="index.html" class="logo"><h1>wushiyiwuzhong</h1></a><nav class="navbar"><ul><li><a href="#">文件功能导航</a></li><li><a href="#">文件上传</a></li><li><a href="#">文件下载</a></li><li><a href="#">文件删除</a></li><li><a href="#">文件读取</a></li><li><a href="#">文件写入</a></li></ul></nav>
</div>
<div class="content">
<h1>文件上传 功能页面</h1>
<!--  编写form表单上传文件  --><form action="" method="post" enctype="multipart/form-data"><!--enctype进行编码传输--><input type="file" name="file"><!--name参数--><input type="submit" name="submit" value="提交"></form>
</div>
</body>
</html><?php//获取上传文件名
@$file_name=$_FILES['file']['name'];
//获取上传文件类型
@$file_type=$_FILES['file']['type'];
//获取上传文件大小
@$file_size=$_FILES['file']['size'];
//获取上传文件临时文件名
@$file_tmpname=$_FILES['file']['tmp_name'];
//获取上传文件是否错误
@$file_error=$_FILES['file']['error'];echo $file_name."<hr>";
echo $file_type."<hr>";
echo $file_size."<hr>";
echo $file_tmpname."<hr>";
echo $file_error."<hr>";

运行查看效果,如果代码正确的话上传一个文件会打印这个被上传的文件的相关信息

我这里上传一张图片做为测试

点击提交上传之后会打印这种图片相关信息

保存用户上传的文件

现在我们实现当用户上传文件后,比如用户上传了自己的头像后我们的服务器要保存用户的数据。这里我们设置当用户上传文件后将文件保存在当前目录下的upload目录里

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Head</title><link rel="stylesheet" href="index.css">
</head>
<body>
<div class="header"><a href="index.html" class="logo"><h1>wushiyiwuzhong</h1></a><nav class="navbar"><ul><li><a href="file_index.php">文件功能导航</a></li><li><a href="file_upload.php">文件上传</a></li><li><a href="#">文件下载</a></li><li><a href="#">文件删除</a></li><li><a href="#">文件读取</a></li><li><a href="#">文件写入</a></li></ul></nav>
</div>
<div class="content">
<h1>文件上传 功能页面</h1>
<!--  编写form表单上传文件  --><form action="upload.php" method="post" enctype="multipart/form-data"><input type="file" name="file"><!-- name是什么,那么后端接受的参数就是什么--><input type="submit" name="submit" value="提交"></form>
</div>
</body>
</html><?php
// 检查是否有文件被上传
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['file'])) {// 指定存放上传文件的目录$uploadDirectory = "upload/";// 获取文件相关信息$fileName = $_FILES['file']['name']; // 文件原名$fileTmpName = $_FILES['file']['tmp_name']; // 文件临时存放的位置$fileError = $_FILES['file']['error']; // 错误码$fileSize = $_FILES['file']['size']; // 文件大小// 检查目录是否存在if (!file_exists($uploadDirectory)) {// 如果不存在则创建目录mkdir($uploadDirectory, 0755, true);}// 检查文件上传过程中是否出错if ($fileError === 0) {// 检查文件是否已经存在if (!file_exists($uploadDirectory . $fileName)) {// 尝试移动文件到指定目录if (move_uploaded_file($fileTmpName, $uploadDirectory . $fileName)) {echo "文件上传成功!";} else {echo "文件上传失败,请检查目录权限。";}} else {echo "文件已存在于目标目录中。";}} else {// 错误处理echo "上传过程中出错,错误码:" . $fileError;}
} else {echo "请通过有效表单提交文件。";
}

代码运行效果如下:

上传文件进行测试,看是不是保存在upload目录下


打开文件夹,确认是不是真的成功了

到这里成功实现了文件上传功能

PS:此时我们就完成了简单的文件上传功能的实现,但是现在的代码是没有任何过滤的,攻击者可以通过上传木马、webshell等等恶意文件来控制我们的服务器。

情景假设:

我是一名黑客,我在目标网站找到了上传漏洞。我现在先上传一个php的webshell到网站上去


现在我们使用蚁剑去连,连接编码为base64,密码为123

PS:当时写代码的时候忘记写回显了。。。。。。不过实战中还是有很多方法可以知道上传路径的

通过第三方组件进行文件上传

在实际的开发中我们可能会节省重复造轮子的时间而去使用其他第三方开发的第三方组件来快速实现我们需要的功能。下面的就是一个第三方组件的例子
(演示使用的第三方组件下载地址)[https://github.com/fex-team/ueditor/releases/tag/v1.4.3.3]

下载后解压到对应的网站目录
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
然后在代码里引入该第三方组件,在html代码里直接加入

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>第三方组件的文件上传</title><link rel="stylesheet" href="index.css"><!-- 集成 UEditor 的 CSS 文件 --><link href="ueditor/themes/default/css/ueditor.min.css" type="text/css" rel="stylesheet"><!-- UEditor 配置文件 --><script type="text/javascript" charset="utf-8" src="ueditor/ueditor.config.js"></script><!-- UEditor 编辑器源码文件 --><script type="text/javascript" charset="utf-8" src="ueditor/ueditor.all.min.js"></script>
</head>
<body>
<a href="index.html" class="logo"><h1>wushiyiwuzhong</h1>
</a>
<nav class="navbar"><ul><li><a href="file_index.php">文件功能导航</a></li><li><a href="file_upload.php">文件上传</a></li><li><a href="#">文件下载</a></li><li><a href="#">文件删除</a></li><li><a href="#">文件读取</a></li><li><a href="#">文件写入</a></li></ul>
</nav>
</div>
<div class="content"><h1>文件上传 功能页面</h1><!-- 编写form表单上传文件 --><form action="upload.php" method="post" enctype="multipart/form-data"><!-- 初始化 UEditor 编辑器的容器 --><script id="editor" name="editor" type="text/plain" style="width:1024px;height:500px;"></script><input type="file" name="file"><!-- 文件上传的input --><input type="submit" name="submit" value="提交"></form>
</div>
<script type="text/javascript">// 实例化 UEditorvar ue = UE.getEditor('editor');
</script>
</body>
</html>

运行效果:

进行文件上传的测试


可以看到第三方组件过滤了简单的恶意文件

总结

到此文件上传漏洞的大致原理和简单利用就结束了,自己开发的代码漏洞出在自己开发的部分,而如果引用第三方组件,那么漏洞点在第三方组件。至于过滤、绕过这些都是后面的事情

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

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

相关文章

基于SpringBoot+Vue的宿舍管理系统

基于SpringBootVue的学生宿舍管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 宿舍公告 登录界面 管理员界面 维修人员 商家界面 学生界面 摘要 摘…

Azure 机器学习:在 Azure 机器学习中使用 Azure OpenAI 模型

目录 一、环境准备二、Azure 机器学习中的 OpenAI 模型是什么&#xff1f;三、在机器学习中访问 Azure OpenAI 模型连接到 Azure OpenAI部署 Azure OpenAI 模型 四、使用自己的训练数据微调 Azure OpenAI 模型使用工作室微调微调设置训练数据自定义微调参数部署微调的模型 使用…

Python---集合中的交集 、并集 | 与差集 - 特性

用 & 来求两个集合的交集&#xff1a;-----键盘上的7上的符号&#xff0c;shift 7 同时按 用 | 来求两个集合的并集&#xff1a; -----键盘上的7上的符号&#xff0c;shift 同时按&#xff08;就是enter键上面那个|\ &#xff09; 用 - 来求两个集合的差集&#xff…

抖斗音_快块手直播间获客助手+采集脚本+引流软件功能介绍

软件功能&#xff1a; 支持同时采集多个直播间&#xff0c;弹幕&#xff0c;关*注&#xff0c;礼*物&#xff0c;进直播间&#xff0c;部分用户手*号,粉*丝团采集 不支持采集匿*名直播间 设备需求&#xff1a; 电脑&#xff08;win10系统&#xff09; 文章分享者&#xff1…

Kerberos认证系统

文章目录 前提知识原理第一次对话第二次对话第三次对话 总结发现 前提知识 KDC&#xff1a;由AS、TGS&#xff0c;还有一个Kerberos Database组成。 Kerberos Database用来存储用户的密码或者其他所有信息&#xff0c;请求的时候需要到数据库中查找。 AS&#xff1a;为客户端提…

Python爬虫抓取微博数据及热度预测

首先我们需要安装 requests 和 BeautifulSoup 库&#xff0c;可以使用以下命令进行安装&#xff1a; pip install requests pip install beautifulsoup4然后&#xff0c;我们需要导入 requests 和 BeautifulSoup 库&#xff1a; import requests from bs4 import BeautifulSou…

No203.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

小H靶场学习笔记:DC-2

DC-2 Created: November 10, 2023 3:01 PM Tags: WordPress, git提权, rbash逃逸 Owner: 只会摸鱼 靶场过程 信息收集 扫描存活主机&#xff0c;找到靶机ip&#xff1a;192.168.199.131&#xff08;本机是192.168.199.129&#xff09; 扫描端口开放协议 发现有80端口和77…

2023nacos源码解读第3集——nacos-client核心功能之微服务调用和配置管理测试

文章目录 1、测试项目2、项目注意事项3、 测试核心功能3.1 测试服务调用与负载均衡3.2 测试配置监听 4、参考文档 1、测试项目 项目地址 nacos-service-a nacos-service-b 2、项目注意事项 项目初始化可以使用aliyun spring initializer ,以更方便的使用springcloud alibaba…

hive里因为列名用了关键字导致建表失败

代码 现象 ParseException line 6:4 cannot recognize input near percent String COMMENT in column name or primary key or foreign key 23/11/13 11:52:57 ERROR org.apache.hadoop.hive.ql.Driver: FAILED: ParseException line 6:4 cannot recognize input near percent …

雷达测角原理、测角精度、测角分辨率以及3DFFT角度估计算法汇总

1.角度测量方法 依据&#xff1a;电磁波的直线传播和雷达天线的方向性。 分类&#xff1a;振幅法测角、相位法测角 1.1 相位法测角 相位法测角利用多个天线所接收回波信号之间的相位差进行测角。如下图所示&#xff1b; 图 1 设在θ方向有一远区目标&#xff0c;则到达接收点…

一个破单机,也要用远程缓存?

大家好&#xff0c;豆小匠终于开始Coding了&#xff0c;这期来聊聊实战相关的杂谈。 正文开始&#xff01; 作为编程萌新的时候&#xff0c;总想着把程序做复杂&#xff0c;堆技术栈。 但是程序是为场景服务的&#xff0c;比如&#xff0c;我想提高接口的响应速度&#xff0c…

Linux应用层点亮硬件的LED灯

一 应用层操作硬件的两种方法 应用层想要对底层硬件进行操控&#xff0c;通常可以通过两种方式&#xff1a; /dev/目录下的设备文件&#xff08;设备节点&#xff09;&#xff1b;/sys/目录下设备的属性文件。 具体使用哪种方式需要根据不同功能类型设备进行选择&#xff0c;通…

vscode设置vue3代码格式化

vscode设置vue3代码格式化 vscode设置vue3代码格式化 下载插件设置格式化时选用的插件实际使用 使用Prettier默认配置使用Prettier添加自定义配置使用Volar 完整配置文件参考链接 下载插件 可以使用Volar或Prettier 设置格式化时选用的插件 mac&#xff1a;【shift】【op…

【C++】类与对象 I

类与对象 I &#xff1a; 前言&#xff1a;&#xff08;C&#xff09;面向过程 和&#xff08;C&#xff09;面向对象 初步认识前言&#xff1a;类的引入一、类的介绍二、类的定义&#xff08;一&#xff09;class 语法&#xff08;二&#xff09;类的两种定义方式&#xff1a;…

【MySql系列】深入解析数据库索引

写在前面 MySQL索引是数据库中一个关键的概念&#xff0c;它可以极大地提高查询性能&#xff0c;加快数据检索速度。但是&#xff0c;要充分发挥索引的作用&#xff0c;需要深入理解它们的工作原理和使用方式。 在本文中&#xff0c;我们将深入解析MySQL索引&#xff0c;探讨它…

JavaWeb——CSS3的使用

目录 1. CSS概述 2. CSS引入方式 3. CSS颜色显示 4. CSS选择器 4.1. 元素&#xff08;标签&#xff09;选择器 4.2. id选择器 4.3. 类选择器 4.4. 三者优先级 5. 盒子模型 1. CSS概述 CSS&#xff0c;全称为“Cascading Style Sheets”&#xff0c;中文译为“层叠样式…

OpenMediaVault控制台web页面密码重置

要重置 OpenMediaVault&#xff08;OMV&#xff09;Web 控制台的密码&#xff0c;可以使用 omv-firstaid 命令行工具中的相应选项。按照以下步骤进行操作&#xff1a; 以管理员权限登录到 OMV 的命令行界面&#xff08;通过 SSH 或直接登录&#xff09;。 ssh登陆到root用户 运…

【数据仓库】数仓分层方法详解与层次调用规范

文章目录 一. 数仓分层的意义1. 清晰数据结构。2. 减少重复开发3. 方便数据血缘追踪4. 把复杂问题简单化5. 屏蔽原始数据的异常6. 数据仓库的可维护性 二. 如何进行数仓分层&#xff1f;1. ODS层2. DW层2.1. DW层分类2.2. DWD层2.3. DWS 3. ADS层 4、层次调用规范 一. 数仓分层…

25.4 MySQL 函数

1. 函数的介绍 1.1 函数简介 在编程中, 函数是一种组织代码的方式, 用于执行特定任务. 它是一段可以被重复使用的代码块, 通常接受一些输入(参数)然后返回一个输出. 函数可以帮助开发者将大型程序分解为更小的, 更易于管理的部分, 提高代码的可读性和可维护性.函数在编程语言…