站群病毒外链批量检测和清理实战:300个站167个被挂过黑链手工挨个登录后台删了三天只清了23个,换成自动化扫描加SQL批量替换一个下午搞完剩下144个全部关联页面一条不留
uc建站系统
发布于 2026-08-09 18:20
·
82 阅读
关注
概述
300个站里167个被挂过黑链,手工删了三天只清了23个站的外链,换成自动化扫描+SQL批量替换一下午搞完剩下144个群里一个做了三年站群的老站长说,他300多个站被批量挂黑链的时候,第一反应是挨个登录后台删。三天下来眼睛都看花了,翻了不到四分之一,剩下的站里又有六个已经被百度降权。最后他用了两个脚本+一个SQ……
300个站里167个被挂过黑链,手工删了三天只清了23个站的外链,换成自动化扫描+SQL批量替换一下午搞完剩下144个
群里一个做了三年站群的老站长说,他300多个站被批量挂黑链的时候,第一反应是挨个登录后台删。三天下来眼睛都看花了,翻了不到四分之一,剩下的站里又有六个已经被百度降权。最后他用了两个脚本+一个SQL命令,一个下午清完了剩下144个站的所有异常外链。他说了一句话让我印象很深:"清理黑链本身不慢,慢的是你不知道黑链藏在哪,更不知道有没有清干净。"
这篇就把站群场景下批量检测和清理病毒外链的方法拆开讲。从发现到清除再到防止复发,每种方法的适用规模、局限和实际操作都列清楚。
站群黑链清理,四个环节缺一不可
| 1 | 发现黑链 — 扫描文件、数据库、页面源码,定位所有异常外链 |
| 2 | 定位后门 — 找到攻击者留下的 Webshell、异常文件、恶意插件 |
| 3 | 批量清除 — 文件替换、SQL批量更新、缓存刷新 |
| 4 | 防止复发 — 堵漏洞、改密码、加监控、定期扫描 |
一、黑链到底藏在哪?五个常见藏身位置

