一次 PHP 框架核心文件感染型后门的完整清理($b25st $b25end):ThinkPHP、Laravel、Workerman、Yii 均会中招

admin 2026-07-05 17:01:39 14

最近处理一次非常顽固PHP 后门感染。起初以为只是 ThinkPHP App.php 插入 WebShell。

实际发现,这个后门并不感染 ThinkPHP。它的真正目标PHP 项目里“每次启动都会载”核心入口文件。因此 ThinkPHP、Laravel、Workerman、Yii、TopThink ORM 都会感染。

这类后门恶心地方不是代码长,而是选择框架核心文件作为点。只要项目访问、队列启动、Workerman 常驻进程运行,甚至 IDE Composer 触发 PHP 代码扫描,可能重新执行。

一、感染特征

最明显的特征是文件中出现如下标记:

;$b25st=0;
$l0ader=function($check){...};
;$b25ed=0;

b25st 是后门开始标记,b25ed 是结束标记,中间是一大段高度混淆的 PHP loader。

我们实际样本中解出的强特征包括:

$b25st
$b25ed
$l0ader=function($check)
0x6578706c
restore_error_handler()
error_reporting(0)
__run_code_x20
/sess_zziudbrorkdadhip90v9jmj
udp://pudp.crmeb.pw:9988
http://p30.crmeb.pw/v20/init?

它不是普通一句 eval($_POST [x]) 那种低级 WebShell,而是把大量函数名和远程地址藏进十六进制数组里,运行时再动态还原。

被还原出来的能力包括:

base64_decode
json_decode
file_get_contents
file_put_contents
stream_socket_client
pcntl_fork
cli_set_process_title
gzuncompress

这些函数组合起来,基本就能判断它不是单纯的信息收集代码,而是具备远程通信、下载指令、写文件、后台驻留、执行动态代码的完整后门。

二、实际感染范围

开始只是看到ThinkPHP 被感染,

但我们本机实际排查发现,感染范围远不止 ThinkPHP。

常见被感染文件包括:

ThinkPHP:
thinkphp/library/think/App.php
vendor/topthink/framework/src/think/App.php
vendor/topthink/framework/library/think/App.php

TopThink ORM:
vendor/topthink/think-orm/src/facade/Db.php

Laravel:
vendor/laravel/framework/src/Illuminate/Foundation/Application.php

Workerman:
vendor/workerman/workerman/Worker.php

Yii:
vendor/yiisoft/yii2/base/Application.php

也就是说,它真正盯上的不是某一个框架,而是所有 PHP 项目中高频加载、稳定存在、很少被业务开发者检查的核心文件。

Laravel 项目启动会加载 Application.php,ThinkPHP 会加载 App.php,Workerman 常驻进程会加载 Worker.php,Yii 会加载自己的 Application.php。后门注入这些文件后,就能借正常业务启动流程自动运行。

三、它具体干了什么

从样本行为看,这个后门主要做了几件事。

第一,隐藏自身。

它用 $b25st 和 $b25ed 包住恶意代码,但真正的函数名、远程地址、临时文件名都被编码成十六进制数组。普通搜索 evalassert 不一定能直接发现。

第二,收集环境信息。

它会读取当前系统、PHP 环境、运行用户、路径、主机标识等信息,生成一个客户端 ID,用来让远程控制端识别这台机器。

第三,建立 C2 通信。

我们样本中出现了:

udp://pudp.crmeb.pw:9988
http://p30.crmeb.pw/v20/init?

这说明它会尝试向远程服务器上报信息,并获取后续指令。

第四,写入临时标记文件。

样本里出现了类似:

/sess_zziudbrorkdadhip90v9jmj

这类文件通常用于记录运行状态、控制执行频率、避免重复启动,或者作为后续代码落地点。

第五,尝试后台驻留。

它使用了 pcntl_forkcli_set_process_title 等函数。CLI 模式下可能 fork 子进程,让后门脱离当前请求继续运行。Web 模式下也可能通过请求触发后继续在后台回连。

第六,具备重新写文件能力。

它包含 file_put_contents,并且我们的实际现象也证明:清理后某些文件会再次被改回感染状态。这说明不是单个文件静态中毒,而是某个运行中的 PHP 进程或持久化入口还在继续落盘。

四、为什么这个病毒很顽固

