CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
DevSecOps 入门/课时/检测与 SIEM
RawBlame
课时目录12 节

DevSecOps 入门

  1. 01DevSecOps 概览
  2. 02网络安全基础
  3. 03密码学
  4. 04身份与访问
  5. 05应用安全
  6. 06威胁建模
  7. 07云安全
  8. 08容器安全
  9. 09供应链安全
  10. 10检测与 SIEM
  11. 11Incident 响应
  12. 12合规与扫描

检测与 SIEM

IDS/SIEM 与日志分析。

30 分钟

检测与 SIEM

这一课你将能做到

  1. 解释 SIEM、IDS、IPS、EDR 四者的分工与互补关系
  2. 为本站(Nginx + Spring Boot + MySQL + Redis)设计一套日志收集方案,明确哪些日志必须采集
  3. 写出 3 条可落地的检测规则(暴力破解、异常流量、权限变更),并配置告警

为什么要学

没有 100% 的安全。防火墙会被绕过、漏洞会被发现、凭证会泄漏。问题不是「会不会被攻破」,而是「被攻破后多久能发现」。全球统计:入侵平均驻留时间(dwell time)以「月」计——攻击者在系统里潜伏数月才被发现。

人话:检测是「监控系统」,SIEM 是「把所有监控数据汇总的指挥中心」。没有检测,入侵者在你数据库里拷了三个月数据你都不知道。有了检测,可能 5 分钟内就收到告警并自动封锁。

先建立图像

检测层技术栈:

日志源                    采集                     存储/分析                  响应
─────────────    ──────────────────    ─────────────────────    ──────────────
Nginx access.log  ──┐                                     │
App 应用日志       ──┼──→ Filebeat ──→ Elasticsearch ──→ Kibana │
MySQL binlog      ──┤    (采集)        (索引)          (可视化) │
Redis slowlog     ──┘                                     │
                                                          │
Spring Boot 审计日志 ────────────────────────────┐         │
                                                  │         │
                                        检测规则引擎 ←──────┘
                                        (ElastAlert/Wazuh)
                                                  │
                                                  ▼
                                        告警: Slack/钉钉/邮件
                                        自动化: 封 IP/改密/隔离

关键日志清单(必须采集):

Nginx:
  access.log      —— 谁、什么时间、访问了什么、状态码、User-Agent
  error.log       —— 4xx/5xx 异常、后端超时

Spring Boot:
  application.log —— 登录成功/失败、权限变更、敏感操作
  audit.log       —— 管理员操作审计(不可篡改)
  security.log    —— 401/403、JWT 过期、限流触发

MySQL:
  general log     —— 谁执行了什么 SQL(采样,性能考虑)
  slow log        —— 慢查询(可能是注入扫描)
  binlog          —— 数据变更(溯源)

Redis:
  slowlog         —— 危险命令调用
  monitor         —— 实时命令流(仅诊断时开)

系统:
  auth.log / secure —— SSH 登录成功/失败、sudo 使用
  cron.log          —— 定时任务执行

跟着做

步骤 1:统一日志格式(Spring Boot)

让日志机器可读(JSON),不要靠人眼扫:

<!-- logback-spring.xml -->
<appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
        <includeMdcKeyName>traceId</includeMdcKeyName>
        <includeMdcKeyName>userId</includeMdcKeyName>
    </encoder>
</appender>

自定义 MDC 过滤器注入 userId:

@Component @Order(1) public class UserIdMdcFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null && auth.isAuthenticated()) { MDC.put("userId", auth.getName()); } MDC.put("traceId", UUID.randomUUID().toString().substring(0, 8)); try { chain.doFilter(req, res); } finally { MDC.clear(); } } }

现在日志每行都是 JSON,含 userId、traceId,SIEM 可以直接解析查询。

步骤 2:记录安全事件日志

不要只靠框架默认日志,关键事件显式记录:

@Component
public class SecurityAuditLogger {
    private static final Logger auditLog = LoggerFactory.getLogger("AUDIT");

    public void logLoginSuccess(String username, String ip) {
        auditLog.info("LOGIN_SUCCESS user={} ip={}", username, ip);
    }

    public void logLoginFailure(String username, String ip, String reason) {
        auditLog.warn("LOGIN_FAILURE user={} ip={} reason={}", username, ip, reason);
    }

    public void logAdminAction(String adminUser, String action, String target, String ip) {
        // 管理员操作单独文件,权限收紧
        auditLog.info("ADMIN_ACTION admin={} action={} target={} ip={}",
                      adminUser, action, target, ip);
    }

