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

news2025/6/19 14:27:31

目录

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

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

思维导图


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,无法利用进行目录遍历

思维导图

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

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

相关文章

示波器探头的使用

无源探头(Tektronix P2220) 阻抗&#xff1a;1Mhz 衰减&#xff1a;10:1/1:1(与探头上的档位X10/X1相关&#xff0c;如果探头没有档位默认为10:1) 探头型号&#xff1a;电压 高压差分探头&#xff08;Tektronix P5200A) 阻抗&#xff1a;1Mhz 衰减&#xff1a;50:1/500:1(…

深入理解python之self

首先明确的是self只有在类的方法中才会有&#xff0c;独立的函数或方法是不必带有self的。self在定义类的方法时是必须有的&#xff0c;虽然在调用时不必传入相应的参数。 self名称不是必须的&#xff0c;在python中self不是关键词&#xff0c;你可以定义成a或b或其它名字都可…

Qt 定时器事件

文章目录 1 定时器事件1.1 界面布局1.2 关联信号槽1.3 重写timerEvent1.4 实现槽函数 启动定时器 2 定时器类 项目完整的源代码 QT中使用定时器&#xff0c;有两种方式&#xff1a; 定时器类&#xff1a;QTimer定时器事件&#xff1a;QEvent::Timer&#xff0c;对应的子类是QTi…

Vue.js+SpringBoot开发大学计算机课程管理平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 实验课程档案模块2.2 实验资源模块2.3 学生实验模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 实验课程档案表3.2.2 实验资源表3.2.3 学生实验表 四、系统展示五、核心代码5.1 一键生成实验5.2 提交实验5.3 批阅实…

Clock Verification IP

Clock Verification IP IP 参数及接口 IP 例化界面 相关函数 start_clock //产生时钟 <hierarchy_path>.IF.start_clockstop_clock //停止时钟 <hierarchy_path>.IF.stop_clockset_initial_value //设置时钟初始值为 0 <hierarchy_path>IF.set_initia…

Solidity攻击合约:“被偷走的资金”

在以太坊智能合约开发中&#xff0c;Solidity是最常用的编程语言。然而&#xff0c;由于代码编写不当或缺乏安全意识&#xff0c;合约可能面临各种攻击。本文将通过一个简单的Solidity合约示例&#xff0c;展示一个潜在的攻击合约&#xff0c;并分析其相对于原本合约的危害以及…

TS项目实战三:Express实现登录注册功能后端

使用express实现用户登录注册功能&#xff0c;使用ts进行代码开发&#xff0c;使用mysql作为数据库&#xff0c;实现用户登录、登录状态检测、验证码获取接口及用户注册相关接口功能的实现。 源码下载&#xff1a;[点击下载] (https://download.csdn.net/download/m0_37631110/…

设计模式-行为型模式-观察者模式

观察者模式定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时&#xff0c;会通知所有观察者对象&#xff0c;使它们能够自动更新自己。[DP] //首先是Observer接口&#xff0c;定义了观察者需要实现的更新方法&…

【Claude 3】一文谈谈Anthropic(Claude) 亚马逊云科技(Bedrock)的因缘际会

文章目录 前言1. Anthropic的诞生2. Anthropic的“代表作”——Claude 3的“三驾马车”3. 亚马逊云科技介绍4. 强大的全托管服务平台——Amazon Bedrock5. 亚马逊云科技(AWS)和Anthropic的联系6. Claude 3模型与Bedrock托管平台的关系7. Clude 3限时体验入口分享【⚠️截止3月1…

[贰],万能开篇HelloWorld

1&#xff0c;新建项目 File/New/Project Android/Android Application Project 输入程序名字HelloWorld Next Next 选择Blank Activity 修改为HelloWorldActivity 2&#xff0c;异常点 No resource found that matches the given name Theme.AppCompat.Light import andro…

c++中string的使用!!!(适合初学者 浅显易懂)

我们先初步的认识一下string,string底层其实是一个模版类 typedef basic_string<char> string; 我们先大致的把string的成员函数列举出来 class string { private: char * str; size_t size; size_t capacity; }; 1.string的六大默认函数 1.1 构造函数、拷贝构造 注&am…

Hadoop生态选择(一)

一、项目框架 1.1技术选型 技术选型主要考虑因素:维护成本、总成本预算、数据量大小、业务需求、行业内经验、技术成熟度。 数据采集传输:Flume&#xff0c;Kafka&#xff0c;DataX&#xff0c;Maxwell&#xff0c;Sqoop&#xff0c;Logstash数据存储:MySQL&#xff0c;HDFS…

【数据库】多表查询:子查询|关联查询 inner join 、left join、right join

一、外键&#xff1a; 就是把一张表的主键拿到另一张表中作为一个普通的字段 通过外键 可以把两张表连接起来 比如&#xff0c;下面【部门】表里的主键 拿到【员工】表里做普通字段&#xff08;外键&#xff09; 员工 部门 1员工&#xff0c;XXX&#xff0c;1部门 1部门&a…

CraxsRat7.4 安卓手机远程管理软件

CRAXSRAT 7.4 最新视频 https://v.douyin.com/iFjrw2aD/ 官方网站下载 http://craxsrat.cn/ 不要问我是谁&#xff0c;我是活雷锋。 http://craxsrat.cn/ CraxsRat CraxsRat7 CraxsRat7.1 CraxsRat7.2 CraxsRat7.3 CraxsRat7.4

[java基础揉碎]super关键字

super关键字: 基本介绍 super代表父类的引用&#xff0c;用于访问父类的属性、方法、构造器 super给编程带来的便利/细节 1.调用父类的构造器的好处(分工明确&#xff0c;父类属性由父类初始化&#xff0c;子类的属性由子类初始化) 2.当子类中有和父类中的成员(属性和方法)重…

R语言更新版本

目录 一、更新R语言 1、安装最新的R语言版本 2、移动之前安装的packages 3、将Rstudio连接到最新的R语言 二、Rstudio更新 一、更新R语言 1、安装最新的R语言版本 查看当前R语言版本&#xff1a; R.version.string 下载最新的R语言安装包&#xff1a;R: The R Project…

链表|19.删除链表的倒数第N个节点

力扣题目链接 struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {//定义虚拟头节点dummy 并初始化使其指向headstruct ListNode* dummy malloc(sizeof(struct ListNode));dummy->val 0;dummy->next head;//定义 fast slow 双指针struct ListNode* f…

SkyWalking链路追踪上下文TraceContext的traceId生成的实现原理剖析

结论先行 【结论】 SkyWalking通过字节码增强技术实现&#xff0c;结合依赖注入和控制反转思想&#xff0c;以SkyWalking方式将追踪身份traceId编织到链路追踪上下文TraceContext中。 是不是很有趣&#xff0c;很有意思&#xff01;&#xff01;&#xff01; 【收获】 skywal…

CSS的盒子模型:掌握网页设计的基石!

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

C#学习:初识各类应用程序

编写我们第一个程序——Hello,World! 1.编程不是“学”出来的&#xff0c;而是“练”出来的 2.在反复应用中积累&#xff0c;忽然有一天就会顿悟 3.学习原则&#xff1a; 3.1从感官到原理 3.2从使用别人的到创建自己的 3.3必需亲自动手 3.4必需学以致用&#xff0c;紧跟实际…