本文约 3,897 字,预计阅读 10 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:校验通过,但站点还是被挂了
上一节讲了 wp core verify-checksums,但它只管 WordPress 核心。现实中:
- 后门文件在
wp-content/uploads/2024/07/x.php——uploads 是唯一必须可写的目录; - 恶意代码被注入主题的
functions.php——核心校验管不到; - 数据库
wp_options里塞了跳转 JS——文件系统完全干净; - 隐藏管理员账号——文件一个没改。
所以需要多维度检测,不能只依赖一条命令。
原理分析:攻击者藏在哪
按被黑途径分类,藏匿位置不同:
| 入侵途径 | 后门位置 | 检测难度 |
|---|---|---|
| 插件上传漏洞 | wp-content/uploads/**/*.php |
低(不该有 PHP) |
| 主题文件写入 | 主题的 functions.php、header.php |
中(要 diff) |
| 数据库注入 | wp_options、wp_posts.post_content |
中(要查 SQL) |
| 创建账号 | wp_users |
低 |
| 定时任务驻留 | wp_options 里的 cron |
中 |
| 核心文件替换 | wp-admin、wp-includes |
低(校验和) |
| 系统层 | crontab、/tmp、其他站点目录 |
高 |
核心思路:按”不该出现的东西”倒推。
保姆级实操:六种方法
方法一:时间排序(最快,5 分钟定位)
恶意文件的修改时间通常和正常文件不同——它们是某一天被批量放进去的:
find /var/www/mimangfei -name "*.php" -mtime -30 -type f \
-printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort -r | head -40
看什么:某一分钟被创建的一批文件。正常更新不会在同一秒产生 5 个陌生文件。
对比法——找到你最后一次正常更新的时间,之后的所有变动都值得怀疑:
find /var/www/mimangfei -newermt "2025-03-01" -name "*.php" -type f | head -30
注意:后门常用 .php5、.phtml、.phar,甚至伪装成 .jpg.php:
find /var/www/mimangfei/wp-content -type f \
\( -name "*.php*" -o -name "*.phtml" -o -name "*.phar" -o -name "*.inc" \) \
-printf '%TY-%Tm-%Td %p\n' | sort -r | head -40
方法二:uploads 目录查 PHP(命中率最高)
find /var/www/mimangfei/wp-content/uploads -type f \
\( -name "*.php" -o -name "*.phtml" -o -name "*.php5" -o -name "*.php7" \) 2>/dev/null
正常情况下输出应为空,任何结果都高度可疑。看到先看内容再删:
head -40 /var/www/mimangfei/wp-content/uploads/2024/07/x.php
典型后门特征:
<?php @eval($_POST['cmd']); ?> // 一句话木马
<?php assert($_REQUEST['x']); ?>
<?php system($_GET['c']); ?>
方法三:特征字符串扫描
grep -rn --include="*.php" -E \
"(eval\(|assert\(|base64_decode|gzinflate|str_rot13|system\(|passthru\(|shell_exec\(|popen\(|proc_open\()" \
/var/www/mimangfei/wp-content/themes/ | head -30
降噪:base64_decode 误报最多,可先去掉只看高危函数;再用编码混淆特征兜底:
grep -rn --include="*.php" -E "(\\\\x[0-9a-fA-F]{2}){8,}" \
/var/www/mimangfei/wp-content/ | head -20
连续 8 个以上 hex 转义,正常代码不会这么写。
方法四:与官方原版 diff 对比
# 从 wordpress.org 下载同版本主题/插件解压到 /tmp/clean
diff -rq /tmp/clean/主题slug /var/www/mimangfei/wp-content/themes/主题slug
输出示例:
Files /tmp/clean/xxx/functions.php and /var/www/.../functions.php differ
Only in /var/www/.../themes/xxx: backdoor.php
Only in 那行就是多出来的文件,重点看。注意:子主题自定义、插件配置文件也会 differ,要逐个确认。
方法五:数据库检查
很多后门根本不在文件里:
-- options 里的恶意代码
SELECT option_id, option_name, LEFT(option_value,300)
FROM wp_options
WHERE option_value LIKE '%<script%'
OR option_value LIKE '%eval(%'
OR option_value LIKE '%base64_decode%';
-- 文章正文里的隐藏 JS / iframe
SELECT ID, post_title
FROM wp_posts
WHERE post_content LIKE '%<iframe%'
OR post_content LIKE '%document.write%';
-- 站点地址是否被改
SELECT option_name, option_value FROM wp_options WHERE option_name IN ('siteurl','home');
定时任务驻留:
wp cron event list --allow-root
看有没有陌生 hook(后门常用 wp_cron 定期回连 C2 服务器)。
方法六:行为层监控(进阶)
以上都查不出,就从”行为”入手:
# 高频访问的陌生路径
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -30
# 某个可疑文件的访问记录
grep "uploads/2024/07/x.php" /var/log/nginx/access.log | head
# PHP 进程的外连
ss -tnp | grep php-fpm
常见踩坑
- 删了文件就以为完事:不找入侵入口,平均一周内会被二次挂马。必须同步:更换所有密码(FTP/SSH/数据库/WP 后台)、更新全部插件主题、查日志定位入侵时间、删除不用的插件。
- 误删正常文件:
eval(在部分老插件/缓存插件里合法存在。删除前先搜文件名确认。 - 案例:某站反复被挂马,每次删完又出现。最后发现是 FTP 弱密码泄露,攻击者随时能重新上传。改密码 + 关闭 FTP 改用 SFTP 密钥后彻底解决。后门只是结果,入口才是根源。
- 同服务器其他站点:一个站被黑,后门可能通过权限扩散。要检查所有站点目录和
/tmp、/dev/shm,以及crontab -l -u www-data。 - 只看 .php 漏掉 .htaccess:
.htaccess里插入RewriteRule做条件跳转(搜索引擎来的跳到菠菜站)非常常见,必须检查。 - 备份里也有后门:从被黑后的备份恢复,等于把后门也恢复了。恢复要用入侵前的备份点。
- 时间戳被篡改:高级后门会
touch伪装时间戳,只能靠特征扫描和 diff 对比。
总结
篡改检测的正确顺序(由快到慢):find uploads -name "*.php" → 按修改时间排序找”同一时刻批量出现”的文件 → wp core verify-checksums → 特征字符串扫描主题 → 与官方原版 diff → 数据库和 wp-cron 检查 → 访问日志和进程外连。最关键的一条:清理后门 ≠ 修复漏洞,必须先找到入口(弱密码?过期插件?777 权限?)。清理完执行完整的WordPress 月度安全巡检清单,并用WordPress 核心文件完整性校验建立长期监控。
