网络安全--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>

功能就不一一展示了

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

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

相关推荐
BingoGo13 小时前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack13 小时前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack2 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo2 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack4 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理4 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
feifeigo1234 天前
matlab画图工具
开发语言·matlab
dustcell.4 天前
haproxy七层代理
java·开发语言·前端