目录
文件管理模块-上传-过滤机制
文件管理模块-显示-过滤机制
思维导图
PHP知识点
功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框架开发等
技术:输入输出,超全局变量,数据库操作,逻辑架构,包含上传&下载删除;
技术:JS&CSS混用,Cookie,Session操作,MVC架构,ThinkPHP引用等。
文件管理模块-上传-过滤机制
PHP文件上传
$_FILES:PHP中一个预定义的超全局变量,用于在上传文件时从客户端接收文件,并将其保存到服务器上。它是一个包含上传文件信息的数组,包括文件名、类型、大小、临时文件名等信息。
$_FILES["表单值"]["name"] 获取上传文件原始名称
$_FILES["表单值"]["type"] 获取上传文件MIME类型
$_FILES["表单值"]["size"] 获取上传文件字节单位大小
$_FILES["表单值"]["tmp_name"] 获取上传的临时副本文件名
$_FILES["表单值"]["error"] 获取上传时发生的错误代码
move_uploaded_file() 将上传的文件移动到指定位置的函数
过滤的类型:
1、无过滤机制
2、黑名单过滤机制
3、白名单过滤机制
4、文件类型过滤机制
AI生成前端代码
<!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>
无过滤机制
upload.php代码如下:
<?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 $tmp_name."<br>"; echo $error."<br>"; if(move_uploaded_file($tmp_name,'upload/'.$name)){ // 转移到网站目录/upload/echo "文件上传成功!"; } ?>
../www/demo3/upload/xxx.png
黑名单过滤机制
upload.php代码如下:
<?php$name=$_FILES['f']['name']; // 文件原名 $type=$_FILES['f']['type']; // 文件类型 $size=$_FILES['f']['size']; // 文件大小 $tmp_name=$_FILES['f']['tmp_name']; // 上传临时目录 $error=$_FILES['f']['error']; // 成功/失败// 上传文件后缀过滤 黑名单机制 $black_ext=array('php','asp','jsp','aspx'); //xxx.jpg xxx.png // explode('.', $name) 使用点号作为分隔符,将 $name 字符串拆分成一个数组。 // 拆分后的结果存储在变量 $fenge 中,每个元素代表一个分隔后的部分。 $fenge = explode('.',$name); // end($fenge) 返回数组 $fenge 的最后一个元素,即最后一部分的文件扩展名。 // 将最后一个元素赋给变量 $exts,即获取到文件的扩展名。 $exts = end($fenge); if(in_array($exts,$black_ext)){echo '非法后缀文件'.$exts; }else{move_uploaded_file($tmp_name,'upload/'.$name);echo '<script>alert("上传成功")</script>'; }?>
根据环境不同有不同的绕过,如这里可尝试上传 php5
缺陷:若未考虑到各种变形后缀,则可能被绕过
白名单过滤机制
upload.php代码如下:
<?php$name=$_FILES['f']['name']; // 文件原名 $type=$_FILES['f']['type']; // 文件类型 $size=$_FILES['f']['size']; // 文件大小 $tmp_name=$_FILES['f']['tmp_name']; // 上传临时目录 $error=$_FILES['f']['error']; // 成功/失败//上传文件后缀过滤 白名单机制 $allow_ext=array('png','jpg','gif','jpeg'); //xxx.jpg xxx.png $fenge = explode('.',$name); $exts = end($fenge); if(!in_array($exts,$allow_ext)){echo '非法后缀文件'.$exts; }else{move_uploaded_file($tmp_name,'upload/'.$name);echo '<script>alert("上传成功")</script>'; }?>
MIME文件类型过滤机制
upload.php代码如下:
<?php$name=$_FILES['f']['name']; // 文件原名 $type=$_FILES['f']['type']; // 文件类型 $size=$_FILES['f']['size']; // 文件大小 $tmp_name=$_FILES['f']['tmp_name']; // 上传临时目录 $error=$_FILES['f']['error']; // 成功/失败//MIME文件类型过滤 $allow_type=array('image/png','image/jpg','image/jpeg','image/gif'); if(!in_array($type,$allow_type)){echo '非法后缀文件'; }else{move_uploaded_file($tmp_name,'upload/'.$name);echo '<script>alert("上传成功")</script>';} ?>
Content-Type: application/octet-stream 改为 Content-Type: image/png
文件管理模块-显示-过滤机制
功能:显示 上传 下载 删除 编辑 包含等
1.打开目录读取文件列表
2.递归循环读取文件列表
3.判断是文件还是文件夹
4.PHP.INI目录访问控制is_dir() 函数用于检查指定的路径是否是一个目录
opendir() 函数用于打开指定的目录,返回句柄,用来读取目录中的文件和子目录
readdir() 函数用于从打开的目录句柄中读取目录中的文件和子目录
open_basedir:PHP.INI中的设置用来控制脚本程序访问目录
示例代码如下:
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>文件列表</title><link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"><style type="text/css">ul {list-style: none;padding: 0;margin: 0;}li {margin-bottom: 10px;}i {margin-right: 10px;}a {text-decoration: none;color: #333;}</style>
</head>
<body>
<h1>当前目录下的文件列表</h1>
<ul></ul>
</body>
</html><?php
$dir = $_GET['path'] ?? './'; // 读取 GET 提交的参数 path=//1.打开目录,读取文件列表 opendir
//2.循环读取文件列表 while readdir
//3.判断是文件还是文件夹 is_dir//打开目录,读取文件列表 opendir
function filelist($dir){if($dh = opendir($dir)){ // 打开文件夹//循环读取文件列表 while readdirwhile(($file=readdir($dh) )!== false){ // 循环读取每一个文件//判断是文件还是文件夹 is_dirif(is_dir($file)){// PHP 后端先对变量进行替换,在发送前端代码echo "<li><i class='fa fa-folder'></i> <a href='?path=$file'>" . $file . '</a></li>'; // . 拼接起来}else{echo '<li><i class="fa fa-file"></i> <a href="#">' . $file . '</a></li>';}}}
}filelist($dir);// 文件删除
function del($file){if(!is_dir($file)){unlink($file); // unlink($file) 是一个 PHP 内置函数,用于删除指定的文件。echo "<script>alert('删除成功')</script>";}
}if(isset($_GET['del'])){del($_GET['del']);
}// 文件下载
function down($filepath){// basename($filepath) 是一个 PHP 内置函数,用于从文件路径中提取文件名部分。$fileName = basename($filepath);// 设置响应头,指定下载文件的 MIME 类型为 application/octet-stream,表示通用的二进制流。header("Content-Type: application/octet-stream");// 设置响应头,指定下载时的文件名,并将其设置为 $fileName。header("Content-Disposition: attachment; filename=\"" . $fileName . "\"");// 设置响应头,指定下载文件的大小。header("Content-Length: " . filesize($filepath));// 用于将指定文件的内容输出到浏览器,实现文件下载。readfile($filepath);
}if(isset($_GET['down'])){down($_GET['down']);
}
?>
需要限制对文件/文件夹的访问权限
方式一:黑名单过滤
// 将filelist($dir);替换为下面的代码即可 //黑名单过滤 $black_filepath=array('../'); if(in_array($dir,$black_filepath)){echo '<script>alert("禁止跨目录访问!")</script>'; }else{filelist($dir); }
- 禁止了../ 即当 url 中传入?path=../ 时,会弹窗禁止跨目录访问!,但是这里可以输入改为..\, 即可绕过该黑名单。
方式二:PHP.INI目录访问控制
网站根目录设置为D:\phpStudy\PHPTutorial\WWW\blog,无法利用进行目录遍历