Skip to content

MacCMS 源码安全审计报告 ​

本页是对本仓库 MacCMS V10 源码(框架为 ThinkPHP 5.0.24)做的一次只读安全审计记录。目标有三个:排查是否存在后门 / webshell、复核历史上影响巨大的 ThinkPHP5 远程命令执行(RCE,Remote Code Execution)漏洞是否已打补丁、并把需要站长手动做的加固项整理出来。

审计元信息(审计的是哪个版本) ​

安全审计结论只对特定版本的源码成立。下面列清本次审计对应的版本坐标,你应当拿它和自己手上的源码比对,一致才能直接套用本页结论。

项目值
审计日期2026-10-12
上游仓库github.com/magicblack/maccms10(https://github.com/magicblack/maccms10.git)
程序版本号(code)2026.1000.4056(取自 application/extra/version.php)
升级指纹(update_hash)4d95c1cdb0133a17a4e482c72aff430d(同文件,可作版本比对的辅助指纹)
框架版本ThinkPHP 5.0.24(thinkphp/base.php 的 THINK_VERSION)
Git master HEADa468b6236c1e028b1aca3f91f463345cf72f16c7

审计口径

审计阅读源码,对每个命中的「危险特征」都结合上下文做了人工判读,分成三档:合法(框架/业务正常用法)、可疑(需要关注的攻击面)、恶意(真实后门)。结论:本次审计范围内未发现恶意后门。下文把扫描范围、命中点和判定逐条列清楚,方便你自行复核。

一、审计范围与方法 ​

扫描对象是整套源码,按风险优先级覆盖:

  • 入口与安装:index.php、admin.php、api.php、install.php、application/install/
  • 插件(第三方代码重点看):addons/ 下的 adminloginbg、aicontent、mpt、socialws
  • 可写 / 上传面:upload/、runtime/、static/、template/
  • 第三方库:vendor/、extend/、thinkphp/
  • 业务代码:application/admin、application/api、application/index、application/common
  • 配置:application/config.php、application/route.php、application/extra/*.php

方法是按一份危险特征清单做全仓匹配,命中后逐条看上下文判定:

  • 代码执行:eval、assert、create_function、call_user_func(_array)、动态可变函数 $a($b)
  • 编解码混淆:base64_decode、gzinflate、gzuncompress、gzdecode、str_rot13、strrev,尤其是多层嵌套(如 eval(gzinflate(base64_decode(...))))
  • 命令执行:system、exec、shell_exec、passthru、popen、proc_open、反引号
  • 输入直达危险函数:$_GET / $_POST / $_REQUEST / $_COOKIE / php://input 直接拼进上述函数
  • 正则后门:preg_replace 带 /e 修饰符
  • 落地写马:file_put_contents / fwrite 写 .php、move_uploaded_file 到可执行目录
  • 远程回连:fsockopen / 远程 fopen / curl 与编解码组合

二、后门 / Webshell 排查结论 ​

结论:未发现后门或 webshell。 所有命中的危险特征都能对应到框架或业务的正常用途。下面是逐类判定。

代码执行类(eval / assert / create_function)—— 判定:合法 ​

位置用途判定
thinkphp/library/think/view/driver/Php.php原生 PHP 模板驱动,eval('?>' . $this->content) 渲染磁盘上的模板文件内容,不是请求参数合法(框架模板引擎标准实现)
application/common/util/Dir.phpcreate_function 生成目录排序回调(固定逻辑,无外部输入)合法
application/common/util/PclZip.php多处 eval(...) 全部在注释里(// 开头),实际走的是普通可变函数调用合法(第三方 zip 库)
application/common/util/SlidingWindowIpLimiter.php$handler->eval(...) 是 Redis 的 EVAL 命令(执行 Lua 限流脚本),不是 PHP eval合法

关于模板引擎的 eval

eval('?>' . $this->content) 看着吓人,但它执行的是模板文件内容,和所有 PHP 模板引擎(本质都是 include 或 eval 模板)一样。只要后台模板不被攻击者篡改、不允许上传 .php 到模板目录,它就不是风险点。真正要防的是「别让人往模板目录写文件」,这归入下文的权限收紧。

命令执行类(shell_exec / proc_open 等)—— 判定:合法 ​

位置用途判定
application/admin/controller/Index.php后台仪表盘取 CPU / 内存占用,命令是写死的(wmic、free、top、sysctl),无任何用户输入拼接合法(仅后台可触发)
application/common/util/OpenccConverter.php调用 opencc 二进制做简繁转换,命令固定合法
thinkphp/library/think/console/output/Ask.php、Console.php命令行交互(stty、mode CON),只在 CLI 下跑合法(框架 console)
thinkphp/library/think/Process.php框架 Process 组件封装 proc_open合法

编解码类(base64_decode)—— 判定:合法 ​

全仓的 base64_decode 没有一处和 eval / 命令执行组合,没有多层嵌套混淆。典型用途:

  • application/common/model/Collect.php 多处 base64_decode($param['param']):解码采集附加查询串,解码后拼进采集 URL 并交给 checkCjUrl() 做 SSRF 校验。这是采集功能的正常参数解码,不是后门。
  • Update.php / Safety.php / common.php / Addon.php 里的 base64 是被编码的普通字符串,解码后分别是官方更新地址 https://update.maccms.la/、静态接口域名 http://api.dplayerstatic.com、「预留功能」字样、以及一段版权说明(指向官方仓库 github.com/magicblack)。属于轻度字符串混淆,解码值均为 URL 或文案,不含任何可执行代码。
  • application/common/util/ 下的 JwtService、SensitiveDataCrypto、AddonSecureInstaller、AddonCloudService、PushDispatcher 等:base64 用于 JWT、加解密、签名校验,标准用法。

正则后门 / 输入直达 / 落地写马 —— 判定:均未命中 ​

  • preg_replace /e:未发现带 /e 修饰符的 preg_replace(命中的几处正则不含 /e,是普通字符串替换)。
  • 输入直达危险函数:未发现 eval($_POST[...])、system($_GET[...])、$可变函数($_REQUEST[...]) 这类把请求输入直接喂给危险函数的写法。
  • php://input:命中点都是正常用途——微信 / 支付异步回调验签(且 WechatPublic.php 还显式 libxml_disable_entity_loader(true) 防 XXE)、JSON 请求体解析、框架自身的 input 捕获。
  • 落地写 .php:只有两处——install/controller/Index.php 安装时写 database.php(受 install.lock 控制)、路由缓存命令写 runtime/route.php(框架优化)。均无外部可控内容写入可执行路径。
  • move_uploaded_file / fsockopen:业务代码里未命中,上传走的是框架 think\File 组件(带类型 / 大小 / 扩展名校验)。

第三方插件(addons)—— 判定:合法 ​

四个插件 adminloginbg、aicontent、mpt、socialws 均通读过。风险最高的 socialws(常驻 WebSocket 服务,依赖 workerman)代码质量反而很规范:握手用 Cookie 还原 uid 时查库校验 user_check,用 PDO 预处理语句 + hash_equals 做常量时间比较,并对常驻进程内存做了上界控制防 DoS。个人房间(user_<uid>)只允许本人订阅。属于考虑了安全的正常功能代码,不是后门。

三、ThinkPHP 5.0.24 RCE 补丁复核 ​

历史上最有名的 ThinkPHP5 RCE 利用链形如:

?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami

它靠在路由里塞 \think\app 这种带命名空间分隔符 \ 的「控制器名」,让框架实例化到 \think\App 并触达 invokefunction,从而执行任意函数。复核结论如下:

补丁已覆盖。 关键点在 thinkphp/library/think/App.php 的 module() 方法(约第 554 行),控制器名有正则白名单校验:

php
if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) {
    throw new HttpException(404, 'controller not exists:' . $controller);
}
  • 该正则只允许「字母开头 + 字母 / 数字 / 下划线 / 点」的控制器名,命名空间分隔符 \ 直接被拒,所以 \think\app 这类 payload 会命中 404,进不去。
  • App::invokeFunction() 虽然还在(约第 311 行),但只有 case 'function'(开发者在路由里写的闭包)才会调它,无法再通过 URL 直达任意函数。
  • THINK_VERSION 在 thinkphp/base.php 中确认为 5.0.24,正则补丁完整存在、未被改动。

此外复核了几个相关面:

  • Request::method()(Request.php 约第 518 行):表单伪方法 _method 做了白名单限制(只接受 GET/POST/DELETE/PUT/PATCH),HTTP_X_HTTP_METHOD_OVERRIDE 为标准支持。
  • Request::filterExp()(约第 1122 行):标准的 SQL 关键字过滤(EXP/NEQ/GT/.../IN),是 5.0.24 的正常实现,用于缓解方法覆盖类 SQL 注入。
  • 路由配置 application/route.php:只有正常的伪静态规则,映射到已知控制器(vod/art/actor/role/manga/live 等),没有 function 闭包路由、也没有允许 \think\ 直达的危险路由。
  • 调试默认值 application/config.php:出厂即 app_debug => false、app_trace => false,默认不泄露报错细节。

仍需站长手动做的事

补丁在框架层已覆盖经典 RCE,但 ThinkPHP 5.0.x 历史上还有数据库驱动 SQL 注入等 CVE。源码层无法替你拦住所有变体,建议在 Nginx / 云 WAF 再加一层特征拦截(见下)作为纵深防御。

四、加固建议(需站长手动执行) ​

这些都在源码之外,装完 / 升级后请逐条落实,详细操作见安全加固:

  1. 加 WAF / 拦截规则:在 Nginx 或云防火墙拦掉带 invokefunction、call_user_func_array、\think\ 特征的请求,作为 RCE 的纵深防御。
  2. 后台入口改名(强制):默认 admin.php 会被源码强制拦截,必须改名后用新文件名访问。
  3. 关调试:生产环境确认 app_debug / app_trace 为 false。
  4. 收紧目录权限:只给 runtime、upload 写权限,其余最小权限;禁止向模板目录写入 .php,防止模板引擎 eval 被利用。
  5. 锁安装目录:安装后保留 install.lock,避免被触发重装。
  6. 及时升级:关注官方仓库 magicblack/maccms10 的安全公告,升级前备份数据库与配置。

加固操作明细见安全加固,源码结构说明见源码结构分析,报错排查见部署排障。