讲师中心 微信公众号
AI工具推荐 视频效率加速

怎么用Copilot修复PHP文件上传漏洞详细步骤

冬萱同学_8038

冬萱同学_8038

发布时间:2026-10-23 09:41:00

|

123人浏览过

|

来源于php中文网

原创

用copilot修复php上传漏洞,要一起检查上传身份、文件内容、保存位置与访问方式。下面以仅允许png的头像入口为例,给出可运行校验测试和带会话校验的上传处理代码。

GitHub Copilot官方Agent使用文档真实截图

文件上传完成后,记得让Copilot同步校验访问路径

文件上传风险不止存在于表单校验。若用户能指定保存路径、上传目录允许脚本执行,或者下载接口绕过权限,单独限制后缀仍可能留下问题。先整理上传路由、存储目录、下载处理器及服务器配置。

本文只处理已登录用户上传PNG头像的场景,不扩展到压缩包、文档或任意图片格式。生产项目还需要配额、限流和必要的内容处理,这些要求应在任务开始时交代,不能靠补丁自行猜测。

另外最好额外加两层限制:单个账号最多能传多少个文件、累计总大小不能超过多少,而且用户替换新头像的时候,必须明确写好旧头像的删除逻辑,不然时间长了存储目录里会堆大量没人用的冗余文件。

立即学习“PHP免费学习笔记(深入)”;

后缀、MIME和存储隔离分别解决什么

原始文件名与请求中的Content-Type都由客户端提供,不能直接证明文件内容。服务端检测MIME、检查图片结构与尺寸,可以收紧允许输入的范围,但不是病毒扫描或绝对安全证明。

随机命名减少路径操控和覆盖风险,私有目录则避免上传物被当作站点脚本执行。身份校验和CSRF保护还要在读取文件前完成,防止未授权消耗存储资源。

在VS Code里把整套校验任务拆成4步落地执行

  1. 在项目副本中打开Copilot Chat,选择Agent工作方式。把上传控制器、表单和访问文件的代码加入上下文,明确只能审查测试项目,不连接对象存储生产桶。

    btpanel phpsite 宝塔面板PHP网站
    btpanel phpsite 宝塔面板PHP网站

    宝塔面板 PHP 网站管理:站点创建、删除、启停、PHP 版本切换、域名管理、SSL证书管理、伪静态管理、数据库管理

    下载
  2. 要求先输出风险清单,逐项回答身份从哪里取得、支持哪些文件、最终路径谁决定、文件如何下载。缺少服务器配置时,标记待确认,不默认上传目录不可执行。

  3. 确认方案后让Copilot生成小范围补丁。检查保存路径是否只由服务端生成,错误响应是否泄露绝对路径,是否误删原有会话和权限条件。

  4. 先运行校验单元测试,再在测试Web服务发送真实multipart上传。逐条核对正常头像、伪装文本、超限文件和未登录请求;不得把命令行临时文件当成HTTP上传成功证据。

修复当前PHP头像上传入口,只允许登录用户上传PNG。
先检查认证、CSRF、上传错误、真实大小、扩展名、服务端MIME、图片尺寸和最终访问路径。
保存名使用随机值,存储目录必须在Web根目录之外;不要相信原始文件名和客户端MIME。
先给最小修改差异与测试,再列出Nginx/Apache和下载处理器需要人工核验的条件。
不更改生产存储、不开放任意后缀,不把MIME检测描述成病毒扫描。

完整上传处理器实现,附带可直接运行的校验测试代码

下面给出的代码文件,既可以直接在命令行跑单元测试,收到HTTP请求的时候也会自动走上传处理分支。

接入这套逻辑之前,要确保站点本身的登录流程已经正常把用户身份写入会话、能生成随机CSRF令牌,前端上传表单用avatar做文件字段名、csrf做令牌字段名,后台由管理员提前配置好站点根目录外的私有存储路径。

