需在ThinkPHP 6.0框架层主动拦截:第一步白名单校验扩展名;第二步用finfo_open校验真实MIME类型;第三步重命名剥离原始文件名;禁用危险函数;启用中间件检测WebShell特征;上传目录设为无执行权限。

在 ThinkPHP 6.0 应用中防止攻击者通过上传接口植入 WebShell 文件并执行恶意代码,需在框架层主动拦截可疑文件、阻断危险函数调用、限制脚本执行权限,而非依赖外部 WAF 被动检测。
上传文件时实时校验后缀与 MIME 类型
第一步:在文件上传逻辑中,禁用所有可执行扩展名。使用 validate 方法强制限定白名单:
→ $file->validate(['size'=>1024*1024,'ext'=>'jpg,png,gif,docx,xlsx,pdf'])
第二步:仅靠后缀校验极易被绕过(如上传 shell.php.jpg),必须同步读取文件头判断真实类型。调用 finfo_open(FILEINFO_MIME_TYPE) 获取 MIME,拒绝 text/php、application/x-php、application/x-httpd-php 等高危类型。
第三步:对上传后的临时文件重命名,彻底剥离原始文件名。使用 uniqid() . '.' . $safeExt 生成新名,避免攻击者利用 %00 截断或路径遍历控制最终保存路径。
禁用 PHP 危险函数并限制运行环境
方法一:在 public/index.php 入口顶部添加全局禁用:ini_set('disable_functions', 'eval,assert,system,exec,passthru,shell_exec,proc_open,popen,curl_exec,dl,pcntl_exec');
方法二:在 php.ini 中配置更彻底:disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,dl,pcntl_exec,eval,assert
【注意】此操作不可逆,修改后必须重启 PHP-FPM 或 Apache 服务才能生效。
方法三:为上传目录单独设置 .htaccess(Apache)或 Nginx 配置:
Apache 下写入 php_flag engine off;Nginx 下配置 location ~ ^/public/uploads/.*\.(php|php5|phtml|phps)$ { deny all; },从 Web 层杜绝脚本解析。
启用 TP6 内置中间件拦截可疑请求参数
① 创建中间件:php think make:middleware CheckWebshellInput
② 在 app/middleware/CheckWebshellInput.php 的 handle 方法中,检查 GET/POST/REQUEST 中是否含以下特征:
→ 包含 base64_decode、gzinflate、str_rot13 等混淆函数名
→ 参数值含 eval(、assert(、$_POST[、$_GET[、file_put_contents( 等典型 WebShell 片段
→ URL 路径或参数中出现 cmd=、act=shell、function=file 等敏感关键词
③ 匹配任意一条即调用 halt('Access Denied') 终止请求,并记录日志到 runtime/log/security/ 目录下。
④ 将该中间件注册至 app/middleware.php 的全局中间件数组首位,确保最先执行。
设置上传目录无执行权限(Linux 系统必做)
进入服务器终端,定位到项目上传根目录(如 public/uploads/):chmod -R 755 ./uploads
执行关键命令移除执行位:find ./uploads -type f -name "*.php" -deletechmod -R -x ./uploads
【必须执行】否则即使文件名合法,仍可能被 Nginx/Apache 误解析执行。
验证是否生效:ls -ld ./uploads 输出权限应不含 x(如 drw-r--r--);尝试访问 https://yoursite.com/uploads/test.php 应返回 403 或直接下载而非执行。


















