# Linux Endpoint Introduction(Linux 端点基础 / 入门)

# 01_Linux Applications and Daemons

# 1.1 基础概念:应用程序与守护进程 (Daemons)

在 Linux 系统中,程序主要分为两类:

  • 前台应用程序:需要用户交互,依附于特定的终端(TTY)会话运行。
  • 守护进程 (Daemons):在后台独立运行的系统服务,通常没有控制终端,生命周期贯穿系统运行期间。其命名习惯上常以字母 d 结尾(如 sshd , cron , apache2 , mysqld )。

# 1.2 蓝队视角:日志在 Linux 安全防御中的核心地位

对于蓝队(防御方)而言,日志是入侵检测、事件响应和数字取证的基石。

  • 行为可见性:日志记录了系统状态变化、用户登录、服务启停及网络活动,是还原攻击链的唯一可靠依据。
  • 抗抵赖性:完善的日志审计机制可追踪到具体操作的用户、时间和来源。
  • 防御挑战:攻击者在获取权限后,通常会优先尝试清除或篡改本地日志(如清空 /var/log/auth.log 或使用 history -c )。因此,日志的集中化收集(如发送至远程 SIEM/Syslog 服务器)和完整性保护是防御的关键。

# 1.3 守护进程的交互与管理

现代 Linux 发行版主要使用 systemd 作为初始化系统和服务管理器(取代了传统的 SysVinit)。

  • 状态检查systemctl status <service_name> (例如: systemctl status sshd
  • 启动 / 停止 / 重启systemctl start|stop|restart <service_name>
  • 重载配置systemctl reload <service_name> (在不中断当前连接的情况下重新读取配置文件,常用于 Nginx/Apache)
  • 发送信号:传统方式可通过 kill -HUP <PID> 通知守护进程重新加载配置。

# 1.4 核心日志文件与检查方法

Linux 系统的日志通常集中存储在 /var/log/ 目录下。安全分析师需重点关注以下文件:

日志文件适用发行版记录内容与安全价值
auth.log / secureDebian/Ubuntu / RHEL/CentOS最重要。记录所有身份验证事件(SSH 登录成功 / 失败、 sudo 提权、PAM 模块活动)。
syslog / messagesDebian/Ubuntu / RHEL/CentOS记录系统级常规信息、内核消息及大部分守护进程的运行状态。
daemon.logDebian/Ubuntu专门记录后台守护进程的运行日志。
btmp通用记录失败的登录尝试。需使用 lastb 命令读取,而非文本编辑器。
wtmp通用记录成功的登录、注销及系统重启历史。需使用 last 命令读取。

常用日志检查命令

# 实时追踪日志更新 (如监控 SSH 爆破)
tail -f /var/log/auth.log
# 筛选特定关键字 (如查找 sudo 提权记录)
grep "sudo" /var/log/auth.log
# 查看失败的登录尝试
lastb
# 查看历史登录记录
last

# 1.5 现代日志管理组件

Linux 的日志架构通常由两部分协同工作:

  1. systemd-journald (现代标准)

    • 特点:收集来自内核、系统启动早期阶段、标准输出 (stdout/stderr) 及 syslog 的日志。默认存储为二进制格式(位于 /run/log/journal//var/log/journal/ ),无法直接用 cat 查看。
    • 查询工具journalctl
      journalctl -u sshd          # 查看特定服务的日志
      journalctl -f               # 实时追踪 (类似 tail -f)
      journalctl --since "1 hour ago" # 按时间范围过滤
      journalctl -p err           # 仅查看错误及以上级别的日志
  2. rsyslog (传统 / 兼容性标准)

    • 特点:基于规则的日志守护进程,负责将 journald 或其他来源的日志过滤并写入到 /var/log/ 下的纯文本文件中,或转发至远程日志服务器。
    • 配置文件/etc/rsyslog.conf/etc/rsyslog.d/ 目录下的规则文件。
    • 安全加固:在生产环境中,常配置 rsyslog 将关键日志(如 auth.* )实时通过网络 (UDP/TCP) 发送至集中的日志服务器,以防本地日志被攻击者销毁。

# 02_Daemons

# 2.1 守护进程 (Daemon) 的核心概念

在 Linux 系统中,守护进程(Daemon) 是一种在后台独立运行、持续提供特定服务或执行特定任务的特殊进程。

与前台进程 / 图形化进程的区别:

  • 无控制终端 (TTY):守护进程在启动时通常会脱离父进程,并与其控制终端(如用户登录的 Shell)断开连接。这意味着即使用户注销或关闭终端,守护进程依然会在后台持续运行。
  • 非交互式:它们不需要用户的直接输入,也不会在屏幕上显示标准的输出信息(stdout/stderr 通常被重定向到 /dev/null 或特定的日志文件)。
  • 命名特征:在 Linux 中,守护进程的名称通常习惯性地以字母 d 结尾,以表明其 Daemon 身份(例如: sshd , crond , httpd , mysqld )。
  • 与图形化进程对比:图形化进程(如浏览器、GUI 文本编辑器)依赖于 X11 或 Wayland 等显示服务器,需要与用户进行图形界面交互;而守护进程纯粹在系统底层运行,服务于系统本身或其他网络请求。

# 2.2 守护进程的功能与作用

Linux 系统之所以能提供丰富的网络、安全和自动化功能,完全依赖于在后台默默运行的众多守护进程。它们的核心作用包括:

  1. 网络服务监听:如 Web 服务器 ( nginx , apache2 )、数据库 ( mysqld )、SSH ( sshd ),它们持续监听特定端口,等待并处理客户端的网络请求。
  2. 系统任务调度:如定时任务 ( crond ),负责在后台按计划执行系统维护或用户指定的脚本。
  3. 硬件与系统管理:如网络管理 ( NetworkManager )、日志记录 ( rsyslogd )、电源管理等,确保底层硬件和系统组件的协同工作。

# 2.3 经典案例:SSH 守护进程 ( sshd )

sshd (Secure Shell Daemon) 是 Linux 系统中最核心的守护进程之一,负责处理所有远程 SSH 登录请求。

工作机制:

  • 后台监听sshd 启动后,会在后台静默运行,并默认监听 TCP 22 端口。
  • 并发处理:当有客户端尝试连接时,主 sshd 进程会 fork(派生)出一个子进程来专门处理该用户的会话,而主进程继续留在后台监听新的连接。
  • 安全基石:如果 sshd 停止运行,管理员将无法通过 SSH 远程登录和管理该服务器(只能通过物理控制台或云平台的 VNC 访问)。

# 2.4 守护进程的生命周期管理 ( systemd )

现代 Linux 发行版使用 systemd 作为初始化系统和服务管理器。 systemctl 是其核心命令行工具,用于控制守护进程的状态。

1. 检查守护进程状态

# 查看 sshd 的当前运行状态
systemctl status sshd

预期输出(当服务关闭时):

● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
     Active: inactive (dead) since Sat 2022-03-05 10:00:00 UTC; 1min ago
       Docs: man:sshd(8)
             man:sshd_config(5)
    Process: 1234 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
   Main PID: 1235 (code=exited, status=0/SUCCESS)

分析要点Active: inactive (dead) 明确表示该守护进程当前处于停止状态。

2. 启动守护进程

# 启动 sshd 服务 (需要 root 或 sudo 权限)
sudo systemctl start sshd

3. 再次检查状态验证

systemctl status sshd

预期输出(当服务成功启动后):

● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2022-03-05 10:01:30 UTC; 5s ago
       Docs: man:sshd(8)
             man:sshd_config(5)
    Process: 1500 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
   Main PID: 1501 (sshd)
      Tasks: 1 (limit: 4661)
     Memory: 2.5M
        CPU: 45ms
     CGroup: /system.slice/ssh.service
             └─1501 sshd: /usr/sbin/sshd -D [listener] 0 of 10 startups

分析要点

  • Active: active (running) 证明守护进程已成功启动并在后台运行。
  • Main PID: 1501 显示了该守护进程在系统中的进程 ID。
  • CGroup 展示了该进程及其子进程的层级关系。
  • 日志部分( Mar 05 10:01:30 ... Server listening on 0.0.0.0 port 22. )直接印证了 sshd 正在执行其核心功能 —— 监听网络端口。

# 03_Logging on Linux and the Syslog Framework

# 3.1 日志基础与结构分析

在 Linux 中,系统和服务的运行状态、用户操作及网络活动都会被记录在日志文件中。以 SSH 服务为例,通过查看原始日志可以清晰地还原系统事件。

查看 SSH 相关日志:

sudo grep sshd /var/log/secure

原始日志条目示例与结构拆解:

Oct 31 16:28:07 linux02 sudo: offsec : TTY=pts/0 ; PWD=/home/offsec ; USER=root ; COMMAND=/bin/systemctl start sshd
Oct 31 16:28:07 linux02 sshd[3621]: Server listening on 0.0.0.0 port 22.
Oct 31 16:31:28 linux02 sshd[3703]: Accepted password for offsec from 192.168.50.50 port 45382 ssh2
Oct 31 16:31:28 linux02 sshd[3703]: pam_unix(sshd:session): session opened for user offsec by (uid=0)

标准 Syslog 消息结构解析:

  1. Timestamp(时间戳)Oct 31 16:28:07 (月 日 时:分: 秒)。
  2. Hostname(主机名)linux02 (生成该日志的机器名称)。
  3. Process [PID](进程名与进程 ID)sshd[3621]sudo (标识产生日志的具体进程)。
  4. Message(消息内容):具体的事件描述(如 Accepted password... 表示密码验证成功)。

# 3.2 Syslog 框架与 rsyslog 远程转发

Linux 的日志收集主要由 rsyslog 守护进程负责。其核心配置文件位于 /etc/rsyslog.conf

查看并理解远程日志转发配置:

tail /etc/rsyslog.conf

配置片段解读:

# Remote Logging (we use TCP for reliable delivery)
# remote host is: name/ip, e.g. 192.168.0.1, port optional e.g. 10514
# Forwarding to remote syslog collectors
#*.* @linux01   # 使用 UDP 协议转发所有日志 (单 @)
#*.* @@linux01  # 使用 TCP 协议转发所有日志 (双 @,更可靠)
  • 安全价值:在生产环境中,攻击者获取权限后通常会尝试清空本地日志(如 rm -rf /var/log/* )。通过配置 @@ 将日志实时转发至远程集中日志服务器(SIEM/Syslog Server),可以确保日志证据的持久性和抗篡改性。

应用配置变更:
修改配置文件后,必须重启服务使其生效:

sudo systemctl restart rsyslog

# 3.3 日志格式变化深度解析 (PRI 字段)

启用远程转发(或调整相关模板)后,再次查看日志,会发现格式发生了变化:

sudo tail /var/log/secure | grep sshd

输出示例:

<86>Oct 31 16:36:51 linux02 sshd[3919]: Accepted password for offsec from 192.168.50.50 port 45384 ssh2

关键细节: <86> 是什么?
这是 Syslog 协议(RFC 5424/3164)标准的 PRI (Priority) 字段。当 rsyslog 准备将日志通过网络发送或按照标准格式输出时,会计算并附加此值。

  • 计算公式PRI = Facility * 8 + Severity
  • 本例解析:SSH 日志属于 authpriv (Facility = 10),级别为 info (Severity = 6)。
  • 计算10 * 8 + 6 = 86 。因此日志头部出现了 <86> 。理解此机制有助于在编写 SIEM 解析规则时准确提取日志级别。

# 3.4 核心安全日志文件与实战分析

Linux 的日志通常集中存储在 /var/log/ 目录下。不同发行版的默认日志文件命名略有差异(Debian/Ubuntu 系 vs RHEL/CentOS 系)。

1. 身份验证日志 ( /var/log/secure/var/log/auth.log )
记录所有涉及身份验证的事件,是蓝队排查 SSH 爆破、 sudo 滥用的核心文件。

实战:排查 SSH 登录失败(爆破痕迹)

sudo cat /var/log/secure | grep "Failed password"

输出示例:

<86>Oct 31 16:38:33 linux02 sshd[4011]: Failed password for offsec from 192.168.50.50 port 45386 ssh2
  • 分析要点:通过提取 Failed password 后的源 IP 地址( 192.168.50.50 )和目标用户名( offsec ),可以快速统计爆破频率,并结合 iptablesfail2ban 进行自动化封禁。

2. 其他关键日志文件速查:

  • /var/log/syslog (Debian) / /var/log/messages (RHEL):记录系统全局常规信息。
  • /var/log/daemon.log :专门记录后台守护进程的运行状态。
  • /var/log/kern.log / dmesg :记录内核级日志(如硬件错误、OOM Killer 杀进程、加载恶意内核模块)。
  • /var/log/wtmp/var/log/btmp :二进制文件,分别使用 last (成功登录)和 lastb (失败登录)命令查看。

# 04_Rsyslog Meets Journal

# 4.1 现代 Linux 日志架构:Journald 与 Rsyslog 的协同

在现代 Linux 发行版中,日志收集通常由两个组件协同完成:

  1. systemd-journald (第一捕获者):作为 systemd 的一部分,它是系统启动后最早运行的日志守护进程。它负责收集来自内核 (kmsg)、系统启动早期阶段、标准输出 (stdout/stderr) 以及传统 syslog 的所有日志,并将其存储为高效的二进制格式(位于 /var/log/journal/ )。
  2. rsyslog (传统格式化与转发者):负责读取 journald 收集到的日志,将其转换为传统的纯文本格式写入 /var/log/ 目录下的特定文件(如 /var/log/secure ),或根据规则通过网络转发至远程 SIEM / 日志服务器。

验证进程与文件关联:

# 查找 rsyslogd 进程并确认其正在写入 /var/log/secure
sudo lsof -p $(pgrep rsyslogd) | grep '/var/log/secure'

# 4.2 Rsyslog 核心配置解析

/etc/rsyslog.conf 决定了 rsyslog 如何获取和处理日志。

#### MODULES ####
# 提供对本地系统日志记录的支持(例如通过 logger 命令)
# SysSock.Use="off" 表示不通过 /run/systemd/journal/syslog 套接字读取
module(load="imuxsock" SysSock.Use="off") 
# 核心模块:允许 rsyslog 直接从 systemd-journald 读取日志
# StateFile 用于记录读取进度,防止服务重启后日志丢失或重复读取
module(load="imjournal" StateFile="imjournal.state")
# 提供 UDP/TCP syslog 接收能力(用于集中式日志收集)
# module(load="imudp")
# input(type="imudp" port="514")
# module(load="imtcp")
# input(type="imtcp" port="514")

# 4.3 实战:日志查询与安全分析

通过对比传统文本日志和 journalctl ,可以验证两者的数据一致性。

1. 查看传统安全日志 ( /var/log/secure )

sudo tail /var/log/secure

关键安全事件提取:

  • 密码认证失败sshd[10891]: Failed password for offsec from 192.168.50.50 port 35638 ssh2 (潜在的暴力破解或凭据猜测)。
  • PAM 认证失败passwd[6055]: pam_unix(passwd:chauthtok): authentication failure (用户尝试修改密码但原密码输入错误)。
  • 特权提升 (Sudo)sudo[10822]: offsec : TTY=pts/0 ; PWD=/home/offsec ; USER=root ; COMMAND=/bin/lsof... (记录了低权限用户执行高权限命令的完整上下文)。

2. 使用 Journalctl 查询特定服务日志
由于 journald 是结构化存储,查询效率更高,且支持强大的时间和服务过滤:

# 仅查询 sshd.service 在过去 1 小时内的日志
journalctl -u sshd.service --since "1 hour ago"

输出结果与 /var/log/secure 中的 SSH 相关条目完全一致,证明 rsyslog 成功从 journald 同步了数据。

# 4.4 深度实验:切断日志流 ( imjournal 的影响)

操作:在 /etc/rsyslog.conf 中注释掉 module(load="imjournal" StateFile="imjournal.state") ,然后重启 rsyslog ( sudo systemctl restart rsyslog ),并尝试新的 SSH 登录。

现象
新的 SSH 登录 / 失败记录依然会出现在 journalctl -u sshd.service 中,但不会再追加到 /var/log/secure 文件中。

原理解析与安全启示

  1. 依赖断裂:由于配置中 imuxsockSysSock.Use 已被设为 offrsyslog 失去了通过套接字读取日志的备用通道。注释掉 imjournal 后, rsyslog 彻底断开了与 systemd-journald 的数据源连接。
  2. 日志黑洞journald 仍在默默记录一切,但负责将日志持久化为文本或转发到远程服务器的 rsyslog 变成了 “瞎子”。
  3. 攻击者视角:这是一种高级的 “日志规避” 技术。如果攻击者获取了 root 权限,他们无需删除日志文件(这会留下明显的文件修改时间戳异常),只需注释掉 imjournal 或破坏 rsyslog 配置,就能在不触发文件完整性监控 (FIM) 的情况下,使后续的恶意活动不再被记录到传统的审计日志或发送至远程 SIEM 中。
  4. 蓝队防御:必须对 /etc/rsyslog.conf 等核心日志配置文件实施严格的文件完整性监控 (FIM),任何未经授权的修改都应立即触发最高级别的安全告警。
[系统各个部件/程序] 
       │ (产生日志信件)
       ▼
┌──────────────────────────────────────────────┐
│  1. systemd-journald (总收件前台)             │
│  - 第一时间接收所有信件                          │
│  - 存成二进制“电子档案” (/var/log/journal/)  │
└──────────────────────┬───────────────────────┘
                       │
                       │ (通过 imjournal 模块拉取/分拣)
                       ▼
┌──────────────────────────────────────────────┐
│  2. rsyslogd (档案分拣与派送员)               │
│  - 从前台那里把信件抄写下来                    │
│  - 翻译成普通人看得懂的“纯文本”                │
└──────────────────────┬───────────────────────┘
                       │
       ┌───────────────┴───────────────┐
       ▼                               ▼
[写入本地文本文件]              [发送给远端 SIEM/日志服务器]
/var/log/secure (安全日志)      ( SOC 安全监控中心 )
/var/log/messages (系统日志)

# 05_Web Daemon Logging

# 5.1 基础概念与日志位置

Web 守护进程(如 Apache httpd / apache2 或 Nginx)是外部攻击的首要目标。其访问日志(Access Log)和错误日志(Error Log)是检测 Web 攻击(如目录遍历、SQL 注入、暴力破解)的核心数据源。

  • RHEL/CentOS 路径/var/log/httpd/access_log/var/log/httpd/error_log
  • Debian/Ubuntu 路径/var/log/apache2/access.log/var/log/apache2/error.log

# 5.2 日志格式解析:CLF 与 Combined

Apache 默认使用 CLF (Common Log Format,通用日志格式) 或其扩展版 Combined Log Format (组合日志格式)

CLF 标准结构%h %l %u %t "%r" %>s %b
示例条目

192.168.50.50 - offsec [01/Nov/2021:19:52:05 +0000] "GET /admin/config.php HTTP/1.1" 403 287

字段拆解

  1. %h (Remote Host): 192.168.50.50 (客户端 IP 地址)
  2. %l (Remote Logname): - (通常为空,因现代浏览器不发送 ident 信息)
  3. %u (Remote User): offsec (如果请求需要 HTTP Basic Auth,则显示认证用户名,否则为 - )
  4. %t (Time): [01/Nov/2021:19:52:05 +0000] (请求到达服务器的时间)
  5. "%r" (Request Line): "GET /admin/config.php HTTP/1.1" (HTTP 方法 + 请求 URI + 协议版本)
  6. %>s (Status Code): 403 (服务器返回的 HTTP 状态码,如 200, 301, 403, 404, 500)
  7. %b (Bytes Sent): 287 (返回给客户端的响应体大小,不含 HTTP 头)

注:Combined 格式会在末尾追加 %{Referer}i (来源页面) 和 %{User-Agent}i (客户端浏览器 / 工具标识),这对识别自动化扫描器(如 sqlmap, nikto)至关重要。

# 5.3 实战:命令行日志分析技巧

在应急响应或日常巡检中,熟练使用 grepawksort 等文本处理工具能快速从海量日志中提取威胁情报。

场景 1:排查 403 Forbidden (禁止访问) 异常请求
攻击者在尝试访问受限目录或敏感文件(如 .git , wp-config.php )被拒绝时,会产生大量 403 记录。

# 使用 grep 快速过滤包含 "403" 的行(前后加空格避免匹配到 URI 中的 403)
grep " 403 " /var/log/httpd/access_log
# 或使用 awk 精确匹配第 9 个字段(状态码)
awk '$9 == 403' /var/log/httpd/access_log

场景 2:提取并统计高频访问的 URI
攻击者在进行目录爆破或漏洞扫描时,会对特定路径发起海量请求。提取 URI 并统计频率可快速定位被重点攻击的端点。

# 1. awk '{print $7}' 提取第 7 个字段(即 Request URI,如 /admin/config.php)
# 2. sort 对提取出的 URI 进行排序
# 3. uniq -c 统计每个 URI 出现的次数
# 4. sort -nr 按次数进行数字降序排列
# 5. head -n 10 仅显示排名前 10 的最频繁请求
awk '{print $7}' /var/log/httpd/access_log | sort | uniq -c | sort -nr | head -n 10

输出示例

1542 /wp-login.php
   312 /admin/
    45 /index.html

分析价值:如果 /wp-login.php 出现异常高频的访问,且伴随大量 401/403 状态码,即可高度怀疑正在遭受 WordPress 登录页面的暴力破解攻击。

# 06_Automating the Defensive Analysis

# 6.1 手动分析的局限性

在前面的章节中,我们学习了如何通过命令行工具(如 grep , awk , journalctl )手动检查 Linux 系统日志和 Web 访问日志。虽然这些方法对于单点排查事后取证非常有效,但在真实的蓝队防御和大规模企业环境中,纯手动分析面临着巨大的瓶颈:

  • 数据量级庞大:现代系统每秒产生数以万计的日志事件,人眼和简单的文本搜索无法在海量噪音中发现微弱的攻击信号。
  • 缺乏实时性:手动巡检通常是滞后的(如定期抽查或事件发生后),无法满足安全运营对 “实时检测” 和 “快速响应(降低 MTTR)” 的要求。
  • 数据孤岛:手动分析通常局限于单台主机的本地日志,难以跨主机、跨网络层进行全局的关联分析(例如:将 Web 日志中的注入尝试与数据库日志中的异常查询关联起来)。
  • 人力成本高昂:无法实现 7x24 小时的不间断监控,容易因疲劳导致漏报。

# 6.2 自动化防御分析的必要性

为了应对高级持续性威胁(APT)和自动化攻击工具,防御方必须将日志分析过程自动化。自动化分析的核心目标是将安全团队从繁琐的 “日志翻阅” 中解放出来,使其能够专注于高价值的威胁狩猎(Threat Hunting)事件响应(Incident Response)

# 6.3 自动化分析的技术演进路线 (本章导读)

接下来,我们将探讨如何从 “手动敲击命令” 过渡到 “构建自动化防御体系”。这一演进通常包含以下几个关键阶段和技术栈:

  1. 脚本化与定时任务 (Scripting & Cron)

    • 使用 Bash 或 Python 编写自动化解析脚本,提取关键安全指标。
    • 结合 cron 定时任务,定期生成安全报表或自动执行缓解措施(如结合 fail2ban 自动封禁爆破 IP)。
  2. 日志集中化与聚合 (Log Centralization)

    • 利用 rsyslog 或轻量级采集器(如 Filebeat, Fluentd, Promtail)将分散在各个端点(Linux 主机、Web 服务器、网络设备)的日志统一收集到中心节点,打破数据孤岛。
  3. SIEM 与日志分析平台 (SIEM & Log Management)

    • 引入安全信息和事件管理(SIEM)系统或现代日志栈(如 Splunk, ELK Stack/Elastic Security, Wazuh, Graylog)。
    • 实现海量日志的索引、全文检索、可视化仪表盘(Dashboards)以及跨数据源的复杂关联分析。
  4. 规则引擎与实时告警 (Rule Engine & Alerting)

    • 编写或导入检测规则(如 Sigma 规则),当系统行为匹配已知的攻击特征(如短时间内大量 SSH 登录失败、Web 目录遍历、异常的 sudo 提权)时,自动触发高优先级的安全告警,并通过邮件、即时通讯工具或 Ticket 系统通知安全团队。

# 07_Python for Log Analysis

# 7.1 为什么使用 Python 进行日志分析

虽然 grepawk 等命令行工具在快速检索时非常高效,但在面对复杂的日志结构、需要多条件关联分析或跨平台兼容时,Python 凭借其强大的正则表达式( re 模块)丰富的数据结构以及跨平台特性,成为了自动化日志解析和构建安全分析脚本的首选语言。

# 7.2 实战脚本 1:SSH 日志解析器

该脚本用于提取 SSH 守护进程( sshd )的相关日志。为了兼容不同的 Linux 发行版,脚本同时定义了 RHEL/CentOS 和 Debian/Ubuntu 的默认日志路径,并通过 os.path.isfile 自动过滤掉不存在的路径。

(注:已修复原笔记中的缩进错误、拼写错误 shh 及语法截断问题)

#!/usr/bin/env python3
import re
import os.path
# 定义不同发行版的 SSH 日志路径
centos_ssh_log_file_path = "/var/log/secure"
ubuntu_ssh_log_file_path = "/var/log/auth.log"
ssh_log_files = [centos_ssh_log_file_path, ubuntu_ssh_log_file_path]
# 正则表达式:匹配包含 sshd [数字 PID] 的行
regex = r'sshd\[\d+\]'
for log_file in ssh_log_files:
    # 自动判断并跳过不存在的日志文件,实现跨发行版兼容
    if os.path.isfile(log_file):
        print(f"[*] Parsing {log_file}...")
        with open(log_file, "r") as file:
            for line in file:
                # 使用 re.search 查找行内是否包含匹配项
                if re.search(regex, line):
                    print(line, end='')

# 7.3 实战脚本 2:Apache 访问日志解析器

该脚本用于解析 Apache 的 Combined Log Format(组合日志格式)。通过正则表达式的捕获组 () ,将一行复杂的日志拆解为 IP、时间、请求、状态码、User-Agent 等独立字段,便于后续的统计分析或告警判断。

(注:已修复变量名拼写错误 Togshh ,优化了正则表达式以精准匹配 CLF 格式,并去除了重复匹配的逻辑)

#!/usr/bin/env python3
import re
import os.path
# 定义不同发行版的 Apache 访问日志路径
centos_apache_log_file_path = "/var/log/httpd/access_log"
ubuntu_apache_log_file_path = "/var/log/apache2/access.log"
apache_log_files = [centos_apache_log_file_path, ubuntu_apache_log_file_path]
# 正则表达式:匹配 Combined Log Format
# 捕获组依次为:1.IP, 2. 时间,3. 请求行,4. 状态码,5. 字节数,6.Referer, 7.User-Agent
regex = r'^(\S+) \S+ \S+ \[(.*?)\] "(.*?)" (\d+) (\d+) "(.*?)" "(.*?)"'
for log_file in apache_log_files:
    if os.path.isfile(log_file):
        print(f"[*] Parsing {log_file}...")
        with open(log_file, "r") as file:
            for line in file:
                # 使用 re.match 从行首开始匹配
                match = re.match(regex, line)
                if match:
                    # .groups () 返回包含所有捕获组的元组
                    log_data = match.groups()
                    
                    # 提取关键字段进行格式化输出
                    ip = log_data[0]
                    status = log_data[3]
                    user_agent = log_data[6]
                    
                    print(f"IP: {ip:<15} | Status: {status} | UA: {user_agent}")

# 7.4 进阶优化:动态识别操作系统与日志路径

正如笔记中提到的:“日志文件不一样还需要根据系统判断应该从哪个路径读”。虽然上述脚本通过遍历所有可能路径并用 os.path.isfile 过滤已经解决了兼容性问题,但在更严谨的工程实践中,我们可以主动探测操作系统类型,从而直接锁定正确的路径,减少不必要的文件 I/O 操作。

优化方案:使用特征文件探测发行版

import os
import platform
def get_log_paths(service="ssh"):
    """根据操作系统类型动态返回正确的日志路径"""
    
    # 探测是否为 RedHat/CentOS 系 (通过特征文件判断)
    is_rhel = os.path.exists('/etc/redhat-release') or os.path.exists('/etc/centos-release')
    # 探测是否为 Debian/Ubuntu 系
    is_debian = os.path.exists('/etc/debian_version')
    
    if service == "ssh":
        if is_rhel:
            return ["/var/log/secure"]
        elif is_debian:
            return ["/var/log/auth.log"]
            
    elif service == "apache":
        if is_rhel:
            return ["/var/log/httpd/access_log"]
        elif is_debian:
            return ["/var/log/apache2/access.log"]
            
    # 如果无法识别,则返回所有可能的路径作为 Fallback (兜底)
    if service == "ssh":
        return ["/var/log/secure", "/var/log/auth.log"]
    elif service == "apache":
        return ["/var/log/httpd/access_log", "/var/log/apache2/access.log"]
        
    return []
# 使用示例
target_logs = get_log_paths("ssh")
print(f"[*] Detected OS requires parsing: {target_logs}")

# 08_DevOps Tools & Ansible Automation

# 8.1 DevOps 与自动化安全概述

DevOps 是一种结合了软件开发(Dev)和 IT 运维(Ops)的文化与实践,旨在通过自动化 “基础设施即代码(IaC)” 和 CI/CD 流程,缩短系统开发生命周期。
在安全与日志分析领域,DevOps 理念延伸为 DevSecOps。安全团队利用自动化工具(如 Ansible、Terraform)来批量部署安全基线、集中收集日志、自动化运行威胁狩猎脚本,从而将安全能力无缝集成到日常运维中,大幅降低人工操作的成本和出错率。

# 8.2 Ansible 基础概念

Ansible 是一款开源的 IT 自动化引擎,广泛用于配置管理、应用部署和任务自动化。

  • 无代理架构(Agentless):Ansible 不需要在目标主机上安装客户端软件,仅通过 SSH(Linux)或 WinRM(Windows)进行通信。
  • Playbook:Ansible 的核心配置文件,使用 YAML 格式编写。它定义了要在目标主机上执行的一系列 “任务(Tasks)”,具有极强的可读性。

# 8.3 验证 Ansible 连通性 (Inventory & Ping)

在执行复杂的 Playbook 之前,必须先验证控制节点(Kali)与受控节点(soc200 组内的主机)之间的 SSH 连通性及 Python 环境。

测试命令:

# 使用指定的 SSH 私钥和用户,对 soc200 主机组执行 ping 模块测试
kali@attacker01:~/SOC-200/Linux_Endpoint_Introduction$ ansible soc200 -m ping -u offsec --key-file=/home/kali/.ssh/ansible_rsa

(注:已修复原笔记中 -u offsec--key-file 之间缺失空格的问题)

输出解析:

192.168.50.12 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
192.168.50.13 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
  • 安全 / 运维提示:Ansible 的 ping 模块不是发送 ICMP 网络包,而是通过 SSH 登录目标机器,检查其是否安装了 Ansible 运行所必需的 Python 解释器(如输出中的 /usr/bin/python3 )。返回 "ping": "pong" 表示主机已准备好接收自动化指令。

# 8.4 编写自动化日志分析 Playbook

接下来,我们将之前编写的 Python 日志解析脚本 ( ssh_log_parser.py ) 封装到 Ansible Playbook 中,实现跨多台主机的批量日志分析。

log_parser.yml 内容:

---
- name: Automated SSH Log Parser
  hosts: soc200                # 指定目标主机组(需在 inventory 文件中定义)
  tasks:
    - name: Execute SSH log parser script on remote hosts
      become: yes              # 启用提权
      become_user: root        # 提权至 root 用户(读取 /var/log/secure 需要权限)
      script: /home/kali/SOC-200/Linux_Endpoint_Introduction/ssh_log_parser.py
      args:
        executable: python3    # 指定使用 python3 执行脚本
      register: script_output  # 将脚本的标准输出注册为变量 script_output
    - name: Display parsed log output
      debug:
        var: script_output.stdout_lines  # 格式化打印脚本输出的每一行

# 8.5 执行 Playbook 与结果分析

通过 ansible-playbook 命令下发并执行自动化任务。

执行命令:

# 执行 playbook,指定用户、SSH 密钥,并使用 -K 提示输入 sudo 密码(用于 become 提权)
kali@attacker01:~/SOC-200/Linux_Endpoint_Introduction$ ansible-playbook log_parser.yml -u offsec --key-file=/home/kali/.ssh/ansible_rsa -K

执行流程与预期输出:

  1. Gathering Facts:Ansible 收集目标主机的系统信息。
  2. Task 1 (Execute script):Ansible 通过 SFTP 将 ssh_log_parser.py 临时传输到远程主机的随机临时目录,使用 python3 执行,捕获输出后自动清理临时文件。
  3. Task 2 (Display output):将捕获到的 SSH 日志内容(如登录成功 / 失败记录)以结构化的列表形式打印在控制台的终端上。

自动化价值总结:
通过这种模式,安全分析师无需再逐台 SSH 登录服务器手动执行 greppython 脚本。只需一条命令,即可在几秒钟内完成数十台甚至上百台 Linux 主机的日志收集与初步解析,极大地提升了安全事件响应(IR)和日常巡检的效率。

# 09_Hunting for Login Attempts

# 9.1 命令行基础排查 (grep)

在进行初步的威胁狩猎或事件响应时,使用 grep 快速过滤 SSH 认证日志是最直接的方法。

1. 狩猎成功的 SSH 登录

sudo cat /var/log/secure | grep "Accepted password"

输出示例:

Nov 1 05:17:10 linux02 sshd[1638]: Accepted password for offsec from 192.168.48.5 port 38448 ssh2

2. 狩猎失败的 SSH 登录 (暴力破解痕迹)

sudo cat /var/log/secure | grep "Failed password"

输出示例:

Nov 1 19:52:05 linux02 sshd[10891]: Failed password for offsec from 192.168.50.50 port 35638 ssh2

# 9.2 Python 自动化日志狩猎脚本

为了在多台主机或大规模日志中实现自动化分析,我们将上述 grep 逻辑封装为 Python 脚本。该脚本能够自动识别操作系统类型,读取对应的日志文件,并分类输出成功与失败的登录事件。

(注:已修复原笔记中的缩进错误、变量拼写错误 shh 、正则表达式语法错误 * 修正为 .* ,以及 print 语句的语法缺失)

#!/usr/bin/env python3
import re
import os.path
# 定义不同发行版的 SSH 日志路径
centos_ssh_log_file_path = "/var/log/secure"
ubuntu_ssh_log_file_path = "/var/log/auth.log"
ssh_log_files = [centos_ssh_log_file_path, ubuntu_ssh_log_file_path]
# 修正后的正则表达式:
# \d+ 匹配数字 PID,.* 匹配中间的空格和任意字符,确保精准定位到 Accepted/Failed password
regex_valid_login = r'sshd\[\d+\].*Accepted password'
regex_failed_login = r'sshd\[\d+\].*Failed password'
for log_file in ssh_log_files:
    # 自动跳过不存在的日志文件,实现跨平台兼容
    if os.path.isfile(log_file):
        with open(log_file, "r") as file:
            for line in file:
                # 使用 re.search 进行单行匹配,比 finditer 更高效
                if re.search(regex_valid_login, line):
                    print("[*] Valid SSH Login found:\n\t" + line.strip())
                if re.search(regex_failed_login, line):
                    print("[!] INVALID SSH Login found:\n\t" + line.strip())

# 9.3 脚本逻辑解析与安全价值

  1. 跨平台兼容性:通过遍历 ssh_log_files 列表并结合 os.path.isfile() ,脚本能够无缝运行在 RHEL/CentOS ( /var/log/secure ) 和 Debian/Ubuntu ( /var/log/auth.log ) 系统上,无需手动修改路径。
  2. 正则表达式优化:使用 sshd\[\d+\].* 替代原有的 sshd\[.*\]*\d+ 确保只匹配合法的数字 PID, .* 正确处理了 PID 与状态信息之间的空格和任意字符,避免了正则匹配失败或误报。
  3. 安全分析价值
    • 异常登录检测:通过提取 [*] Valid SSH Login 中的源 IP,可以排查是否存在非工作时间的异常登录或来自未知 IP 的凭据窃取。
    • 暴力破解预警:通过统计 [!] INVALID SSH Login 的出现频率和源 IP 分布,可以快速识别针对 SSH 服务的字典攻击或暴力破解行为,并为后续配置 fail2ban 或防火墙封禁提供数据支撑。