这次最明显的现象就是:删了又出现。

最初我们发现:

~/Sites/workman-project/vendor/topthink/think-orm/src/facade/Db.php

被反复修改。后来又陆续发现:

~/Sites/project1/vendor/topthink/framework/src/think/App.php
~/Sites/project2/thinkphp/library/think/App.php
~Sites/project3/vendor/laravel/framework/src/Illuminate/Foundation/Application.php

也都被插入同类代码。

它顽固主要有三个原因。

第一,它感染的是 vendor/framework 核心文件。

这些文件不是业务代码,平时很少有人逐行看。项目一多,很容易漏掉。

第二,它感染多个框架。

如果只按 ThinkPHP 查,就会漏掉 Laravel、Workerman、Yii。我们一开始也遇到过这个问题:某些 Sites 里的项目没有被第一版规则命中,后来才把规则扩展到 Laravel Application.php、Workerman Worker.php、Yii Application.php

第三,可能存在内存中的循环进程。

哪怕磁盘文件已经清理,如果某个 PHP 常驻进程已经加载过后门,它仍可能继续执行,把干净文件重新写脏。

这就是为什么单纯“删除恶意代码”不够,必须配合重启

五、我们做过哪些排查和清理

这次不是直接写个脚本扫一下就结束,中间做了几轮确认。

第一步,监控被篡改文件。

最开始针对:

vendor/topthink/think-orm/src/facade/Db.php

做了文件 hash 监控。文件一变,就保存 baseline 和 mutated 副本。后来确实抓到了变化:

old_hash: 7861ba53...
new_hash: fdaccdbc...
mutated copy: runtime/security-watch/Db.php.mutated...

这证明文件确实被再次改写,不是误判。

第二步,分析注入代码特征。

根据感染样本,提取出:

$b25st / $b25ed
$l0ader=function($check)
十六进制函数表
C2 地址
临时 sess 标记
__run_code_x20

然后把清理脚本从“只匹配固定三行”改成“综合强特征匹配”,避免变种去掉边界标记后漏扫。

第三步,扩大扫描范围。

最初只看 ThinkPHP,后来确认 Laravel、Workerman、Yii 都会被感染,于是把扫描目标扩到整个:

~/Sites

并且不是只扫 .php,而是允许按文件大小限制扫描所有可疑文本文件。

第四步,批量清理。

一次关键清理结果是:

扫描目录: ~/Sites
命中: 66
成功清理: 66

这些是历史污染样本,用来留证,不是项目运行文件,而且当时是 root 权限保存的,普通用户脚本无法写回。所以真正项目中的 55 个感染文件已经全部清理。

被清理的真实项目文件包括 Laravel、ThinkPHP、Workerman、Yii、TopThink ORM 多类核心文件,例如:

vendor/laravel/framework/src/Illuminate/Foundation/Application.php
vendor/workerman/workerman/Worker.php
thinkphp/library/think/App.php
vendor/topthink/framework/library/think/App.php
vendor/topthink/think-orm/src/facade/Db.php
vendor/yiisoft/yii2/base/Application.php

第五步,排查可疑进程。

期间看到过:

composer update --dry-run --no-interaction

一开始怀疑是不是病毒触发。后来通过父进程确认,它是 PhpStorm 启动的 Composer 自动检查,不是这次后门的直接证据。

但这个发现也说明:IDE、Composer、项目扫描工具都可能启动 PHP 进程。在清理阶段,这些东西会干扰判断,所以最好临时关闭 PhpStorm 的 Composer 自动同步或直接退出 IDE。

第六步,重启电脑。

这是关键步骤。

因为这类后门可能已经被 Workerman、queue、php-fpm、CLI 进程加载进内存。只清理磁盘文件,不杀掉内存进程,就可能继续复发。

所以最终采用的流程是:

先全盘清理
立即重启
重启后再次扫描
等待一段时间
再扫描确认

第七步,重启后复扫。

重启后重新扫描:

~
/Applications
/Library
/usr
/usr/local
/opt
/private/tmp
/private/var
/etc
/bin
/sbin
/home
结果全部是:0
MATCHED=0
另外还专门检查了 ~/Sites 下这些高风险文件在重启后是否又被写入:
App.php
Application.php
Db.php
Worker.php
结果为空,没有新的修改记录。
当前也没有真实的:
php
composer
php-fpm
workerman
artisan
think
swoole
queue
进程在运行。
这说明:清理后立即重启,再复扫,目前没有发现后门重新落盘。

