Day24:安全开发-PHP应用&文件管理模块&显示上传&黑白名单类型过滤&访问控制

本文介绍了PHP文件管理模块中的上传功能,包括无过滤机制、黑名单过滤、白名单过滤以及MIME类型过滤,同时探讨了如何增强安全性,如使用PHP.INI设置目录访问控制。还涉及了文件显示与目录遍历的过滤机制和相应的PHP函数应用。
摘要由CSDN通过智能技术生成

目录

文件管理模块-上传-过滤机制

文件管理模块-显示-过滤机制

思维导图


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 readdir
        while(($file=readdir($dh) )!== false){  // 循环读取每一个文件
            //判断是文件还是文件夹 is_dir
            if(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,无法利用进行目录遍历

思维导图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dao-道法自然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值