搜索全站
报错排查 10 分钟阅读

网站被攻击或故障时的应急流程:止损、取证、恢复与复盘

站点被打不开、被挂马、被篡改时该先做什么?本文给出一套五步应急流程:断网止损、快照取证、定位入口、干净恢复、加固复盘,附可直接执行的排查命令。

U
UFO_PF 2017-04-23 · 阅读 10 分钟
网站 报错排查
阅读提示
本文约 3,791 字,预计阅读 10 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:最怕的不是被黑,是慌乱中把证据删了

站点出事的那一刻,人的第一反应通常是”赶紧修好”。于是登录后台删掉可疑文件、回滚一下、重启服务器,站点恢复了,长舒一口气。两周后同样的事情再来一次,而且更严重——因为你从来没搞清楚攻击者是从哪个口子进来的,第一次的”修复”只是在打扫现场,门还开着。

更常见的问题是现场被破坏。有人发现被挂马后第一件事是删掉马文件,结果唯一能告诉你攻击入口的线索(文件创建时间、关联的上传记录、WebShell 的通信地址)全部消失。也有些人第一时间恢复备份,却没保留被污染的现场快照,事后无法复盘,也无法判断有没有数据泄露。应急处理的核心原则是:先止损、再取证、后恢复、最后复盘,顺序不能颠倒。本文按这个顺序讲清每一步做什么、跑什么命令。

原理分析:先分清是”故障”还是”入侵”

两类事件的处置路径完全不同,第一步必须先判断。故障的典型表现是:站点 502/504、数据库连不上、磁盘满、CPU 打满、插件更新后白屏。入侵的典型表现是:页面被跳转到陌生站点、前台出现博彩/药品内容、后台多了陌生管理员账号、搜索引擎提示”此网站可能已被黑客入侵”、服务器出现未知进程、邮件被大量外发。

判断的关键证据有几处:wp-content/uploads/ 下是否出现 .php 文件(正常上传目录不应有可执行脚本)、wp-admin 或 wp-includes 里是否有近期被修改的文件、数据库 wp_options 表里的 siteurl/home 是否被改、以及是否出现非官方的定时任务(WP-Cron 里的陌生 event)。

现象 更可能的原因 第一动作
502/504、打不开 资源耗尽、PHP-FPM 挂了、磁盘满 看错误日志,别急着重装
白屏(更新后) 插件/主题冲突、PHP 版本不兼容 重命名插件目录
跳转到陌生站点 文件被篡改或数据库被注入 JS 全站文件校验
前台多出垃圾内容 被写入大量垃圾文章 查后台账号与发布记录
后台多出管理员 账号泄露或注册功能被利用 立即停用并审计
服务器 CPU 长期 100% 被植入挖矿脚本、被 CC 查进程与外连

保姆级实操

  1. 第一步:止损,把损失范围固定住

这一步的目标是”不再继续恶化”,而不是修复。做法:把站点切到维护页(Nginx 返回 503 或直接放一个静态 maintenance.html);如果是数据库被篡改,先锁库只读;如果服务器被用作挖矿/发包,先断外网(保留内网以便取证)。同时把所有密码改一遍:服务器 SSH、数据库、WordPress 管理员、FTP、主机面板——改密码前先确认新密码不复用旧密码。

  1. 第二步:取证,先复制再动手

在改任何东西之前,把三样东西完整保存下来:整站文件(打包)、数据库导出、以及最近 7 天的 Web 访问日志与 PHP 错误日志。这一步的产出是后续所有分析的基础:

# 1) 打包整站文件(保留时间戳,便于按时间定位)
tar -czpf /root/backup-site-$(date +%F).tar.gz /var/www/html

# 2) 导出数据库(不要只导出单表)
mysqldump -u root -p --single-transaction --routines mimangfei > /root/db-$(date +%F).sql

# 3) 找出最近 7 天内被修改过的 php 文件(挂马最常伪装在这里)
find /var/www/html -type f -name "*.php" -mtime -7 -printf "%T@ %TY-%Tm-%Td %TH:%TM  %p\n" | sort -rn

# 4) 上传目录里不该有 php,全部列出来
find /var/www/html/wp-content/uploads -type f -name "*.php" -ls

