网络安全--PHP第三天

今天学习文件上传的相关知识

上传的前端页面如下

upload.html

复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>简单文件上传</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 0 auto;
            padding: 20px;
        }
        .upload-container {
            border: 2px dashed #ccc;
            padding: 20px;
            text-align: center;
            border-radius: 5px;
        }
        .upload-btn {
            background-color: #4CAF50;
            color: white;
            padding: 10px 20px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            margin-top: 15px;
        }
        .upload-btn:hover {
            background-color: #45a049;
        }
        .note {
            font-size: 14px;
            color: #666;
            margin-top: 10px;
        }
    </style>
</head>
<body>
<h1>文件上传</h1>
<form action="upload.php" method="post" enctype="multipart/form-data">
    <div class="upload-container">
        <h3>选择要上传的文件</h3>
        <input type="file" name="file" id="file" required>
        <p class="note">注意:实际文件上传需要服务器端处理脚本</p>
        <button type="submit" class="upload-btn">上传文件</button>
    </div>
</form>
</body>
</html>

配套的php文件如下:

upload.php

复制代码
<?php

$name = $_FILES['file']['name'];
$type = $_FILES['file']['type'];
$size = $_FILES['file']['size'];
$temp_name = $_FILES['file']['tmp_name'];
echo $type;

$error = $_FILES['file']['error'];

$black_ext = array('jpg', 'jpeg', 'gif', 'png');//添加非法文件类型
$fenge =  explode(".", $name);//通过.分割文件形成数组
$exts = end($fenge);//拿到数组最后面的数据

//黑名单过滤
//if (in_array($exts, $black_ext)) {//对后缀进行验证
//    echo "非法文件'.$exts'";//失败
//}else{
//    move_uploaded_file($temp_name, './'.$name);//保存在根目录下
//    echo '<script>alert("上传成功");</script>';
//}

//白名单过滤
//$allow_type = array('image/jpeg','video/mp4','image/png','image/gif');
//if(!in_array($type,$allow_type)){
//    echo '非法后缀';
//}else{
//    move_uploaded_file($temp_name,'.'.$name);
//    echo '<script>alert</script>';
//}


?>

两个过滤模式

黑名单过滤

白名单过滤

html调用后可以上传文件

如果遇到上传漏洞 可以使用一下的简单代码拿到数据 例子如下

复制代码
<?php

$dir = $_GET['dir'] ?? './';

function show_file($dir) {
    $d = opendir($dir);
    while(($file=readdir($d))!==false){
        if(is_dir($file)){
            echo '文件夹:'.$file."<br>";
        }else{
            echo '文件:'.$file."<br>";
        }
    }
}

show_file($dir);

上传文件成功和 访问即可 这里修改了dir里面的参数

成功拿到目录信息

优化拿到目录(文件)后的操作

并且添加了删除 下载 修改功能

复制代码
<?php
// 获取操作类型(删除、下载、编辑)
$action = isset($_GET['a']) ? $_GET['a'] : '';
// 获取路径参数,默认当前目录
$path   = isset($_GET['path']) ? $_GET['path'] : './';

// 路径处理:去除两端斜杠/反斜杠
$path = rtrim($path, '/\\');

//判断是文件还是目录
if (is_file($path)) {
    $current_dir = dirname($path) . '/';  // 文件所在目录
    $file = basename($path);             // 文件名
} else {
    $current_dir = $path . '/';          // 目录路径

    // 检查目录是否存在
    if (!is_dir($current_dir)) {
        die('sorry, the directory does not exist: ' . $current_dir);
    }
}

//拿到路径信息
function getlist($path) {
    $hd = opendir($path);  // 打开目录句柄
    $list = ['dir' => [], 'file' => []];  // 初始化分类数组

    // 遍历目录内容
    while(($file_name = readdir($hd)) !== false) {
        // 跳过当前目录(.)和上级目录(..)
        if($file_name != "." && $file_name != "..") {
            $file_path = $path . $file_name;  // 完整文件路径

            // 跳过不存在的文件
            if(!file_exists($file_path)) continue;

            $file_type = filetype($file_path);  // 获取文件类型

            // 按类型分类存储文件信息
            $list[$file_type][] = array(
                'file_name' => $file_name,               // 文件名
                'file_path' => $file_path,               // 完整路径
                'file_size' => is_file($file_path) ? round(filesize($file_path)/1024) : '-',  // 文件大小(KB)
                'file_time' => date('Y/m/d', filemtime($file_path)),  // 修改日期
            );
        }
    }

    closedir($hd);  // 关闭目录句柄
    return $list;
}

// 获取当前目录内容列表
$list = getlist($current_dir);