<?php
declare(strict_types=1);
const MAX_BYTES = 2 * 1024 * 1024;
function inspectPng(string $name, string $bytes): string {
    if (strlen($bytes) < 1 || strlen($bytes) > MAX_BYTES ||
        strtolower(pathinfo($name, PATHINFO_EXTENSION)) !== 'png') {
        throw new InvalidArgumentException('Invalid size or extension');
    }
    $mime = (new finfo(FILEINFO_MIME_TYPE))->buffer($bytes);
    $image = @getimagesizefromstring($bytes);
    if ($mime !== 'image/png' || $image === false || $image[2] !== IMAGETYPE_PNG ||
        $image[0] > 4096 || $image[1] > 4096) {
        throw new InvalidArgumentException('Invalid PNG');
    }
    // 原始文件名不参与保存路径;返回随机服务端名称。
    return bin2hex(random_bytes(16)) . '.png';
}
if (!in_array(PHP_SAPI, ['cli', 'phpdbg', 'wasm'], true)) {
    // 接入项目时,user_id必须由登录流程写入服务端会话。
    session_start();
    header('Content-Type: application/json; charset=UTF-8');
    try {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_SESSION['user_id']) ||
            !is_int($_SESSION['user_id']) || $_SESSION['user_id'] < 1 ||
            !is_string($_SESSION['csrf'] ?? null) || strlen($_SESSION['csrf']) !== 64 ||
            !is_string($_POST['csrf'] ?? null) ||
            !hash_equals($_SESSION['csrf'], $_POST['csrf'])) {
            http_response_code(403); throw new RuntimeException('Forbidden');
        }
        $file = $_FILES['avatar'] ?? null;
        if (!is_array($file) || ($file['error'] ?? null) !== UPLOAD_ERR_OK ||
            !is_string($file['tmp_name'] ?? null) || !is_string($file['name'] ?? null) ||
            !is_uploaded_file($file['tmp_name'])) { throw new RuntimeException('Upload failed'); }
        $bytes = file_get_contents($file['tmp_name'], false, null, 0, MAX_BYTES + 1);
        if ($bytes === false) { throw new RuntimeException('Read failed'); }
        $name = inspectPng($file['name'], $bytes);
        // 管理员预建私有目录,并确保不在Web文档根目录下。
        $configured = getenv('UPLOAD_PRIVATE_DIR');
        $dir = is_string($configured) && $configured !== '' ? realpath($configured) : false;
        $documentRoot = $_SERVER['DOCUMENT_ROOT'] ?? '';
        $root = is_string($documentRoot) && $documentRoot !== '' ? realpath($documentRoot) : false;
        if ($dir === false || $root === false || $dir === $root ||
            str_starts_with($dir, rtrim($root, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR) ||
            !is_dir($dir) || !is_writable($dir)) { throw new RuntimeException('Storage unavailable'); }
        if (!move_uploaded_file($file['tmp_name'], $dir . DIRECTORY_SEPARATOR . $name)) {
            throw new RuntimeException('Move failed');
        }
        echo json_encode(['id' => $name], JSON_THROW_ON_ERROR);
    } catch (Throwable $e) {
        if (http_response_code() < 400) { http_response_code(400); }
        echo '{"error":"Upload rejected"}'; // 不向用户泄露绝对路径。
    }
    exit;
}
// CLI教学夹具,不伪造HTTP上传成功。
$png = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+jp1sAAAAASUVORK5CYII=', true);
if ($png === false) { throw new RuntimeException('Fixture error'); }
$name = inspectPng('avatar.png', $png);
echo 'valid_png: PASS', PHP_EOL;
foreach (['fake_png'=>['a.png','not an image'], 'wrong_extension'=>['a.php',$png],
    'oversize'=>['a.png',str_repeat('A',MAX_BYTES+1)]] as $case => [$filename,$data]) {
    try { inspectPng($filename, $data); }
    catch (InvalidArgumentException $e) { echo $case, ': PASS rejected', PHP_EOL; continue; }
    throw new RuntimeException('FAIL: ' . $case);
}
if (!preg_match('/^[a-f0-9]{32}\.png$/D', $name)) { throw new RuntimeException('FAIL: name'); }
echo 'random_name: PASS', PHP_EOL;
echo 'Runtime: PHP ', PHP_VERSION, ' / ', PHP_SAPI, PHP_EOL;
php audit.php

本次实际环境是macOS上的PHP 8.5.10 WebAssembly,已执行内容与命名测试。会话、真实上传来源校验、文件移动和目录权限尚未在Web服务器联调;下图不代表已经完成生产上传验收。

PNG上传校验函数的五条真实测试结果

头像上传和文档上传别共用同一份宽松的后缀白名单

业务 内容处理 提供访问
PNG头像 尺寸限制,按需安全解码后重编码 隔离域或受控图片响应
合同文档 独立类型白名单、配额与内容检测 鉴权下载,默认附件方式

示例没有实现图片重编码与恶意内容扫描,不能据此接收所有业务文件。私有文件的下载也要重新鉴权,服务器不得仅凭猜到文件名就返回内容;文件标识应与数据库中的所属用户对应。

正式上线前重点排查四类校验失效场景

  • 正常头像也被拒绝:检查fileinfo扩展、PHP上传限制和PNG策略是否一致。
  • 请求中没有文件:核对表单编码及post_max_size,区分传输失败和内容不合格。
  • 命令行移动测试失败:move_uploaded_file只接受真正的PHP上传文件,不要用普通临时文件绕过校验。
  • 上传成功却能作为脚本访问:立即停止放行,复核真实存储路径与Web服务器映射,不能只靠后缀限制。

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

11244

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

6521

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

2155

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

4128

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

4834

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

3811

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

5457

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

4282

2023.11.13

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

0

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
墨刀帮助中心
墨刀帮助中心

共0课时 | 0人学习

MyEclipse学习中心
MyEclipse学习中心

共0课时 | 0人学习

Apache Subversion 官方手册
Apache Subversion 官方手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn