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

news2024/12/24 9:54:41

前言

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">
    // 实例化 UEditor
    var ue = UE.getEditor('editor');
</script>
</body>
</html>

运行效果:

进行文件上传的测试


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

总结

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

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

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

相关文章

山西电力市场日前价格预测【2023-11-12】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-12&#xff09;山西电力市场全天平均日前电价为224.59元/MWh。其中&#xff0c;最高日前电价为434.30元/MWh&#xff0c;预计出现在18:00。最低日前电价为0.00元/MWh&#xff0c;预计出…

【代码随想录】算法训练计划17

1、 110.平衡二叉树 题目&#xff1a; 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 思路&#xff1a; 经典后序遍历&#xff0c;感…

Ansible自动化运维工具及模块

目录 一、Ansible 1.ansible简介 2、ansible的特性 二、ansible的部署 1&#xff09;管理端安装ansible 2&#xff09;配置主机清单 3&#xff09;配置密钥对验证 三、ansible命令块模块 1&#xff09;command模块 2&#xff09;shell模块 3&#xff09;cron模块 4)…

软件测试之Web自动化测试,Web自动化测试的详细流程和步骤

一、什么是web自动化测试 自动化&#xff08;Automation&#xff09;是指机器设备、系统或过程&#xff08;生产、管理过程&#xff09;在没有人或较少人的直接参与下&#xff0c;按照人的要求&#xff0c;经过自动检测、信息处理、分析判断、操纵控制&#xff0c;实现预期的目…

无缝集成GORM与Go Web框架

探索GORM与流行的Go Web框架之间的和谐集成&#xff0c;以实现高效的数据管理 高效的数据管理是每个成功的Web应用程序的基础。GORM&#xff0c;多才多艺的Go对象关系映射库&#xff0c;与流行的Go Web框架非常搭配&#xff0c;提供了无缝集成&#xff0c;简化了数据交互。本指…

C++使用线程池模拟异步事件处理机制

在C很多框架中都有异步事件处理机制&#xff0c;这导致我们在看源码时经常很疑惑&#xff0c;难以理解&#xff0c;而其中包含的编程套路可能是一些成熟的技术&#xff0c;只是我们不熟悉&#xff0c;比如WebRTC中类似于Qt的信号槽机制&#xff0c;线程事件处理, 或者使用系统异…

玩转Linux基本指令

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;牢记Linux的基本指令。 > 毒鸡汤&#xff1a;挫…

2023 年最好的 Android 系统修复/刷机应用程序和软件

任何 Android 设备要顺利运行&#xff0c;其操作系统必须运行良好。幸运的是&#xff0c;对于大多数 Android 用户来说&#xff0c;这是不间断的。设备运行良好&#xff0c;打电话、共享文档等都没有问题。尽管如此&#xff0c;Android 操作系统可能会停止运行。这可能是由于特…

Postman for Mac(HTTP请求发送调试工具)v10.18.10官方版

Postman for mac是一个提供在MAC设备上功能强大的开发&#xff0c;监控和测试API的绝佳工具。非常适合开发人员去使用。此版本通过Interceptor添加了对请求捕获的支持&#xff0c;修正了使用上下文菜单操作未复制响应正文的问题和预请求脚本的垂直滚动条与自动完成下拉列表重叠…

ios开发 之 多线程

目录 第一节&#xff1a;多线程简介 线程执行原理 主线程 多线程解决方案 pthread __bridge NSThread 线程的状态 第二节&#xff1a;多线程访问资源 Synchronized nonatomic 、atomic 自动释放池 属性修饰符 第三节&#xff1a;消息循环 消息模式 第四节&…

人工智能基础_机器学习022_使用正则化_曼哈顿距离_欧氏距离_提高模型鲁棒性_过拟合_欠拟合_正则化提高模型泛化能力---人工智能工作笔记0062

然后我们再来看一下,过拟合和欠拟合,现在,实际上欠拟合,出现的情况已经不多了,欠拟合是 在训练集和测试集的准确率不高,学习不到位的情况. 然后现在一般碰到的是过拟合,可以看到第二个就是,完全就把红点蓝点分开了,这种情况是不好的, 因为分开是对训练数据进行分开的,如果来…

三掌柜第2期赠书活动:《计算机考研精炼1000题》

引言 各位朋友大家好&#xff0c;我是三掌柜。今天&#xff0c;三掌柜赠书第2期启动&#xff0c;本次为大家精选了《计算机考研精炼1000题》这本书。关于这本书的内容&#xff0c;非常丰富&#xff0c;涵盖计算机考研的高频知识内容&#xff0c;不管是正在备考&#xff0c;还是…

JUC下常见类

JUC(java.util.concurrent) 的常见类ReentrantLock原子类线程池信号量SemaphoreCountDownLatch JUC(java.util.concurrent) 的常见类 ReentrantLock ReentrantLock可重入互斥锁. 和 synchronized 定位类似, 都是用来实现互斥效果, 保证线程安全。 用法: lock(): 加锁, 如果获…

合同审查---财务条款、合同形式与生效审查

1.合同主体 1人 廖 2.财务条款、合同形式与生效 1人 黄 3.履行、验收、知识产权、不可抗力 1人 詹 4.违约责任、争议解决、保密、法律引用 1人 王 代码规范&#xff1a; 1.代码函数的层级 各审查点在json中分为3级层级&#xff0c;但用python写规则的时候&#xff0c;1级层级为…

【C++那些事儿】类与对象(2)

君兮_的个人主页 即使走的再远&#xff0c;也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;我之前看过一套书叫做《明朝那些事儿》&#xff0c;把本来枯燥的历史讲的生动有趣。而C作为一门接近底层的语言&#xff0c;无疑是抽象且难度颇…

LeetCode 面试题 16.20. T9键盘

文章目录 一、题目二、C# 题解 一、题目 在老式手机上&#xff0c;用户通过数字键盘输入&#xff0c;手机将提供与这些数字相匹配的单词列表。每个数字映射到0至4个字母。给定一个数字序列&#xff0c;实现一个算法来返回匹配单词的列表。你会得到一张含有有效单词的列表。映射…

图书销售数据大屏可视化【可视化项目案例-03】

🎉🎊🎉 你的技术旅程将在这里启航! 🚀🚀 本文选自专栏:可视化技术专栏100例 可视化技术专栏100例,包括但不限于大屏可视化、图表可视化等等。订阅专栏用户在文章底部可下载对应案例源码以供大家深入的学习研究。 🎓 每一个案例都会提供完整代码和详细的讲解,不…

Leetcode-144 二叉树的前序遍历

递归方法 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* …

谈谈如何写作(一)

序言 没有什么比一套好理论更有用了。——库尔特勒温 谈谈如何写作&#xff1f; 这个题目就像一本书《如何阅读一本书》&#xff0c;听起来似乎很无趣&#xff0c;因为各位盆友直接的反应&#xff0c;可能是这根本无需理论。 实际情况呢&#xff1f;恰恰相反&#xff0c;往往你…

javax.management.InstanceNotFoundException: Catalina:type=Server错误的解决

软件&#xff1a; JDK 1.8 Tomcat 8.5.66 IDEA 2019.3.3 问题&#xff1a;启动IDEA新建一Web Application项目&#xff0c;设置好项目运行&#xff0c;结果发现提示&#xff1a; 提示&#xff1a;Application Server was not connected before run configuration stop, rea…