六、最终有效的清理方案

结合这次实战,比较可靠的清理流程应该是:

1. 停止所有 PHP 相关进程

包括:

php-fpm
Workerman
Laravel queue
artisan
think
swoole
composer
IDE 自动 Composer 检查

如果不确定有没有残留,直接准备重启。

2. 全盘扫描感染特征

不要只扫 ThinkPHP,也不要只扫当前项目。

至少覆盖:

所有 PHP 项目目录
/usr/local
/opt
/private/tmp
用户目录下的 PHP 环境目录
Web 服务目录
扫描特征至少包含:
$b25st
$b25ed
$l0ader=function($check)
0x6578706c
restore_error_handler()
error_reporting(0)
udp://pudp.crmeb.pw:9988
http://p30.crmeb.pw/v20/init?
/sess_zziudbrorkdadhip90v9jmj
__run_code_x20

3. 清理所有命中文件

清理时必须注意:

只删除恶意注入块
不要破坏原框架文件结构
清理前备份
保留文件权限
保留 mtime
输出清理列表
如果项目使用 Composer,最干净的方式是:
删除 vendor
重新 composer install
但如果项目很多,或者 vendor 中有历史改动,就需要先用特征脚本批量清理,再逐个验证。

4. 立即重启

这是这次清理能稳定下来的关键。

如果不重启,内存里残留的 PHP 后门进程可能继续写文件。尤其是 Workerman、队列、php-fpm worker 这类常驻进程,风险最大。

5. 重启后立即复扫

重启后再次全盘扫描,如果命中为 0,说明磁盘上的感染文件已经清掉,内存里的旧进程也没有立刻重新落盘。

6. 等 1 小时后再扫一次

这是观察是否存在持久化的关键。

如果 1 小时后仍然:0

MATCHED=0

并且高风险核心文件没有新的 mtime 变化,基本可以判断清理完成。

七、后续加固建议

清理完成不代表风险结束,因为后门运行期间可能已经泄露配置。

建议继续做:

修改服务器登录密码
修改数据库密码
修改后台管理员密码
更换第三方 API key
检查 crontab
检查 LaunchAgent / LaunchDaemon
检查 php-fpm 配置
检查 Workerman 启动脚本
检查 Composer scripts
检查 /tmp、/private/tmp 下异常 sess 文件
检查 Web 访问日志中的异常请求

如果是 Linux 服务器,建议用 auditd 对核心文件加监控;如果是 macOS,本次使用的是 fs_usage 思路,重点抓谁在写:

App.php
Application.php
Db.php
Worker.php

只有抓到写入进程,才能真正确认是否还有隐藏持久化。

八、结论

这次感染不能简单理解成“ThinkPHP app.php 中毒”。更准确地说,它是一种 PHP 框架核心文件感染型后门。

它会批量寻找 PHP 项目中稳定存在、每次启动都会加载的核心文件,然后插入混淆 loader。ThinkPHP、Laravel、Workerman、Yii、TopThink ORM 都可能中招。

它之所以顽固,是因为:

感染点分散在多个项目
落点都是框架核心文件
普通搜索不容易发现
可能存在内存中的循环进程
清理后不重启可能再次写回

感染点分散在多个项目
落点都是框架核心文件
普通搜索不容易发现
可能存在内存中的循环进程
清理后不重启可能再次写回

这次最终有效的办法是:

全盘扫描
清理全部感染文件
立即重启
重启后再次全盘扫描
等待观察
再次复扫确认

从当前结果看,重启后全盘复扫已经没有再发现感染特征,高风险框架文件也没有新的写入。后续只要 1 小时后复扫仍然为 0,并且监控没有抓到新的写入进程,就可以认为这次后门已经清理干净。

 


社区声明 1、本站提供的一切软件、教程和内容信息仅限用于学习和研究目的
2、本站资源为用户分享,如有侵权请邮件与我们联系处理敬请谅解!
3、本站信息来自网络,版权争议与本站无关。您必须在下载后的24小时之内,从您的电脑或手机中彻底删除上述内容
最新回复 (0)

您可以在 登录 or 注册 后,对此帖发表评论!

返回