    public void logPrivilegeChange(String userId, String oldRole, String newRole, String operator) {
        auditLog.warn("PRIV_CHANGE user={} {}→{} by={}", userId, oldRole, newRole, operator);
    }
}

在登录服务里调用:

public String login(String username, String password, String ip) {
    try {
        // ... 验证逻辑 ...
        auditLogger.logLoginSuccess(username, ip);
        return token;
    } catch (BadCredentialsException e) {
        auditLogger.logLoginFailure(username, ip, "bad_credentials");
        throw e;
    }
}

步骤 3:用 Filebeat + Elasticsearch 搭最小 SIEM

docker-compose 最小化部署(测试环境):

version: '3'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false  # 测试环境,生产必开
    ports:
      - "9200:9200"

  kibana:
    image: docker.elastic.co/kibana/kibana:8.12.0
    ports:
      - "5601:5601"

  filebeat:
    image: docker.elastic.co/beats/filebeat:8.12.0
    volumes:
      - ./filebeat.yml:/usr/share/filebeat/filebeat.yml
      - /var/log/nginx:/var/log/nginx:ro        # 采集 Nginx 日志
      - ./logs:/app/logs:ro                     # 采集应用日志
    depends_on:
      - elasticsearch

filebeat.yml:

filebeat.inputs:
  - type: filestream
    paths:
      - /var/log/nginx/access.log
    fields:
      log_type: nginx-access
    parsers:
      - ndjson:  # 如果 Nginx 配了 JSON 格式日志
          target: ""

  - type: filestream
    paths:
      - /app/logs/*.log
    fields:
      log_type: app
    parsers:
      - ndjson:
          target: ""

output.elasticsearch:
  hosts: ["elasticsearch:9200"]

步骤 4:写 3 条检测规则

规则 1:登录暴力破解

# ElastAlert 规则示例 (rules/brute_force.yaml)
name: Login brute force
type: frequency
index: logs-*
num_events: 5                # 5 次失败
timeframe:
  minutes: 1                 # 1 分钟内
filter:
  - term:
      log_type: app
  - term:
      message: "LOGIN_FAILURE"
query_key:
  - ip                       # 按 IP 分组
alert:
  - slack:
      slack_webhook_url: "https://hooks.slack.com/..."

规则 2:管理员操作异常

name: Admin action from unusual IP
type: any
index: logs-*
filter:
  - term:
      message: "ADMIN_ACTION"
  - not:
      term:
        ip: "203.0.113.0/24"   # 办公网 IP 段
alert:
  - email

规则 3:大量 4xx/5xx(可能是扫描器或攻击)

name: Error rate spike
type: spike
index: logs-nginx-*
threshold: 50
timeframe:
  minutes: 5
spike_height: 3             # 错误数是平时的 3 倍
spike_type: up
filter:
  - range:
      status:
        gte: 400
alert:
  - slack

步骤 5:配置告警到钉钉/Slack

# 钉钉机器人告警
alert:
  - "alertmanager"  # 或直接 webhook

关键原则:告警必须可行动。「有人登录了」不是告警(太吵),「同 IP 1 分钟 5 次失败」是告警(该封 IP)。告警要包含:什么、谁、哪里、多严重、下一步建议。

讲清楚要点

  1. IDS 和 IPS 的区别:IDS(入侵检测)只报警,不拦截;IPS(入侵防御)在线路上,实时阻断。现代边界用 IPS(WAF),内部用 IDS(EDR)监控。

  2. SIEM 的核心是关联:单看「登录失败」是噪音,「登录失败 5 次 + 第 6 次成功 + 来自从未见过的国家」是事件。SIEM 把多源日志关联成安全事件。

  3. 日志的完整性比数量重要:如果应用账号能 UPDATE/DELETE 审计日志,攻击者就能抹掉痕迹。审计日志应该是「只追加」——写入后不可改,用 WAL 或独立日志服务保证。

  4. EDR 是主机层的 SIEM:传统 SIEM 看网络流量和应用日志,EDR 看进程、文件、注册表(Windows)/系统调用(Linux)。主机层面检测恶意行为(如奇怪进程注入)。

  5. 告警疲劳是检测系统最大的敌人:100 条告警/天,人会在第 3 天开始全部忽略。只保留高置信度规则,每条告警都必须有明确的响应动作。宁可漏报,不可滥报。

你可能会懵的地方

  • SIEM 一定要买商业产品吗? 不需要。Elastic Stack(ELK)+ ElastAlert + Wazuh(开源 HIDS)就能搭一套覆盖中小企业需求的开源 SIEM。商业产品(Splunk、QRadar)贵在预置规则、技术支持、合规报告。

  • SOAR 是什么? Security Orchestration, Automation and Response——安全编排自动化响应。SIEM 负责「发现」,SOAR 负责「处置」:检测到暴力破解后,SOAR 自动调用防火墙 API 封 IP、给用户发通知、创建工单。是 SIEM 的下一层。

  • 日志要保留多久? 合规要求通常 6 个月到 1 年。分冷热层:最近 30 天热查询(Elasticsearch),历史归档冷存储(S3/OSS + 压缩)。溯源时多数只需要最近几天,别为「1 年前某条日志」花大价钱买热存储。

  • 如何检测内网横向移动? 这是最难的。关键指标:异常 SMB/RDP 连接(工作站之间)、新服务创建、权限提升(普通用户突然有管理员权限)、大量文件访问。EDR 比网络 IDS 更有效。

  • 日志里能不能记密码? 绝对不行。password、token、secret 字段必须在日志输出前脱敏。Spring 里用 @JsonIgnore 或自定义 Logback Pattern 过滤。

错法对照

错法问题正解
只采集错误日志无法溯源正常操作INFO 级别安全事件全采集
日志写本地不收集服务器被攻破后日志被删Filebeat 实时外发
审计日志应用账号可删攻击者抹痕迹只追加,独立账号,定期异地备份
告警规则「登录成功」每天几千条,全部忽略只告警异常模式
日志里有明文密码日志库=密码库脱敏+访问控制
保留 7 天日志入侵数月后发现无法溯源合规要求 180 天+

卡点急救

  1. Filebeat 不采集新日志:检查 Filebeat 进程是否运行、filebeat.yml 路径是否正确、registry 文件是否记录了错误的 offset(删除 /var/lib/filebeat/registry 后重启)。用 filebeat test output 验证 ES 连接。

  2. Elasticsearch 磁盘爆了:配置 ILM(Index Lifecycle Management)自动删除老索引。30 天热数据 + 180 天冷数据,过期自动删。别等磁盘满再处理。

  3. 告警太多不知道哪些是真的:每条告警加「置信度评分」——多个弱信号组合成强信号(失败 5 次 + 新地理位置 + 非工作时间 = 高置信)。单独一条「失败 1 次」不告警。持续调优,目标是每天告警 < 10 条且每条都需要行动。

面试常问

  • SIEM 的核心功能是什么? 三个:① 日志聚合——从防火墙、IDS、应用、主机等多源收集日志到统一平台;② 关联分析——跨源关联事件(如「防火墙拦截 + 登录失败 + 新文件创建」= 入侵尝试);③ 告警与响应——基于规则触发告警,部分支持自动化响应。价值在于「从噪音中发现信号」。

  • IDS 和 IPS 的区别? IDS(入侵检测系统):旁路部署,镜像流量分析,只报警不阻断,对网络性能无影响,误报容忍度高。IPS(入侵防御系统):在线部署,串联在流量路径上,实时阻断恶意流量,但误报会误伤正常业务,性能要求高。边界用 IPS(WAF),内部用 IDS(EDR)。

  • 如何设计一个有效的安全监控规则? ① 高信号低噪音:规则必须指向明确的攻击模式(如「5 次失败登录」而非「1 次失败」);② 上下文关联:结合用户历史行为、IP 信誉、时间异常;③ 可行动:每条告警必须有明确的响应步骤(封 IP/改密/人工排查);④ 定期调优:误报率 >20% 的规则要么改进要么下线。

自测三问

  1. 为什么「登录成功」不是一个好的告警规则?什么组合才是?
  2. 审计日志为什么要「只追加」?如果应用账号能删日志会怎样?
  3. 本站必须采集的 5 类日志是什么?各自检测什么攻击?

小结一句话

检测的本质是承认防御会失败:SIEM 聚合日志发现异常模式、EDR 监控主机行为、告警必须可行动——目标是发现入侵的时间从「月」缩短到「分钟」。

延伸

  • Elastic Security 入门
  • 下一课:Incident 响应——发现入侵后怎么办:遏制、根除、恢复、复盘的完整生命周期。
加载本节练习…
← 上一课供应链安全下一课 →Incident 响应