PHP网站被入侵后,攻击者往往会在服务器目录中留下WebShell后门文件,一旦清理不彻底,即使修改了所有密码,网站仍然会被反复控制。删除PHP后门并不是简单地删掉一个文件那么简单,需要先准确定位后门位置,理解它的隐藏方式,再结合PHP版本特性进行针对性查杀。特别是PHP7和PHP8在函数支持和语法层面存在不少差异,很多在PHP7下能正常工作的后门,到了PHP8环境会直接报错,这种差异既可以被利用来缩小排查范围,也可能导致查杀工具误报或漏报。

一、PHP后门的常见类型与隐藏手法
在动手删除之前,必须先了解后门长什么样。最经典的一句话木马通常只有一个eval或assert调用,例如接收POST参数并执行。这类后门体积小,特征明显,容易被查杀工具发现。于是攻击者发展出了多种变形手段。
第一种是混淆变形,通过base64编码、gzinflate压缩、字符串拼接、异或运算等方式隐藏关键函数名。第二种是利用PHP的可变变量、回调函数等特性,例如用array_map配合$_REQUEST执行代码,这类后门在静态扫描中很难匹配到eval这样的固定特征。第三种是大马,功能完整的文件管理器,支持上传、下载、执行命令、连接数据库,体积大但往往藏在正常目录或伪装成图片文件。
还有一种比较隐蔽的方式是不落盘后门,攻击者利用.htaccess把图片文件当PHP解析,或者直接在PHP的配置文件、主题文件中插入几行恶意代码,混在正常业务代码里,肉眼几乎无法分辨。此外,通过php auto_prepend_file配置注入、计划任务、写入crontab等方式驻留的后门,即使删除了WebShell文件也会重新生成,排查时必须一并检查。
二、如何定位并删除PHP后门文件
定位后门的第一步是文件时间戳分析。攻击者上传后门文件后,文件的修改时间通常会与正常业务文件不同步。在Linux下可以找出最近7天内被修改的PHP文件:
find /var/www -name "*.php" -mtime -7 -ls # 只列出最近24小时内修改的文件 find /var/www -name "*.php" -mtime -1 -ls
第二步是危险函数扫描。绝大多数PHP后门离不开eval、assert、system、exec、shell_exec、passthru、popen、proc_open这几个函数,以及base64_decode、gzinflate、str_rot13等解码函数。可以用grep快速扫描:
grep -rn --include="*.php" -E "eval\s*\(|assert\s*\(|system\s*\(|shell_exec\s*\(|passthru\s*\(" /var/www
# 扫描常见的编码混淆特征
grep -rn --include="*.php" -E "base64_decode|gzinflate|str_rot13|gzuncompress" /var/www第三步是借助日志回溯。查看Nginx或Apache的访问日志,寻找访问异常文件名的记录,尤其是那些只被同一个IP频繁POST访问、而正常用户不会访问的文件,基本可以确定是后门。找到后门文件后,不要急着直接删除,建议先复制备份到服务器外的安全位置留作证据,然后从Web目录删除,同时检查同目录下是否有攻击者留下的其他文件。
如果站点使用Git或SVN管理代码,最彻底的方式是用版本控制比对差异,执行git status就能立刻发现所有被篡改和新增的文件,效率远高于肉眼逐个排查。
三、PHP7与PHP8环境下的查杀差异
PHP8相比PHP7删除和弃用了大量特性,这直接影响后门的存活情况和查杀策略。最典型的是create_function函数,在PHP8中已被彻底移除。大量老式后门依赖create_function来构造匿名函数执行恶意代码,这类后门迁移到PHP8后会直接抛出错误,反而更容易通过错误日志定位到具体文件:
# 查看PHP错误日志中被移除函数的报错,可快速定位老式后门 grep -i "create_function\|Call to undefined function" /var/log/php-fpm/error.log
其次,assert在PHP8中的行为发生了变化。PHP7.2开始assert不再支持执行字符串参数,到PHP8这一限制更加严格,导致许多以assert($_POST['x'])形式存在的一句话木马完全失效。同样,each函数、money_format函数等被移除,也让部分老后门无法运行。这意味着如果你的服务器已升级到PHP8,那些没有触发报错却仍然存在的后门,大概率使用了eval、回调函数或加密解密等PHP8仍然支持的特性,排查重点应放在eval调用、preg_replace的e修饰符残留、动态函数调用如$a($b)这类写法上。
反过来,升级PHP版本也可能让查杀工具的规则失效。一些老牌扫描器内置的规则库基于PHP7语法编写,对PHP8特有的特性如match表达式、箭头函数、命名参数等构成的变形后门识别能力不足。例如下面这种利用PHP8箭头函数的后门:
<?php // PHP8特性构造的隐蔽后门,传统规则库难以匹配 $f = fn($x) => eval($x); $f($_POST['cmd']); ?>
这种写法在PHP7环境下根本无法运行,但在PHP8下完全合法。因此在PHP8环境查杀后门时,除了依赖工具,还应人工关注eval、proc_open等少量核心函数的一切调用场景,无论其外围包装了什么新语法。
四、删除后门后的加固与防复发措施
删掉后门文件只是治标,找到入侵入口并加固才是治本。首先检查所有后门出现的原因:是否存在任意文件上传漏洞、是否使用了被爆出漏洞的旧版CMS或插件、FTP或SSH密码是否泄露。修改所有密码,包括数据库密码、后台管理员密码、服务器root密码,并检查是否有异常的用户账号和SSH公钥被写入authorized_keys文件。
其次做目录权限收敛。Web运行用户不应该对PHP文件有写权限,上传目录禁止执行PHP。在Nginx中可以这样配置:
location ~* ^/uploads/.*\.(php|php5|phtml)$ {
deny all;
}最后建议部署定期扫描机制。可以使用开源的查杀工具定期全盘扫描,同时开启PHP的disable_functions限制,在php.ini中禁用业务不需要的危险函数:
disable_functions = exec,system,shell_exec,passthru,proc_open,popen,parse_ini_file,show_source
配合open_basedir限制PHP脚本的访问范围,即使未来再次出现后门,其能造成的破坏也会被大幅压缩。定期更新CMS和插件、开启文件篡改监控、保留完整的访问日志,这些措施组合起来,才能真正做到清除后门并防止网站被再次入侵。