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

怎么用ChatGPT批量修复PHP项目里的多处漏洞(附可执行代码)

大明吖_3792

大明吖_3792

发布时间:2026-10-23 09:51:18

|

646人浏览过

|

来源于php中文网

原创

用chatgpt批量修复php漏洞,应先形成人工复核的问题与补丁清单,再分批应用和测试。下面的脚本会校验文件哈希,默认只预览,显式应用时保存备份,用于降低重复替换与误覆盖的风险。

ChatGPT官方文件检查与交付文档真实页面截图

第一步:把零散漏洞整理成可逐一核验的问题清单

别上来就直接让ChatGPT修改整站代码,很容易把不同风险等级的漏洞、业务逻辑调整、无关的格式改动混在一起,后续很难挨个核对清楚。

你可以按访问入口、涉及文件、输入来源、危险操作类型、修复目标、测试编号这几个维度列清单,每一条都能单独说清修改原因和改动位置。

把SQL注入、输出编码和权限问题分批处理,同一批只包含关系清楚的变更。秘密泄露和依赖漏洞还需要轮换或升级流程,不能仅靠代码文本替换解决。

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

注意:批量应用补丁不等于自动发现修复漏洞

同一个函数名在不同上下文中可能有不同含义,正则批量替换缺少数据流和业务权限信息,很容易产生错误补丁。AI应先提出带依据的候选差异,人工批准后再应用。

文件哈希与唯一匹配用于确认补丁针对的原始内容没有变化,并不能证明补丁本身正确;应用后的语法、安全回归与业务测试仍是独立验收环节。

ChatGPT操作流程里,把漏洞审查和补丁落地拆成两个独立环节

  1. 新建项目或会话,提供允许对外处理的脱敏代码和目录说明,明确只读审查范围。让ChatGPT按文件列出问题、证据与不确定项,不提交环境秘密,也不默认上传整个生产仓库。

  2. 选择同一类问题,要求输出最小差异与对应测试。逐项核对认证条件、返回格式和正常业务,删除与本次修复无关的重构,必要时让模型解释具体行。

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

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

    下载
  3. 人工批准后,按脚本的file、sha256、before、after结构整理清单。哈希从本地原文件计算,不能让模型猜;先预览所有目标,再核对没有重复文件和不唯一匹配。

  4. 只在独占的离线副本中应用,执行项目语法检查与测试。失败立即停止后续批次,保留日志与备份;所有变更验收后再按正常发布流程部署。

只读审查这批PHP文件,按“文件→输入来源→危险操作→依据→最小补丁→回归测试”输出。
按SQL、XSS、授权等类型分批,不混入无关重构,不修改vendor、上传文件和环境秘密。
不能确认的风险标记待核实;保留认证、租户与资源条件。
先给差异和完整测试,人工批准后才准备精确替换清单。
哈希由本地计算,不猜测;不承诺全站漏洞清零,不自动部署。

完整脚本规则说明:默认先预览效果,正式应用前核对原文件

这个脚本仅支持处理src目录下第一层的PHP文件,单批最多执行20个补丁,同时要求项目的离线备份副本做好明确标识。

不带参数运行脚本的时候,只会生成两个临时演示文件,走完预览、打补丁、回归测试的全流程之后自动清理临时测试资源,完全不会碰你本地的真实项目代码。