//执行对应操作
switch($action) {
    // 删除文件操作
    case 'del':
        if(isset($_GET['path'])) {
            $fileToDelete = $_GET['path'];

            // 验证文件存在且是普通文件
            if(file_exists($fileToDelete) && is_file($fileToDelete)) {
                // 执行删除
                if(unlink($fileToDelete)) {
                    // 删除成功后返回父目录
                    header("Location: ?path=" . dirname($fileToDelete));
                    exit;
                } else {
                    die('删除文件失败,可能是权限不足');
                }
            } else {
                die('文件不存在或不是普通文件');
            }
        } else {
            die('未指定要删除的文件路径');
        }
        break;

    // 文件下载操作
    case 'down':
        if (isset($_GET['path'])) {
            $file = $_GET['path'];

            // 验证文件存在且是普通文件
            if (file_exists($file) && is_file($file)) {
                // 设置下载头信息
                header('Content-Type: application/octet-stream');  // 二进制流
                header('Content-Disposition: attachment; filename="' . basename($file) . '"');  // 下载文件名
                header('Content-Length: ' . filesize($file));     // 文件大小

                readfile($file);  // 输出文件内容
                exit;
            }
        }
        break;

    // 文件编辑操作
    case 'edit':
        if (isset($_GET['path'])) {
            $file = $_GET['path'];

            // 处理保存操作(POST请求)
            if ($_SERVER['REQUEST_METHOD'] === 'POST') {
                $content = $_POST['content'] ?? '';  // 获取编辑内容

                // 写入文件
                if (file_put_contents($file, $content) !== false) {
                    // 保存成功返回目录
                    header("Location: ?path=" . dirname($file));
                    exit;
                } else {
                    die('保存文件失败,可能是权限不足');
                }
            }

            // 显示编辑界面
            if (file_exists($file) && is_file($file) && is_readable($file)) {
                $content = htmlspecialchars(file_get_contents($file));  // 读取内容并转义
                $filename = basename($file);  // 获取纯文件名

                // 输出编辑界面HTML
                echo <<<HTML
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>编辑文件 - {$filename}</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        h1 { margin-bottom: 20px; }
        textarea { width: 100%; height: 400px; font-family: monospace; }
        .actions { margin-top: 10px; }
    </style>
</head>
<body>
    <h1>编辑文件: {$filename}</h1>
    <form method="post">
        <textarea name="content">{$content}</textarea>
        <div class="actions">
            <button type="submit">保存</button>
            <a href="?path=" . dirname($file) . "">取消</a>
        </div>
    </form>
</body>
</html>
HTML;
                exit;
            } else {
                die('文件不可编辑或不存在');
            }
        }
        break;

    // 默认情况:显示目录内容
    default:
        break;
}
?>

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>设备类型图例</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        h1 {
            text-align: center;
            margin-bottom: 20px;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f2f2f2;
            text-align: center;
        }
        img {
            vertical-align: middle;
        }
    </style>
</head>
<body>
<h1>图例</h1>
<table>
    <thead>
    <tr>
        <th>图形</th>
        <th>名称</th>
        <th>日期</th>
        <th>大小</th>
        <th>路径</th>
        <th>操作</th>
    </tr>
    </thead>
    <tbody>
    <?php foreach ($list['dir'] as $v): ?>
        <tr>
            <td><img src="./img/file.png" width="20" height="20"></td>
            <td><?php echo htmlspecialchars($v['file_name']); ?></td>
            <td><?php echo $v['file_time']; ?></td>
            <td>-</td>
            <td><?php echo htmlspecialchars($v['file_path']); ?></td>
            <td><a href="?path=<?php echo urlencode($v['file_path']); ?>">打开</a></td>
        </tr>
    <?php endforeach; ?>
    <?php foreach ($list['file'] as $v): ?>
        <tr>
            <td></td>
            <td><?php echo htmlspecialchars($v['file_name']); ?></td>
            <td><?php echo $v['file_time']; ?></td>
            <td><?php echo $v['file_size']; ?></td>
            <td><?php echo htmlspecialchars($v['file_path']); ?></td>
            <td>
                <a href="?a=edit&path=<?php echo urlencode($v['file_path']); ?>">编辑</a>
                <a href="?a=down&path=<?php echo urlencode($v['file_path']); ?>">下载</a>
                <a href="?a=del&path=<?php echo urlencode($v['file_path']); ?>" οnclick="return confirm('确定删除吗?')">删除</a>
            </td>
        </tr>
    <?php endforeach; ?>
    </tbody>
</table>
</body>
</html>

功能就不一一展示了

功能都可以实现 但是全是安全问题

通过代码 知道了大致的文件上传的过程于一些基本的安全问题

相关推荐
冰雪青松11 分钟前
智能手机上用Termux安装php+Nginx
nginx·php
.似水24 分钟前
Python PyMySQL
开发语言·python
不会飞的鲨鱼40 分钟前
【QQ音乐】sign签名| data参数 | AES-GCM加密 | webpack(上)
开发语言·javascript·webpack
余辉zmh1 小时前
【Linux网络篇】:初步理解应用层协议以及何为序列化和反序列化
linux·网络·php
vvilkim1 小时前
深入理解C#中的LINQ:数据查询的终极利器
开发语言·c#·linq
Jim-zf1 小时前
Flutter 实现6个验收码输入框
开发语言·javascript·flutter
橙子199110161 小时前
Kotlin 中的数据类型有隐式转换吗?为什么?
android·开发语言·kotlin
黄小耶@2 小时前
深度解析 Dockerfile 配置:构建高效轻量的FastAPI 应用镜像
开发语言·python
唐装鼠2 小时前
C++ 模板参数包展开方式
开发语言·c++