
核心要点(TL;DR)
- 暗链与WebShell常同源出现,先隔离取证再清理,避免证据被覆盖。
- 按修改时间与异常代码特征双维度排查,比单靠杀毒软件更可靠。
- 清理后必须做文件完整性监控与最小权限加固,否则极易二次入侵。
- 暗链清理后要提交死链与重新抓取,才能恢复搜索排名。
早上打开搜索资源平台,发现站点标题被改成了赌博词,快照里全是外链;登录服务器一看,首页底部多了一串display:none的链接,某个upload.php的修改时间还是凌晨三点。暗链和 WebShell 往往是一起出现的:前者负责 SEO 劫持变现,后者负责长期控制。只删页面代码,几小时后就会复发。本文按「隔离取证 → 定位入口 → 清除后门 → 清理暗链 → 防篡改落地」五步给出可执行命令与检查清单,照着做能一次清干净。
先隔离取证,别急着删文件
发现异常后第一反应往往是直接改文件,这会把攻击者的写入痕迹一起抹掉。正确顺序是先降低影响面,再保留证据。
- 切断写入通道:把站点切到维护页,或在 Nginx 层对可疑路径返回 403,避免继续被写入。
- 保留现场:对 Web 根目录做一次快照,例如
tar -czf /tmp/webroot-$(date +%F).tar.gz /var/www/html,同时导出近 7 天 access_log。 - 记录关键信息:
last、lastb、crontab -l、cat /etc/passwd的输出全部留存,便于后续判断是否有提权。
取证阶段不要重启服务,内存中的进程信息(如 ps auxf 看到的异常父进程)重启后就没了。
定位入口:从修改时间和代码特征双维度排查
WebShell 的典型特征是「近期被修改」+「包含危险函数组合」,单看任何一项都容易漏报或误报。
按时间筛出可疑文件
# 找出近 7 天被修改的 php 文件
find /var/www/html -type f -name "*.php" -mtime -7 -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort
# 按修改时间排序取最近 20 个
find /var/www/html -type f -name "*.php" -printf '%T@ %p\n' | sort -rn | head -20
按特征匹配后门
grep -rnE "eval\(|assert\(|base64_decode\(|gzinflate\(|str_rot13\(|$_(POST|GET|REQUEST)\[[^]]+\]\)" \
/var/www/html --include="*.php" | grep -v vendor/
命中结果不要直接删,逐个打开确认。常见伪装包括:图片目录下的 .php 文件、正常类文件末尾追加的一行 @eval($_POST['x']);、以及被改写的 index.php 首行。
交叉验证访问日志
# 统计对单个 php 文件的 POST 请求量
awk '{print ,}' access.log | grep POST | sort | uniq -c | sort -rn | head -20
如果某个平时没人访问的文件出现大量 POST,基本可以确认是 Webshell 通信点。
清除后门与暗链
确认入口后按「先断控制、再清内容」的顺序处理。
- 删除或隔离后门文件:先
mv到隔离目录而非直接rm,便于复盘;同时检查同目录是否有伴随文件。 - 排查持久化:检查
crontab -l、/etc/cron.*、~/.ssh/authorized_keys、/etc/rc.local,确认没有计划任务定时回写。 - 清理暗链:暗链常见位置是模板 footer、
index.php尾部、数据库wp_options或文章表。用grep -rn "display:none" /var/www/html和grep -rn "<a href" --include="*.php"定位,数据库侧按可疑域名检索。 - 重置凭据:后台密码、数据库密码、FTP/SSH 密钥全部更换,避免攻击者用已窃取凭据再次进入。
| 检查项 | 命令/位置 | 预期结果 |
|---|---|---|
| 异常计划任务 | crontab -l | 无可疑 curl/wget 回连 |
| SSH 后门公钥 | ~/.ssh/authorized_keys | 仅本人密钥 |
| Web 目录属主 | ls -l /var/www/html | 非 www 用户可写 |
| 隐藏链接 | grep display:none | 无批量外链 |
防篡改落地:让下一次写入立刻被发现
清理只是止血,防复发靠的是「改不了 + 改了就告警」。建议按以下三层落地:
- 权限层:Web 进程以低权限用户运行,代码目录对运行用户只读;上传目录禁止执行 PHP(Nginx 中对 upload 路径
location ~ \.php$ { deny all; })。 - 监控层:用 AIDE 或 inotifywait 监控 Web 根目录,任何新增/修改文件立即告警。例如
inotifywait -mrq -e modify,create,delete /var/www/html。 - 发布层:代码变更走 CI 发布,禁止线上直接编辑;发布后自动比对文件哈希,与基线不一致即回滚。
如果不想自己搭这套监控,AegisX 的网站防篡改与文件完整性监控能力可以直接覆盖上述监控层与告警联动,省去自建 inotify 加告警通道的维护成本。
清理后验证清单
- 全站 grep 危险函数,确认无残留后门;
- 访问首页与关键页面,确认无隐藏外链、无跳转;
- 观察 24 小时,文件监控无异常回写;
- 搜索资源平台提交死链、更新 sitemap 并申请重新抓取;
- 复盘日志,确认入侵入口已封堵(弱口令、过期插件、上传漏洞)。
行动建议:今天先做两件事——给 Web 目录加只读权限,把文件完整性监控跑起来。暗链可以删,但只有把写入通道堵死,网站才算真正安全。
常见问题(FAQ)
网页被植入暗链,只删掉暗链代码就够了吗?
不够。暗链通常由WebShell或计划任务自动写回,只删页面代码往往几小时内复发。正确做法是先定位写入入口(WebShell、被篡改的模板、弱口令后台),清除控制通道后再清理暗链,最后加文件完整性监控验证不再回写。
怎么快速判断服务器上是否存在WebShell?
可用find按修改时间筛出近期变更的脚本文件,再用grep匹配eval、assert、base64_decode、system等危险函数组合,结合access_log中POST到单文件的高频请求交叉验证。没有绝对可靠的单条命令,建议多特征叠加并人工复核可疑文件。
网站被黑后需要重装系统吗?
视入侵深度而定。若确认仅Web目录被写入且未发现提权、计划任务、SSH公钥等持久化痕迹,彻底清理并加固即可;若发现rootkit、异常账号或系统级后门,建议备份数据后重装系统并重置全部凭据,成本更低也更彻底。
防篡改落地最有效的手段是什么?
优先做文件完整性监控加只读部署:用inotify或AIDE监控Web目录变更并告警,静态资源与代码发布走CI而非线上直接改,Web进程以低权限运行且对代码目录无写权限,三者结合能阻断绝大多数篡改。
暗链清理后网站排名多久能恢复?
没有固定周期,取决于清理彻底程度与外链质量。清理后应提交死链、更新sitemap并在搜索资源平台申请重新抓取,同时观察快照是否更新。若暗链长期存在导致站点被降权,通常需要数周到数月逐步恢复,期间保持内容正常更新。