<?php
declare(strict_types=1);
function reviewedPatch(string $directory,array $plan,bool $apply=false): array {
    $root=realpath($directory);
    if ($root===false || !is_file($root.'/.repair-sandbox') || count($plan)<1 || count($plan)>20) {
        throw new RuntimeException('An explicitly marked offline project copy is required');
    }
    $changes=[];
    foreach ($plan as $entry) {
        $relative=$entry['file'] ?? null;
        // 教学脚本只允许src下单层PHP文件,拒绝vendor、目录穿越及重复目标。
        if (!is_string($relative) || !preg_match('~^src/[A-Za-z0-9_-]+\.php$~D',$relative) || isset($changes[$relative])) {
            throw new RuntimeException('Unsupported or duplicate target');
        }
        $path=$root.'/'.$relative; $real=realpath($path);
        if ($real===false || is_link($path) || !is_file($real) ||
            !str_starts_with($real,$root.DIRECTORY_SEPARATOR) || filesize($real)>1024*1024) {
            throw new RuntimeException('Unsafe target');
        }
        $old=file_get_contents($real);
        $sha=$entry['sha256'] ?? null; $before=$entry['before'] ?? null; $after=$entry['after'] ?? null;
        if (!is_string($old) || !is_string($sha) || !preg_match('/^[a-f0-9]{64}$/D',$sha) ||
            !hash_equals($sha,hash('sha256',$old)) || !is_string($before) || $before==='' ||
            !is_string($after) || $after===$before || substr_count($old,$before)!==1) {
            throw new RuntimeException('Precondition mismatch');
        }
        $new=str_replace($before,$after,$old);
        $changes[$relative]=['path'=>$real,'old'=>$old,'new'=>$new,'sha'=>$sha];
    }
    if (!$apply) { return ['mode'=>'dry_run','files'=>array_keys($changes)]; }
    $backups=[];
    foreach ($changes as $change) {
        // 离线副本须独占使用;再次校验,避免覆盖预检后已变化的文件。
        if (!hash_equals($change['sha'],hash_file('sha256',$change['path']) ?: '')) {
            throw new RuntimeException('File changed after preflight');
        }
        $backup=$change['path'].'.before-'.substr($change['sha'],0,12).'.bak';
        $handle=fopen($backup,'x'); // 不覆盖已有备份。
        if ($handle===false) { throw new RuntimeException('Backup already exists or cannot be created'); }
        chmod($backup,0600);
        $written=fwrite($handle,$change['old']); fclose($handle);
        if ($written!==strlen($change['old'])) { throw new RuntimeException('Incomplete backup'); }
        $backups[]=$backup;
        $temporary=tempnam(dirname($change['path']),'.repair_');
        if ($temporary===false) { throw new RuntimeException('Cannot stage file'); }
        try {
            if (file_put_contents($temporary,$change['new'])!==strlen($change['new']) ||
                !chmod($temporary,fileperms($change['path']) & 0777) ||
                !rename($temporary,$change['path'])) { throw new RuntimeException('Cannot replace file'); }
        } finally { if (is_file($temporary)) { unlink($temporary); } }
    }
    return ['mode'=>'applied','files'=>array_keys($changes),'backups'=>$backups];
}
if (isset($argv[1])) {
    if (count($argv)<3 || count($argv)>4 || (isset($argv[3]) && $argv[3]!=='--apply')) {
        throw new RuntimeException('Usage: php batch-repair.php PROJECT_COPY PLAN.json [--apply]');
    }
    if (!is_file($argv[2]) || filesize($argv[2])>2*1024*1024) { throw new RuntimeException('Invalid plan'); }
    $json=file_get_contents($argv[2]);
    if ($json===false) { throw new RuntimeException('Cannot read plan'); }
    $plan=json_decode($json,true,32,JSON_THROW_ON_ERROR);
    if (!is_array($plan) || !array_is_list($plan)) { throw new RuntimeException('Plan must be a list'); }
    echo json_encode(reviewedPatch($argv[1],$plan,($argv[3] ?? '')==='--apply'),JSON_THROW_ON_ERROR),PHP_EOL;
    exit;
}
// 无参数仅演示自建临时夹具;不读取或修改真实项目。
$root=sys_get_temp_dir().'/repair_demo_'.bin2hex(random_bytes(8));
if (!mkdir($root,0700) || !mkdir($root.'/src',0700)) { throw new RuntimeException('Cannot create fixture'); }
$view='<?php function demo_render(string $name): string { return $name; }';
$query=<<<'PHP_SOURCE'
<?php function demo_lookup(PDO $db,string $term): array {
    return $db->query("SELECT id FROM items WHERE name = '$term'")->fetchAll(PDO::FETCH_COLUMN);
}
PHP_SOURCE;
$querySafe=<<<'PHP_SOURCE'
<?php function demo_lookup(PDO $db,string $term): array {
    $stmt=$db->prepare('SELECT id FROM items WHERE name = ?');
    $stmt->execute([$term]);
    return $stmt->fetchAll(PDO::FETCH_COLUMN);
}
PHP_SOURCE;
$plan=[['file'=>'src/view.php','sha256'=>hash('sha256',$view),'before'=>'return $name;',
    'after'=>"return htmlspecialchars(\$name, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');"],
    ['file'=>'src/search.php','sha256'=>hash('sha256',$query),'before'=>$query,'after'=>$querySafe]];