清理之前先搞清楚黑链的藏身方式,不然删了表面的代码,后门还在,第二天又长出来了。根据实际处理过的案例,站群黑链主要出现在这五个位置:
1. 模板文件
header.php、footer.php、functions.php 被直接写入隐藏链接或 iframe,最常见也最容易发现。站群如果所有站共用同一套模板,一个模板被改等于全军覆没。
2. 数据库文章内容
wp_posts 表的 post_content 字段被批量插入隐藏链接,用 display:none 或 font-size:0 包裹,前台看不见但搜索引擎能抓取。批量挂马常用这种方式。
3. 插件/主题后门
通过漏洞上传的恶意插件,或者在合法插件里注入后门代码。特征是文件名伪装成正常插件,或者修改了已有插件中的某个 PHP 文件。
4. .htaccess 重定向
在 .htaccess 文件中插入 RewriteRule,把搜索引擎蜘蛛或特定来源的流量重定向到恶意站。普通访客访问正常,但搜索引擎看到的是另一套内容。
5. 上传目录 webshell
wp-content/uploads 目录下被上传了 .php 伪装的图片文件,或者直接就是 webshell 脚本。这是攻击者保持持久访问的关键入口。
二、检测阶段:怎么快速发现哪些站被挂了黑链
站群几百个站,一个个打开看源码不现实。检测阶段的目标是用自动化手段快速筛查,缩小范围。
2.1 Linux 命令行一键扫描
如果你的站群部署在 Linux 服务器上,grep + find 组合是最快的初筛方式。不需要装任何工具,直接上命令:
# 扫描所有PHP文件中是否包含常见的恶意函数grep -r -l "eval(" /www/wwwroot/ --include="*.php" | head -20# 扫描是否有隐藏外链(display:none 包裹的链接)grep -r -l 'display:\s*none.*http' /www/wwwroot/ --include="*.php" --include="*.html"# 扫描 base64_decode(最常见的后门编码方式)grep -r -l "base64_decode" /www/wwwroot/ --include="*.php"# 扫描最近7天内被修改过的PHP文件(最可疑的)find /www/wwwroot/ -name "*.php" -mtime -7 -ls | sort -k8,9# 批量扫描多个站点目录for dir in /www/wwwroot/site*; doecho "=== Scanning $dir ==="grep -r -c "base64_decode\|eval(\|system(\|shell_exec" "$dir" --include="*.php"done
grep 扫描结果怎么看
· eval(base64_decode(...)) — 基本可以确定是后门,几乎没有任何合法插件会用这种方式编码
· system() / shell_exec() / passthru() — 出现在主题或插件目录里需要高度警惕,WP核心文件里偶尔有但很少
· display:none 配合 <a href — 典型的黑链隐藏方式
· 最近7天被修改的文件 — 如果某个文件你自己没改过但出现在了列表里,优先检查
2.2 在线检测工具
命令行适合有服务器权限的情况。如果用的是虚拟主机没有SSH,或者想快速抽查几个站,在线工具更直接:
| 工具 | 检测能力 | 费用 | 适合场景 |
|---|
| Sucuri SiteCheck | 恶意软件扫描、黑链检测、被列入黑名单检查、iframe注入检测 | 免费 | 单站快速扫描,不需要注册 |
| VirusTotal | URL 多引擎扫描,聚合60+杀毒引擎结果 | 免费 | 确认某个链接是否为恶意域名 |
| Quttera | 恶意软件检测、可疑文件识别、AI驱动威胁分析 | 免费版有限制 | 深度扫描,检测未知威胁 |
| 因尔特黑链检测 | 全站链接提取、隐藏链接识别、实时检测 | 免费 | 查看页面所有链接,快速识别未知外链 |
| Google Search Console | 安全问题报告、被黑页面通知、手动操作提醒 | 免费 | Google 发现的安全问题会主动通知 |
在线工具的局限
在线工具只能扫描页面前端渲染结果,数据库里的黑链、.htaccess 的重定向、服务端的后门文件它是看不到的。在线扫描能发现"你已经被挂马了"这个事实,但找到真正的感染源还得上服务器。
2.3 WordPress 安全插件扫描
如果站群用的是 WordPress,每个站装一个安全插件做定期扫描是性价比最高的方案。下面是四款主流插件的功能对比:
| 插件 | 文件扫描 | 防火墙 | 免费版 | 付费起价 | 站群适配 |
|---|
| Wordfence | 完整文件对比+恶意代码签名库 | WAF + 实时IP黑名单 | 支持 | $119/年 | 多站许可贵,免费版够用 |
| Sucuri Security | 远程扫描+黑名单检测 | 付费版含WAF | 基础版 | $199/年 | 多站需企业版,价格高 |
| MalCare | 远程扫描不占服务器资源 | 内置WAF | 不支持 | $99/年 | 一键清理功能省时间 |
| iThemes Security | 文件完整性监控 | 暴力破解防护为主 | 支持 | $99/年 | 侧重防御,清理能力一般 |
站群场景下,Wordfence 免费版是性价比最高的选择。文件扫描引擎能对比 WordPress *** 仓库的原始文件,快速揪出被篡改的核心文件、主题和插件。300个站每个站都装一遍确实麻烦,但很多服务器面板支持批量安装插件,或者用 WP-CLI 一条命令搞定:
# 批量安装并激活 Wordfence(遍历所有站点目录)for site in /www/wwwroot/site*; docd "$site"wp plugin install wordfence --activate --allow-rootecho "Installed on $site"done
三、清理阶段:怎么批量删掉所有黑链
检测完哪些站中了招,接下来是重头戏——批量清理。这里按清理目标分为文件层和数据库层两种方式,站群场景下两种都要用。
3.1 数据库批量清理(针对文章内容中的隐藏链接)
大多数站群黑链是直接写进数据库的 post_content 字段里的。攻击者在文章末尾或中间插入一段隐藏链接代码。这些链接的特征是:被 div style="display:none" 或 span style="position:absolute;left:-9999px" 包裹,或者直接写在正文末尾。SQL 批量替换是最快的清理方式:
-- ===== 1. 先查后删:看看哪些文章被注入了黑链 =====SELECT ID, post_title,SUBSTRING(post_content, LOCATE('display:none', post_content), 200) AS malicious_codeFROM wp_postsWHERE post_content LIKE '%display:none%'AND post_content LIKE '%关键词
','')WHERE post_content LIKE '%display:none%';-- ===== 3. 删除绝对定位隐藏的链接 =====UPDATE wp_postsSET post_content = REGEXP_REPLACE(post_content,'
','')WHERE post_content REGEXP 'position\\s*:\\s*absolute.*left\\s*:\\s*-[0-9]{4}';-- ===== 4. 删除不在白名单域名内的所有外链(最激进,慎用) =====CREATE TABLE wp_posts_backup_20260801 AS SELECT * FROM wp_posts;UPDATE wp_postsSET post_content = REGEXP_REPLACE(post_content,'
执行SQL前必须做的三件事
· 先备份数据库:CREATE TABLE xxx_backup AS SELECT * FROM xxx
· 先在测试站执行:不要在300个站的生产库上直接跑正则替换,先用一个站的备份库验证效果
· 正则表达式不能保证100%准确:黑链代码格式千奇百怪,正则只能处理常见模式,跑完后要抽查
3.2 批量执行 SQL(站群场景)
如果300个站都用同一个数据库服务器,遍历所有数据库执行相同的清理SQL:

