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

运行效果:

进行文件上传的测试


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

总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode刷题详解——单词搜索

1. 题目链接&#xff1a;79. 单词搜索 2. 题目描述&#xff1a; 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的…

基于ubuntu 22, jdk 8x64搭建图数据库环境 hugegraph--google镜像chatgpt

基于ubuntu 22, jdk 8x64搭建图数据库环境 hugegraph download 环境 uname -a #Linux whiltez 5.15.0-46-generic #49-Ubuntu SMP Thu Aug 4 18:03:25 UTC 2022 x86_64 x86_64 x86_64 GNU/Linuxwhich javac #/adoptopen-jdk8u332-b09/bin/javac which java #/adoptopen-jdk8u33…

开源软件有漏洞,作者需要负责吗?是的——作者责任与社会共同关注开源

近日&#xff0c;禅道作者在开源中国发布的一篇文章引起了众多同行的围观&#xff0c;原因是该文章分享了一个开源协议在中国面临的 bug&#xff01;开源软件许可协议通常会表明作者不对用户使用该开源软件所造成的任何问题负责。但是这种条款&#xff0c;在中国&#xff0c;是…

Labview的分支判断

和其他的编程语言一样的。都会有switch,case, if ,else; 再combo box中实现 再后台程序中对应的写上逻辑就好了。

Android 解决CameraView叠加2个以上滤镜拍照黑屏的BUG (一)

1. 前言 这段时间&#xff0c;在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。 由于CameraView封装的比较到位&#xff0c;在项目前期&#xff0c;的确为我们节省了不少时间。 但随着项目持续深入&#xff0c;对于CameraView的使用进入深水区&#xff0c;逐…

Linux系统初步了解

Linux系统由4个主要部分组成&#xff1a;内核、Shell、文件系统和应用程序。 本专题主要是围绕这四个来展开的。 POSIX&#xff08;可移植操作系统接口&#xff09;定义了操作系统应该为应用程序提供的标准接口&#xff0c;其意愿是获得源码级别的软件可移植性。所以Linux选择…

elemenui的Upload上传整合成数组对象

1. 普通直接上传 <el-upload action"" :before-upload"doBeforeUpload"><el-button type"success" size"mini">导入</el-button></el-upload> methods:{doBeforeUpload(file) {let reader new FileReader(…

Postman基本页面和请求/响应页签介绍

近期在复习Postman的基础知识&#xff0c;在小破站上跟着百里老师系统复习了一遍&#xff0c;也做了一些笔记&#xff0c;希望可以给大家一点点启发。 一、Postman的界面介绍 Home主页、Workspace工作空间、Collections集合、Environments环境变量、Mock Server虚拟服务器、Mo…

GEE:计算有效像素占比(统计有效像素数量、像素总数)

作者:CSDN @ _养乐多_ 在GEE中进行遥感数据处理的时候,经常会由于去云,导致影像出现空洞,只有部分像素可用,或者在进行特殊处理时,只对有效像素进行处理,但是我们不知道有效像素数量和占比,无法对结果做出准确的分析。这个时候就需要统计有效像素数量占比。 本文记录…

智链引擎CEO李智:游戏化增长中台,让裂变营销快十倍、便宜十倍、好十倍丨数据猿专访...

大数据产业创新服务媒体 ——聚焦数据 改变商业 双十一电商大战一触即发&#xff0c;各个垂类的App也都希望能够借力双十一营销季&#xff0c;实现用户和营收双增长。MarTech在这个风口上&#xff0c;又成为2B赛道关注的焦点。 业内人士指出&#xff0c;MarTech的引入催生营销…

【MySQL基本功系列】第二篇 InnoDB存储引擎的架构设计

通过上一篇文章&#xff0c;我们简要了解了MySQL的运行逻辑&#xff0c;从用户请求到最终将数据写入磁盘的整个过程。当数据写入磁盘时&#xff0c;存储引擎扮演着关键的角色&#xff0c;它负责实际的数据存储和检索。在MySQL中&#xff0c;有多个存储引擎可供选择&#xff0c;…

HCIA-DHCP+DHCP中继

DHCPDHCP中继 实验拓扑配置步骤第一步 配置Eth-Trunk聚合链路&二层VLAN第二步 配置IP地址第三步 配置DHCPDHCP中继 配置验证查看PC1 PC2是否正确的获得了IP地址 实验拓扑 配置步骤 第一步 配置Eth-Trunk聚合链路&二层VLAN SW1 sysname SW1 # undo info-center enabl…

Linux 内核启动流程

目录 链接脚本vmlinux.ldsLinux 内核启动流程分析Linux 内核入口stext__mmap_switched 函数start_kernel 函数rest_init 函数init 进程 看完Linux 内核的顶层Makefile 以后再来看Linux 内核的大致启动流程&#xff0c;Linux 内核的启动流程要比uboot 复杂的多&#xff0c;涉及到…

SparkAi创作系统ChatGPT网站源码+详细搭建部署教程+AI绘画系统+支持GPT4.0+Midjourney绘画

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

VulnHub Nullbyte

一、信息收集 1.nmap扫描 arp-scan -l扫描内网存活主机 ┌──(root&#x1f480;kali)-[~/桌面] └─# nmap -sS -A -p- 192.168.103.201/24 -sS 半扫描 -A 扫描详细信息 -p- 扫描全端口发现开放了80、111、777、50978端口 且发现777端口开放了ssh服务&#xff0c;说明他把…

深度学习之各种配置环境

如何使用python进行深度学习&#xff0c;我们需要配置相应的环境 第一步&#xff1a;先安装python python的官网地址&#xff1a;https://www.python.org/ 点进去&#xff0c;点击 Downloads&#xff0c;然后点击 Windows 等待下载完成&#xff0c;安装步骤请参考下文&#x…

主题模型LDA教程:一致性得分coherence score方法对比(umass、c_v、uci)

文章目录 主题建模潜在迪利克雷分配&#xff08;LDA&#xff09;一致性得分 coherence score1. CV 一致性得分2. UMass 一致性得分3. UCI 一致性得分4. Word2vec 一致性得分5. 选择最佳一致性得分 主题建模 主题建模是一种机器学习和自然语言处理技术&#xff0c;用于确定文档…

Linux程序的地址空间

Linux程序的地址空间 &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容深刻理解了什么程序或者进程的地址…

【性能测试】非GUI模式Jemter压测+TPS性能拐点详细,一篇带你打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 非GUI模式执行Jem…

YOLOv8 Ultralytics:使用Ultralytics框架训练RT-DETR实时目标检测模型

YOLOv8 Ultralytics&#xff1a;使用Ultralytics框架训练RT-DETR实时目标检测模型 前言相关介绍前提条件实验环境安装环境项目地址LinuxWindows 制作自己的数据集训练自己的数据集创建自己数据集的yaml文件football.yaml文件内容 进行训练进行验证进行预测 数据集获取参考文献 …