$owned=[$root.'/src/view.php',$root.'/src/search.php',$root.'/.repair-sandbox',
    $root.'/src/view.php.before-'.substr(hash('sha256',$view),0,12).'.bak',
    $root.'/src/search.php.before-'.substr(hash('sha256',$query),0,12).'.bak'];
function check(bool $value,string $name,string $detail=''): void {
    if (!$value) { throw new RuntimeException('FAIL: '.$name); }
    echo $name, ': PASS', $detail, PHP_EOL;
}
try {
    file_put_contents($owned[0],$view); file_put_contents($owned[1],$query); file_put_contents($owned[2],'teaching only');
    $dry=reviewedPatch($root,$plan);
    check($dry['mode']==='dry_run' && file_get_contents($owned[0])===$view,'dry_run',' unchanged');
    $result=reviewedPatch($root,$plan,true);
    check(count($result['files'])===2,'approved_apply',' 2 files');
    require $owned[0]; require $owned[1];
    check(demo_render('<b>A</b>')==='<b>A</b>','render_escape');
    $db=new PDO('sqlite::memory:',null,null,[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION]);
    $db->exec('CREATE TABLE items(id INTEGER PRIMARY KEY,name TEXT)');
    $insert=$db->prepare('INSERT INTO items VALUES(?,?)'); $insert->execute([1,"O'Reilly"]);
    check(array_map('intval',demo_lookup($db,"O'Reilly"))===[1],'query_normal');
    check(demo_lookup($db,"' OR 1=1 --")===[],'query_shape');
    try { reviewedPatch($root,$plan); throw new LogicException('Stale plan accepted'); }
    catch (RuntimeException $e) { echo 'stale_plan: PASS rejected',PHP_EOL; }
} finally {
    foreach ($owned as $path) { if (is_file($path)) { unlink($path); } }
    rmdir($root.'/src'); rmdir($root); // 仅清理本脚本创建的精确夹具路径。
}
echo 'Runtime: PHP ',PHP_VERSION,' / ',PHP_SAPI,' / isolated fixtures only',PHP_EOL;
# 先运行隔离教学测试。
php batch-repair.php
# 以下仅用于已备份、人工批准的离线副本;默认不写入。
php batch-repair.php /absolute/project-copy reviewed-plan.json
# 核对预览和清单后,显式应用。
php batch-repair.php /absolute/project-copy reviewed-plan.json --apply

本次在macOS上的PHP 8.5.10 WebAssembly执行临时文件补丁与SQLite回归,没有调用ChatGPT,也没有修改真实项目。程序会拒绝再次使用旧哈希清单,避免在已变更文件上重复叠加补丁。

批量补丁脚本预检、应用与回归的实际输出

脚本仅用于落地已经过审核的补丁,不支持推导未知业务规则

变更 处理方式 关键验证
已确认的小范围代码补丁 精确清单、预检后逐文件应用 原始哈希、唯一匹配和回归测试
跨模块授权或数据结构调整 单独设计与人工评审 业务规则、迁移兼容与恢复能力

标记文件名为.repair-sandbox,只应在已确认的项目副本创建。此脚本不是数据库迁移器,不保留文件所有权、ACL和扩展属性,也不保证多文件整体事务;某个文件应用失败时,之前的文件可能已经更新。

正式运行脚本之前,记得先给整个项目生成完整的版本快照。脚本会按单个文件存储原始备份,也不会覆盖已经生成过的备份文件;如果运行过程中部分补丁执行失败,先回滚恢复,把所有改动核对清楚后,再整理新的补丁清单重新执行,不要直接重复运行同一批任务。

遇到四类失败场景,第一时间停止批量操作

  • 哈希不一致:重新读取当前文件并复核差异,不强行更新清单绕过检查。
  • 匹配不唯一或目标重复:拆小补丁并确定上下文,不替换所有同名片段。
  • 新增权限回归:检查是否误删认证或资源条件,先恢复该批次再重新设计。
  • 测试通过但覆盖不完整:补充真实业务和框架集成测试,不把教学用例当作全站安全证明。

相关文章

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

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

下载

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

热门AI工具

更多
Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

讯飞智作

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

DeepSeek

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

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

豆包大模型

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

切问学术

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

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

Seko
Seko Hot

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

WorkBuddy

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

相关专题

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

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

11284

2023.09.01

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

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

6541

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数据库相关内容,可以阅读本专题下面的文章。

4854

2023.10.23

html怎么上传
html怎么上传

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

3811

2023.11.03

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

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

5477

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