功能实现:文件后台管理模块的上传、显示功能
========================= 文件上传 ====================================
一、文件上传
1、前端页面
让gpt去给我们生成即可,可以直接复用现成的
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>文件上传页面</title> <style> body { font-family: Arial, sans-serif; background-color: #f2f2f2; padding: 20px; } h1 { text-align: center; margin-top: 50px; } form { background-color: #fff; border-radius: 10px; padding: 20px; margin-top: 30px; max-width: 600px; margin: 0 auto; } input[type="file"] { margin-top: 20px; margin-bottom: 20px; } button { background-color: #4CAF50; color: #fff; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; } button:hover { background-color: #3e8e41; } </style> </head> <body> <h1>文件上传</h1> <form action="upload.php" method="POST" enctype="multipart/form-data"> <label for="file">选择文件:</label> <br> <input type="file" id="file" name="f"> <br> <button type="submit">上传文件</button> </form> </body> </html>
2、文件上传后端部分
1)先利用全局变量file去提取接收到的文件的各类信息
<?php // 从前端表单提取出来的信息,利用全局变量进行提出 $name=$_FILES['f']['name']; $type=$_FILES['f']['type']; $size=$_FILES['f']['size']; $tmp_name=$_FILES['f']['tmp_name']; $error=$_FILES['f']['error'];
2)进行文件上传到服务器的逻辑实现
利用的是move_uploaded_file(),上传到服务器上,我这里是本地开发,所以说本机模拟的是服务器,给的路径是在项目demo1下的upload文件夹
打印一下信息对照是否上传文件是对应的。
<?php // 从前端表单提取出来的信息,利用全局变量进行提出 $name=$_FILES['f']['name']; $type=$_FILES['f']['type']; $size=$_FILES['f']['size']; $tmp_name=$_FILES['f']['tmp_name']; $error=$_FILES['f']['error']; # 测试是否正确提取图片信息 echo $name."<br>"; echo $type."<br>"; echo $size."<br>"; echo $error."<br>"; # 测试文件是否成功上传到服务器的指定文件夹内 注意:需要提前创建好文件夹; if(move_uploaded_file($tmp_name,'upload/'.$name)){ // 按照我的本地环境,我的服务器地址就是我的php项目地址 echo "文件已成功上传"; // 所以我需要在/demo1下面创建一个文件夹 /demo1/upload } ?>
但是这样非常不安全,因为用户可以上传任意的文件类型,所以我们需要加入筛选逻辑(黑白名单)
3、三种文件上传类型验证机制
1)**黑名单**逻辑实现
如果不对上传的文件类型进行限制,那么可能会有木马文件被上传,攻击者可以进入服务器后门。
逻辑:将禁止的后缀类型写入数组,然后我分割服务器接收到的文件名,只取后缀名,用一个变量去接收他,再将其与数组中的黑名单后缀进行比较,如果在黑名单内,则提示禁止上传。
$black_ext=array('php','asp','jsp','aspx'); //xxx.jpg xxx.png $fenge = explode('.',$name); $exts = end($fenge); if(in_array($exts,$black_ext)){ echo '非法后缀文件'.$exts; }else{ move_uploaded_file($tmp_name,'upload/'.$name); echo '<script>alert("上传成功")</script>'; }
测试一下,成功拦截黑名单内的后缀文件上传到服务器。
但是随之而来的是,文件类型太多种了,而且同种文件类型有不同的名字例如html2、html4等等。所以更加安全的是写一个白名单,我们允许哪些类型的通过,不符合条件的一律拒之门外。
2)**白名单**逻辑实现
先进行文件名的切割,给一个新变量去接收,然后拿新变量去我们的白名单数组进行对比,若在允许后缀内,则进行上传服务器的操作;如果不在范围内,则提示非法,不做上传的操作
$allow_ext=array('png','jpg','gif','jpeg'); // xxx.jpg xxx.png $fenge = explode('.',$name); $exts = end($fenge); if(in_array($exts,$allow_ext)) { //第一个参数是要进行判断的变量;第二个参数是判断的依据 move_uploaded_file($tmp_name, 'uoload/' . $name); echo '<script>alert("上传成功!")</script>'; }else{ echo '非法后缀文件'; }
测试:提交一个exe文件
3)**MIME文件类型**逻辑实现
mime在哪里作用?
我们就给一个mime类型:image/gif
, image/png
, image/jpeg 这三种吧
注意我们这里的逻辑是提取上传文件的文件类型,那么可以通过全局变量file去抓取type。
$allow_ext=array('image/png','image/gif','image/jpeg'); // 前面有利用全局变量file去提取文件类型 if(in_array($type,$allow_ext)) { //第一个参数是要进行判断的变量;第二个参数是判断的依据 move_uploaded_file($tmp_name, 'upload/' . $name); echo '<script>alert("上传成功!")</script>'; }else{ echo '非法后缀文件.'.$type; //给一个上传的文件类型 }
========================= 文件显示 ====================================
二、文件显示
1、逻辑实现
00x1、先给一个初始目录进行访问 ----利用get方法去提取url里的,没有就当前目录
00x2、给这个目录一个操作许可 ----- opendir( )实现
00x3、打开这个目录 ----opendir( )实现
00x4、区分文件夹和文件 ---- is_dir()实现
--- 若为文件,则打印文件:文件名
--- 若为文件名,则利用超链接进行路径拼接跳转(将path=此文件夹路径拼接到原url中,实现对文件夹下级路径的访问)
2、代码实现
<?php // 如果初始url没有path参数,则路径取当前文件夹下 $dir =$_GET['path'] ?? './'; # 1.实现打开指定目录,并显示其文件/文件夹名 ---利用readdir()函数 function show_file($dir){ $d = opendir($dir); // 相当于给d一个可以对目录操作的许可 while(($file = readdir($d)) !== false){ //file变量接收的是目录(有d操作许可,且是dir指向的路径目录); echo $file."<br>"; // 同时注意逻辑运算符的优先级,!==要大于= 所以要加括号给$fil # 2.继续进行文件夹和文件的判断 ---利用is_dir()函数 if(is_dir($file)){ # 3.实现点击文件夹继续进入目录的效果 // 原理:利用超链接在url后面增加$file接收到的文件夹,从而实现了url/path=$file的效果,从而可以查看$file接收到的文件夹下面的文件/子目录 echo "文件夹:"."<a href='?path=$file'>$file</a><br>"; }else{ echo "文件:" . $file . "<br>"; } } } show_file($dir);
测试
一一对应 成功!
3、payload方向(文件包含)
涉及到文件包含漏洞,与php.ini中的一个参数有关 【open_basedir】
注意:搞清楚是小皮内置的php.ini 还是自己配置的php环境的ini文件
我这里是关闭,不生效,那么看一下效果
给path参数里面写我任意一个文件夹都可以被访问到。
如果我进行了设置,给他限制在我demo1的上层目录xiaodikaifa中
刷新一下,看效果
总结:如果是没有对php.ini做目录限制的话,就可以利用遍历文件路径,进行被攻击者/服务器文件的泄露。