#!/bin/bash# 遍历MySQL所有数据库,对每个库的wp_posts表执行清理SQLMYSQL_USER="root"MYSQL_PASS="yourpassword"CLEAN_SQL="UPDATE wp_posts SET post_content = REGEXP_REPLACE(post_content, ']*display\\s*:\\s*none[^>]*>.*?
', '') WHERE post_content LIKE '%display:none%';"DATABASES=$(mysql -u$MYSQL_USER -p$MYSQL_PASS -e "SHOW DATABASES;" | grep -v Database | grep -v information_schema | grep -v performance_schema | grep -v mysql)for db in $DATABASES; doHAS_TABLE=$(mysql -u$MYSQL_USER -p$MYSQL_PASS -e "SHOW TABLES FROM \$db LIKE 'wp_posts';" | wc -l)if [ "$HAS_TABLE" -gt 0 ]; thenecho "Cleaning $db..."mysql -u$MYSQL_USER -p$MYSQL_PASS "$db" -e "$CLEAN_SQL"echo "Done: $db"fidone
3.3 文件层批量清理(sed + Python)
黑链也可能直接写在模板文件、插件文件里。用 sed 批量替换是最直接的方式,但sed 操作文件不可逆,必须先备份:
# 1. 先备份整个站点目录tar -czf /backup/sites_backup_$(date +%Y%m%d).tar.gz /www/wwwroot/# 2. 查找包含黑链的文件(不修改,只看)grep -r -l "http://malicious-domain.com" /www/wwwroot/ --include="*.php" --include="*.html"# 3. sed 批量删除包含特定域名的整行for site in /www/wwwroot/site*; dofind "$site" -name "*.php" -o -name "*.html" | while read file; dosed -i '/malicious-domain\.com/d' "$file"sed -i '/spam-site\.xyz/d' "$file"doneecho "Cleaned: $site"done# 4. 删除 eval(base64_decode(...)) 这样的后门行for site in /www/wwwroot/site*; dofind "$site" -name "*.php" | while read file; dosed -i '/eval(base64_decode(/d' "$file"sed -i '/system($_POST/d' "$file"sed -i '/shell_exec($_GET/d' "$file"donedone
sed 清理的致命陷阱
sed -i '/关键词/d' 会删除整行。如果后门代码和你自己的代码在同一行,你自己的代码也会被一起删掉。所以sed 只适合清理那些单独成行的恶意代码,比如 <?php eval(base64_decode("..."))?> 这种一行一个后门的。如果恶意代码和正常代码混在同一行,必须手工处理。
sed 只能删整行,对于更精细的清理(比如只删除恶意链接但保留正常文字),用 Python 更灵活。核心思路:遍历所有站点目录 → 打开每个 PHP/HTML 文件 → 用正则匹配删除隐藏链接代码块和后门代码 → 自动备份原文件 → 写入清理后的版本。关键正则包括匹配 display:none 包裹的 div 链接块、eval(base64_decode 后门代码、以及包含恶意域名的行。
四、根除阶段:找到后门才能防止复发
很多人清理完黑链就觉得完事了,结果第二天又冒出来了。根因是——后门还在。攻击者留下的 webshell 或定时任务没有清除,他可以随时重新写入黑链代码。
4.1 webshell 常见藏身位置
uploads 目录
wp-content/uploads/ 下面混入了 .php 文件,文件名伪装成图片如 logo.jpg.php 或 favicon.ico.php。查找方式:find uploads/ -name "*.php"
主题/插件目录
正常主题文件中 *** 入了一段混淆代码,或者多了个你不认识的插件。对比 WordPress *** 仓库原始文件或用 Wordfence 扫描。
wp-config.php
配置文件 *** 入恶意代码,这是最隐蔽的方式。重点检查文件末尾有没有多余的 PHP 代码块。
Cron 定时任务
攻击者通过 cPanel 或 SSH 添加了定时任务,定期从远程下载黑链代码。检查:crontab -l 和 WordPress 的 wp-cron。
4.2 文件完整性对比
最可靠的后门定位方式是对比原始文件和当前文件的差异。对于 WordPress 核心文件、主题、插件, *** 仓库都有原始版本:
# 1. 下载同版本WordPress原始包wget https://wordpress.org/wordpress-6.4.zipunzip wordpress-6.4.zip -d /tmp/wp-original/# 2. 对比差异(排除 wp-content 和 wp-config.php)diff -rq /tmp/wp-original/wordpress/ /www/wwwroot/site1/ --exclude=wp-content --exclude=wp-config.php# 3. 查看具体差异diff /tmp/wp-original/wordpress/wp-includes/functions.php /www/wwwroot/site1/wp-includes/functions.php
4.3 清除后门后的加固措施