服务器被黑的瞬间,大多数人第一反应是懵的。登录不上、CPU 拉满、网站被篡改、数据库被删,屏幕上跳出一串英文勒索信。我之前带团队处理过不少这类事故,也见过太多因为慌乱乱删文件、重启服务器,导致证据丢失、损失扩大的案例。如果你自己管着服务器,或者公司业务跑在云上,这篇东西就是为你准备的。我把它拆成 8 个实操步骤,从紧急隔离到查杀清理,再到加固复原,基本都是可以直接照做的流程。不管你是刚入行的运维,还是接手了公司服务器开发的小程序员,按这个顺序走,能少踩很多坑。
先说清楚,服务器“被黑”这件事本身不可怕,可怕的是处置顺序错了。很多人一看到服务器异常,第一件事就是 SSH 登上去敲命令,这是最忌讳的。你上去一通操作,可能把攻击者留下的痕迹全踩没了,后面想溯源、想恢复都无从谈起。正确做法是:先隔离,再取证,后清理,最后加固。下面这 8 个操作,就是围绕这条主线展开的。
1. 被黑后的第一反应,决定了你接下来的工作量
1.1 先判断损失,而不是先翻日志
我见过最典型的错误场景:运维发现服务器异常,马上 SSH 进去执行 top,看到 CPU 100%,顺手就把那个可疑进程 kill 了。结果呢?第二天又出现同样的进程,而且这次连 top 都看不到了,因为攻击者已经装了 rootkit,专门隐藏自己的进程。
所以第一步不是动手,而是判断损失范围。你需要快速回答几个问题:这台服务器是纯计算节点,还是跑着业务和数据库?有没有重要的用户数据?是否有备份?备份时间是什么时候?如果这台机器是你唯一的服务器,且没有备份,那处理方式和有完整备份的机器完全不一样——前者要先考虑保全数据,后者可以直接考虑重装系统。
这时候建议你在云厂商的控制台操作,而不是在服务器内部操作。因为服务器内部可能已被攻击者植入了各种后门,你在里面执行的每个命令、看到的每个结果,都可能是伪造的。在控制台界面上给磁盘做快照,或者直接创建一份自定义镜像,相当于把当前状态完整拷贝出来,这是后续分析取证的基础。
1.2 处理决策树:隔离 vs 修复 vs 重建
判断完损失后,需要做一个关键决策:这台服务器到底是修,还是直接重装?
我的经验是,如果服务器上跑的是可重新部署的无状态服务(比如 Nginx 前端、构建节点),直接重装系统,再把代码从 Git 仓库拉下来跑起来,是效率最高、最彻底的办法。因为攻击者可能已经在系统里埋了很多你根本找不出来的东西,光靠手动清理,风险很高。
但如果服务器上有不可替代的数据,或者你没法确认代码仓库是最新的,那就必须走“隔离-取证-清理-修复”的路线。无论哪种选择,第一步都必须是隔离:在云控制台上,把服务器从公网断开,或者通过安全组规则把入方向流量全部拒绝,只保留你自己的管理 IP。这一步非常关键——不断开网络,攻击者可能还在远程盯着你这台机器,你清理的同时他还可以继续写入新的后门,甚至把你清到一半的文件重新传回来。
注意:隔离不是简单关掉服务器。云服务器直接关机,有些数据盘可能没来得及同步,而且重启后内存里的证据就丢了。正确做法是先在控制台做快照,再断开公网,保留业务系统继续运行,方便取证。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 8 个应急排查操作,一个比一个关键
2.1 操作一:快照、断网、隔离三件套
这里重点说说快照怎么做,以及为什么顺序不能乱。
以阿里云为例,登录控制台,找到目标实例,点击“磁盘”选项卡,对系统盘和数据盘分别创建快照。快照说白了就是磁盘某个时间点的完整副本,跟你手机里的照片备份一个道理——记录的是那一刻的磁盘状态。做完快照后,立刻修改安全组规则:把入方向的 22、80、443 等端口全部拒绝,只保留 0.0.0.0/0 出方向(如果业务完全中断没关系,现在不是保业务的时候,是保数据的时候)。
如果你的服务器不在云上,而是物理机,那就直接拔网线。别觉得好笑,物理机被黑后,网线一拔比什么都管用。如果是在机房托管的机器,联系机房值班人员协助断网即可。
做完这步,你已经把攻击者挡在门外了。接下来就是在“安静”的机器上做排查。
2.2 操作二:查登录记录、异常账号和后门登入入口
很多攻击者是通过 SSH 暴力破解进来的,也有的是利用了某个应用的漏洞拿到 shell。不管哪种方式,系统里都会留下痕迹。这一步的目标是搞清楚“谁进来了”“从哪进来的”。
执行下面的命令,一条一条看:
bash复制# 查看成功登录记录
last
# 查看所有用户最近登录位置
lastlog
# 查看登录失败记录,看有没有暴力破解
lastb
last 输出里会出现一串 IP 和登录时间。比对一下你的日常运维记录,如果有你不知道的登录时段和异地 IP,基本可以确认失陷。这时候先把 /var/log/secure(CentOS)或 /var/log/auth.log(Ubuntu)打开,重点看 SSH 登录相关的日志,里面有攻击者的源 IP 和尝试过的用户名。
接着检查系统账号:
bash复制# 列出所有普通用户
cat /etc/passwd
# 看哪些用户有 UID 0(root权限)
awk -F: '$3==0{print $1}' /etc/passwd
# 查看有 sudo 权限的用户
cat /etc/sudoers
攻击者常用的套路是:添加一个 UID 为 0 的用户,比如 support、sysadmin、test 之类的名字,看起来像是系统账号,但实际上是最高权限。也会往 root 用户的 authorized_keys 文件里写入自己的公钥,实现免密登录。所以 authorized_keys 必须检查:
bash复制cat /root/.ssh/authorized_keys
正常情况这个文件你是不会主动改的,里面每一行都要确认是自己生成和认可的。发现陌生公钥,先别急着删,记录下来再清理。另外也要检查 /etc/ssh/sshd_config,看看有没有被改过端口、有没有开 PermitRootLogin。我之前遇到一个案例,攻击者把 SSH 端口从 22 改成了 22222,然后自己连进来,管理员反而被锁在外面。
2.3 操作三:切断攻击者当前的活跃连接
排查完账号,接下来处理“正在进行中的”攻击行为。你要看看当前还有谁连着这台机器:
bash复制# 查看所有网络连接,尤其是 ESTABLISHED 状态的
ss -antp
这条命令会列出所有 TCP 连接,重点看 “ESTABLISHED” 和 “SYN_RECV” 状态的连接。如果某个连接来自国外 IP 或者动态 IP,而且连着的是 22 端口、MySQL 端口等,基本就是攻击者的实时会话。用 ss 输出里的 PID,直接把对应进程杀掉,或者用 pkill 结束会话:
bash复制# 踢出所有登录用户
pkill -u 用户名
# 杀掉某个 PID
kill -9 PID
注意:kill -9 是强制杀死进程,普通业务进程可能来不及保存状态就被中断,所以在执行前要区分清楚。我自己习惯先用 who 看当前登录用户,用 w 看他们在跑什么命令,再决定踢哪个。
这一步做完,攻击者的实时会话被切断,但系统里的后门还在。所以别指望杀一个进程就结束,后面的每一步都要做。
2.4 操作四:揪出正在运行的恶意进程
这是整个排查过程最耗精力的环节。攻击者通常会挂一个挖矿程序、反弹 shell、或者 HTTP 代理程序在你的服务器上,靠它来赚钱或者扫描内网。
先看资源消耗:
bash复制top -c
按 P 键按 CPU 排序,按 M 键按内存排序。看到占用接近 100% 的进程,记下 PID。然后看进程的详细信息:
bash复制# 查看进程的完整启动命令
ps aux | grep PID
# 查看进程对应的可执行文件
ls -l /proc/PID/exe
# 查看进程的工作目录及其打开的配置文件
ls -l /proc/PID/cwd
这几条命令很有用。恶意程序经常藏在 /tmp、/var/tmp、/dev/shm、/usr/lib 这些目录里。比如 /proc/12345/exe 指向 /tmp/xx,基本可以确定是挖矿木马。确认后先别急着 kill,先把它启动的完整命令记录到本地文件里,再把父进程、关联进程都拎出来:
bash复制# 查看进程树
pstree -ap
# 查看进程打开的端口,确认是否有对外连接
lsof -p PID
全部记录完之后,再 kill -9 进程。为什么强调记录?因为在应急响应里,证据链很重要。万一后面要报警、要找攻击者留下来的线索,这些信息就是最原始的凭证。
2.5 操作五:按时间轴清理恶意文件
进程清掉之后,恶意程序的文件还留在磁盘里。如果放任不管,下次重启或者某个条件触发,可能又被重新拉起。这一节就是帮你把“病根”挖出来。
按时间找最近被修改过的文件:
bash复制# 查找最近 7 天被修改过的文件
find / -mtime -7 -type f > /tmp/recent_files.txt
# 查找最近 1 小时被修改的,紧急情况用
find / -mmin -60 -type f > /tmp/urgent_files.txt
拿到文件列表之后,重点看这几个目录:/tmp、/var/tmp、/dev/shm、/usr/bin、/usr/sbin、/bin、/sbin、/etc/init.d、/etc/systemd/system。恶意程序喜欢藏在这种目录里,因为普通用户也会用到,不容易引起注意。
如果你跑的是 Nginx、Apache、Tomcat 这类 Web 服务,一定要检查网站根目录。攻击者常往里塞 webshell,比如一个 PHP 文件,里面只有几行代码,看起来像图片,但实际能执行任意命令:
bash复制# 找 PHP 文件里可疑的危险函数
grep -r "eval\|assert\|base64_decode\|system\|exec" /var/www/html/
这一步要特别仔细。有时候 webshell 被压缩、混淆过,用 grep 只能命中一部分,最好的办法是把整个 web 目录打包下载到本地,用工具扫描。在服务器上不要装太多不信任的工具,因为在你系统已被入侵的前提下,下载到本地的工具也可能被替换。把可疑文件下载到本地后用杀毒软件或者在线沙箱分析,是更稳妥的做法。
2.6 操作六:计划任务和自启动入口大扫除
恶意程序想活得久,必须有“开机自启”或“定时拉取”的机制。最常见的藏身处是 crontab,也就是计划任务。
bash复制# 查看当前用户的计划任务
crontab -l
# 查看系统的计划任务
cat /etc/crontab
# 查看所有 cron 目录下的任务
ls -la /etc/cron.d/
cat /etc/cron.d/*
恶意程序常在这里写一条定时任务,每过几分钟就去某个 URL 下载一个脚本并执行。所以你看 crontab 的时候,看到有 wget、curl 加一串奇怪的 URL,几乎可以断定是中招了。有些木马还会把日志写成空文件、把注释符号写在任务前面来混淆视听,比如 # 开头的行要留意是不是被做了手脚,别以为注释掉就安全了。
除了 cron,还有 systemd 服务:
bash复制# 列出所有开机自启的服务
systemctl list-unit-files --state=enabled
# 查看 systemd 的 unit 文件,注意 /etc/systemd/system 下的
ls -la /etc/systemd/system/
攻击者会在 /etc/systemd/system/ 下建一个名字很正常的 service,比如 systemd-update.service,内容是执行某个恶意脚本。比较隐蔽,因为 systemctl list-unit-files 里能显示,但名字不像可疑文件,容易被忽略。还有一种情况是 rc.local:
bash复制cat /etc/rc.local
CentOS 6 时代的老套路了,到现在还有人用。确保这里面没有加东西。
2.7 操作七:网络端口和后门检测
恶意程序清得差不多了,还要确认服务器没有留下容易再次被入侵的后门。这一步侧重于网络层。
bash复制# 查看所有监听端口
netstat -lntp
# 或者用 ss
ss -lntp
对比一下你已知的服务监听端口。正常来说,一台 Linux 服务器监听 22、80、443、3306 这些就差不多了。如果冒出一个 6666、8888、9090 之类的端口,且对应的进程名字很怪,那多半是木马在监听,等待攻击者远程连接。
防火墙规则也要检查:
bash复制iptables -L -n
# 或 firewalld
firewall-cmd --list-all
看看有没有被添加奇怪的端口转发规则——攻击者可能把你服务器当跳板,把外部的流量转发到内网,或者反过来。
SSH 后门是另一个重灾区。除了检查 authorized_keys,还要检查 alias 命令是否被篡改。有些后门会改掉 ps、ls、netstat 这些命令本身,让你看不到真实情况。为了绕过这种“命令替换”,检查时可以调用系统的完整路径:
bash复制/bin/ps aux
/bin/netstat -lntp
/usr/bin/lsof -i
如果这些命令的输出和之前用短命令 ps aux 看到的完全不一样,说明命令本身已经被替换过,系统的二进制文件已经被污染,最稳妥的做法是直接重装系统。另外,用 chkrootkit 或 rkhunter 扫描一下 rootkit,虽然它们不是百分百准确,但能辅助发现已知的隐藏后门:
bash复制# CentOS
yum install chkrootkit -y && chkrootkit
# Ubuntu
apt install chkrootkit -y && chkrootkit
2.8 操作八:加固、复原与长效盯防
所有恶意的东西清理干净之后,修复才算完成了一半。接下来要把系统加固到“不轻易再被打进来”的水平。
按优先级排列,这六件事是必须做的:
- 修改所有账号密码:包括 root、所有普通用户、数据库密码、Web 后台密码。密码要求长且随机,不要用 123456、admin888 这种。建议用密码生成器生成 20 位以上混合密码。如果服务器有多个运维人员共管,建议使用密钥登录并关闭密码登录。
- 配置 SSH 安全策略:把
PermitRootLogin改成no,把默认端口改掉(不等于安全,但能减少扫描噪音),启用密钥登录。有条件的话,在安全组限只允许你自己的办公 IP 访问 22 端口。 - 防火墙收口:只放行业务必须的端口,其余全部拒绝。用安全组或 iptables 都行。云上最方便的还是安全组,效果等同于一台硬件防火墙。
- 升级相关软件:检查 Nginx、Apache、MySQL、PHP、Redis 等组件有没有官方安全通告里提到的漏洞。攻击者能进来,大概率是有漏洞可以利用,不补上等于留了门。
- 安装监控与告警:至少要在服务器上装一个 fail2ban(自动封禁暴力破解 IP),并在云厂商控制台开启云监控。CPU、内存、带宽超过阈值时给你发短信/邮件。有条件的话,把关键日志发送到集中式日志平台,方便回溯。
- 定期备份:快照策略要开,代码仓库必须完整,数据库每天自动备份并保留至少 7 天到独立存储。我见过很多公司,被黑之后才发现备份也放在同一台服务器上,结果一起被删了,这才是真正的灾难。
完成这六件事,再把业务恢复上线。上线后第一天要密切关注监控曲线和登录日志,正常情况下,尝试暴力破解的扫描流量还会持续一段时间,但真正的攻击者如果发现自己后门被清了,可能会换一个姿势再试。所以至少盯一周。
3. 常见问题速查:症状、原因、处置对照表
3.1 实战中最高频的 5 类情况
处置完不代表就一定能彻底干净。我整理了实战里最常遇到的几种情况,你可以对照着快速定位。
| 症状 | 可能原因 | 处置建议 |
|---|---|---|
| CPU 突然跑满,top 看到奇怪进程 | 挖矿木马 | kill 进程后马上清 cron 和自启动项,再排查二进制是否被替换 |
| 无法登录,提示密码错误 | 密码被改,或 SSH 服务被替换 | 用云厂商网页 VNC 登录,重置密码,检查 sshd 配置并恢复 |
| 网站页面被篡改,或跳转到其他网站 | Web 目录被改,存在 webshell | 全量检查 web 目录,下载代码对比 Git 仓库,修复程序漏洞 |
| MySQL/数据库文件被加密,出现勒索提示 | 勒索病毒 | 留存证据,尝试从离线备份恢复;不要轻易付赎金 |
| 服务器对外发送大量流量,带宽被占满 | 被植入 DDoS 发包工具或代理程序 | 断网隔离,查对外连接进程,清理后收紧防火墙 |
很多朋友会问:我清理完之后,有没有可能哪天又复发?答案是可能。因为你可能漏掉了一个比较深的系统级后门,比如内核模块级别的 rootkit。这也是为什么我一直强调:如果这台机器上的业务可以用代码仓库和自动化脚本重新部署,重装系统永远比“清理”更彻底。清了一个小时木马,以为干净了,结果攻击者留下一个内核模块,平时根本探不出来,过两周又回来了——这个成本远比重装高。
3.2 用“验证清单”确认服务器是否真的干净
清理完成后,先在服务器上跑一遍自查脚本,确认常用的后门入口都已封死:
bash复制# 1. 检查所有 UID 为 0 的账户
awk -F: '$3==0{print $1":"$7}' /etc/passwd
# 2. 检查空密码账户
awk -F: '($2==""){print $1}' /etc/shadow
# 3. 检查 authorized_keys 有没有新增
find / -name "authorized_keys" -exec cat {} \;
# 4. 检查 crontab 有没有异常任务
for user in $(cut -f1 -d: /etc/passwd); do crontab -u $user -l 2>/dev/null; done
# 5. 检查监听端口是否有可疑服务
ss -lntup | grep -v "127.0.0.1"
上面列的是最基础的验证项。如果这些都通过了,再观察 24 到 48 小时。期间保持日志完整记录,不要随意清理 /var/log 下的文件。如果 48 小时后没有异常连接、没有新增长文件、CPU 和带宽保持正常,那基本可以判定清理成功。
还要提醒一句:建议更换密钥对。如果你用的是云服务器,并在控制台上传过密钥,而攻击者可能拿到了私钥,那密钥也要重新生成。之前遇到一个客户,服务器被黑后只改了密码,没换密钥,结果第二天又被进去了。因为攻击者已经下载了 /root/.ssh/id_rsa,用那对密钥去连接,即使密码改了也没有用。
做应急响应这些年,我最大的体会就是:被黑之后的第一个小时,比之后所有时间加起来都重要。只要你手上有一套流程,按着步骤一步步来,大多数攻击者留下的东西都能处理掉。可如果平时连备份都没有,那不管多熟练的运维都得捏把汗。
我还有一个小建议:平时每个月抽半小时,在测试服务器上故意模拟一次“服务器被入侵”的场景,演练快照、断网、查日志、清木马这一套流程。等你真的遇到事故那天,这套肌肉记忆会帮你省掉大量时间,也能尽量降低业务中断时长。希望这篇东西能在你需要的时候派上用场。
