> 来源：https://mac-cms.com/cms/cms-security-audit
> 简介：对 MacCMS V10（ThinkPHP 5.0.24）源码做的一次只读安全审计：危险函数与 webshell 特征扫描、后门排查结论、TP5.0.24 RCE 补丁复核、以及发现项的判定与加固建议。
> 更新：2026-11-02

# 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)（`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` HEAD | `a468b6236c1e028b1aca3f91f463345cf72f16c7` |

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

## 一、审计范围与方法

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

- 入口与安装：`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.php` | `create_function` 生成目录排序回调（固定逻辑，无外部输入） | 合法 |
| `application/common/util/PclZip.php` | 多处 `eval(...)` 全部在注释里（`//` 开头），实际走的是普通可变函数调用 | 合法（第三方 zip 库） |
| `application/common/util/SlidingWindowIpLimiter.php` | `$handler->eval(...)` 是 Redis 的 `EVAL` 命令（执行 Lua 限流脚本），不是 PHP `eval` | 合法 |

::: warning 关于模板引擎的 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`，默认不泄露报错细节。

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

## 四、加固建议（需站长手动执行）

这些都在源码之外，装完 / 升级后请逐条落实，详细操作见[安全加固](/cms/cms-security)：

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](https://github.com/magicblack/maccms10) 的安全公告，升级前备份数据库与配置。

---

加固操作明细见[安全加固](/cms/cms-security)，源码结构说明见[源码结构分析](/cms/cms-source-analysis)，报错排查见[部署排障](/cms/cms-troubleshooting)。