# 5) 用 WP-CLI 校验核心文件完整性(与官方 checksum 比对)
wp core verify-checksums

# 6) 访问日志里找可疑的 POST 请求(WebShell 通常会带特征参数)
awk '$6 ~ /POST/ {print $1, $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -40

# 7) 查按 IP 统计请求数,识别 CC 或扫描来源
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
  1. 第三步:定位入口

按优先级排查四个入口:一是过期的插件/主题(最常见),看有没有超过一年未更新的商业插件;二是弱口令(admin/123456 之类),查日志里 wp-login.php 的失败记录;三是服务器上的其他站点(同服务器旁的站点被攻破后跨目录);四是备份文件泄露(/backup.sql、www.zip 放在 web 根目录下可被直接下载)。用 wp core verify-checksums 确认核心干净,再用上面第 3、4 条命令定位具体文件。

  1. 第四步:干净恢复

不要”修修补补”,直接干净恢复:用被入侵前的一个干净备份还原(先确认那个备份本身是干净的——用同样的校验命令扫一遍)。如果备份不可用,则从官方重新下载 WordPress 核心包覆盖 wp-admin 与 wp-includes,重新安装所有插件与主题(从官方源下载,不要用”备份里的老版本”),数据库则逐表检查后导入。恢复后立刻:重置所有用户密码、重新生成 wp-config.php 里的 AUTH_KEY 等盐值(这会让所有已登录会话失效)、删除并重建 salt 后通知用户重新登录。

  1. 第五步:加固与复盘

加固动作清单:目录权限设为文件 644、目录 755,wp-config.php 设为 600 或 440;在 Web 服务器层禁止 uploads 目录执行 PHP;后台加双因素认证;限制 wp-login.php 的访问频率;关闭文件编辑(DISALLOW_FILE_EDIT);安装安全插件(Wordfence、Sucuri 或 Defiant 系)做持续扫描。

<?php
// wp-config.php 中建议常开的两项
define( 'DISALLOW_FILE_EDIT', true );   // 禁止后台编辑主题/插件文件
define( 'WP_DEBUG', false );            // 生产环境关闭调试输出,避免泄露路径
define( 'FORCE_SSL_ADMIN', true );      // 后台强制 HTTPS
# Nginx:禁止上传目录执行 PHP(加在 server 块内)
location ~* ^/wp-content/uploads/.*\.php$ {
    deny all;
    access_log off;
    log_not_found off;
}

# 隐藏备份与敏感文件
location ~* \.(sql|bak|old|zip|tar|gz|log)$ {
    deny all;
}
  1. 写一份事故报告

内容是:什么时候发现的、现象是什么、影响范围(有无数据泄露、停机时长)、根因是什么、做了什么、还剩什么没做。这份报告决定了后续会不会再犯。

常见踩坑

  • 发现被黑后立刻删除马文件:现场证据消失,永远不知道入口在哪,必然二次被黑。
  • 案例:某站点前台被跳转到博彩站,运维在后台把主题文件”恢复默认设置”后跳转消失,两天后再次被挂马,如此反复四次。后来用 wp core verify-checksums 加文件时间排查,发现是一个已停用但未删除的两年前的旧插件里的 upload-handler.php 被反复写入——停用不删除的插件同样是活的后门。
  • 恢复到”最近一次备份”而不验证备份是否干净:备份里同样有马,恢复完立刻复发。
  • 只改 WordPress 密码,没改服务器和数据库密码:攻击者从 SSH 进来,改 WP 密码毫无意义。
  • wp-config.php 权限 777:同服务器的其他站点可直接读取数据库账号。
  • 生产环境开着 WP_DEBUG:报错信息把绝对路径、数据库名直接展示给访客。
  • 恢复后没重新生成 AUTH_KEY:已窃取的登录 cookie 依然有效。

总结

应急的判断标准是”能不能说清根因”。说不出来的处置都只是打扫现场。正确的顺序永远是:止损 → 取证 → 定位入口 → 干净恢复 → 加固复盘,其中取证一步最容易被跳过,也最关键。日常要做的就是两件低成本的事:每周一次异地备份并定期验证可恢复、给后台加双因素认证。把这两项做好,再配合 网站维护年费与续费管理清单 里的监控告警,大部分事故能在造成损失前被发现。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。