ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

安全数据分析实战:从日志接入到异常检测与监控可视化

安全数据分析实战:从日志接入到异常检测与监控可视化 1. 内容整体设计与思路拆解1.1 为什么安全数据分析在2020年成了硬需求先说个背景。很多人提到奇安信第一反应是卖防火墙、卖终端的厂商这其实只是产品层面的认知。到了2020年这个时间节点安全行业已经明显从卖盒子转向卖运营能力而运营能力的核心就是数据分析。每天从防火墙、入侵检测、终端EDR、漏洞扫描、邮件网关、DNS解析这些系统里滚出来的日志动辄几十亿条靠人工去翻已经完全不现实。我记得当时我们这边有个很典型的场景一个中大型客户每天产生大约40TB的安全日志其中告警就有几百万条。安全运营团队一共五六个人就算一个人一整天不吃不喝只看告警也只能看完不到十分之一。这种情况下真正有价值的攻击行为基本被淹没在海量告警里。说白了安全数据分析的核心问题不是有没有数据而是能不能从数据里快速找到那几条真正需要人处理的威胁线索。所以2020年我们做这套数据分析及应用目标非常明确把分散在不同设备里的安全日志统一收起来通过离线批处理和实时流计算两条链路做加工产出一批能直接指导安全运营的分析模型和可视化报表让运营人员从翻日志变成看结论。1.2 我们最终确定的技术选型思路技术选型这块2020年其实可选的东西已经很多了。我们内部对比过几套方案最终敲定的组合是Kafka做消息缓冲Spark做离线批处理Flink做实时流计算Elasticsearch做检索和存储HDFS做冷数据归档可视化统一走Grafana加自研的Web报表。为什么这么选我可以展开说下背后的考量。Kafka在当时的生态成熟度最高几乎没有团队不会用而且它能很好的承接各种设备日志的接入解决数据源五花八门的问题。Spark选它是因为我们大量的分析任务是T1的比如统计前一天有多少台机器外联了恶意域名、某个账户是否存在异常登录规律这类任务用Spark SQL写起来非常直接而且Spark对HDFS的支持非常成熟数据落地上没那么多幺蛾子。Flink则专门用来处理实时告警降噪和在线风险评分因为这两块对延迟敏感等不了批任务跑完。ES在这个架构里的角色经常被低估。很多人把ES只当搜索引擎用但实际上在安全数据分析场景ES的聚合分析能力非常关键。比如运营人员想快速查一下某个IP在过去7天都访问了哪些目标端口用ES的聚合查询几秒钟就能出结果如果用Spark去跑一个小查询反而很浪费时间。我们当时的策略是能用ES聚合解决的查询型分析就直接查ES重计算型分析才走Spark和Flink这种分层思路大大缓解了计算资源的压力。关于可视化的选择多说一句。Grafana的优势是接入数据源方便建仪表盘速度快适合做运维监控类的实时面板。但安全分析报表有很多是复杂表格、多维度下钻、自定义筛选Grafana的交互还是偏弱所以我们做了一层自研的Web报表系统底层直接查ES的聚合接口效果会灵活很多。后面的可视化部分我会详细讲。2. 核心细节解析与实操要点2.1 数据接入阶段最容易踩的坑字段归一化做数据分析的人都知道一个定律垃圾进垃圾出。安全日志的杂乱程度比普通业务日志更严重。不同厂商的设备同一种日志类型的字段命名完全不同。比如同样是源IP有的叫src_ip有的叫source_address有的叫sip有的干脆把IP和端口放在一个字段里写成了10.10.1.2:5566。我们当时做接入层的时候统计过一份数据源的字段差异清单仅仅是源IP这一个字段就有7种不同的写法。这还不算IP格式不统一的问题比如IPv6地址有的带括号、有的用冒号分隔、有的还带着zone ID。如果这些原始数据直接入湖后面分析的时候光是清洗就要占用三分之一的时间。所以我们在接入层做了一个标准化动作统一叫字段归一化。具体做法是维护一个字段映射规则表把每种数据源的标准字段映射到我们内部定义的统一字段模型上。这个模型长什么样呢大致是以下这些核心字段统一字段含义示例值原始字段可能来源src_ip源IP10.10.1.2src_ip / source_ip / sip / SRC_ADDRdst_ip目的IP172.16.3.9dst_ip / dest_ip / dip / DST_ADDRsrc_port源端口5566src_port / sport / source_portdst_port目的端口443dst_port / dport / destination_portevent_time事件时间(UTC)2020-06-01T08:00:00Ztimestamp / time / datetime / event_timeevent_type事件类型login_failuretype / action / event_type / log_typeuser_name用户名adminuser / username / account / src_userdevice_ip设备IP192.168.1.1device_ip / collector_ip / sensor_ipraw_log原始日志全文{src_ip:...}message / raw / original_log这套归一化的逻辑做好之后后续所有分析任务都不需要关心底层日志来自哪个厂商哪款设备直接基于统一字段模型开发。这也是我强烈建议所有做安全数据分析的团队在第一步就要投入精力做好的事情因为越早做后面改动成本越低。2.2 数据清洗的五个必做动作字段归一化只是第一步。为了保证数据质量我们当时在清洗层还强制做了五个动作每个动作背后都有血泪教训。第一个动作是时间统一。安全设备遍布全国有的设备本地时区设置不对有的设备压根没同步NTP导致日志时间漂移。我们见过最离谱的设备时间比真实时间慢了整整8个小时因为它把UTC时间当成北京时间直接存了。在清洗层我们统一把时间转换成UTC时间戳存储同时保留一个原始时间字符串字段用于核对。这个动作看起来很基础但对后续时间窗口分析的影响是决定性的。比如做暴力破解检测如果时间不对前后相差8小时根本关联不起来。第二个动作是IP格式标准化。IPv6地址统一转成标准格式IPv4地址去掉前导零。这里有个小的技术细节有的设备把IPv4地址以整数形式记录需要做转换我们在UDF里专门写了这个逻辑。第三个动作是去重。日志在传输过程中因为Kafka重平衡、采集Agent重试等原因会产生重复数据。我们的策略是基于设备IP日志ID事件时间组合键做去重这个组合键在绝大多数场景下能保证唯一性。第四个动作是补齐资产信息。单纯的IP地址对分析人员来说不够直观我们通过关联资产CMDB给每条日志打上资产标签比如这个IP是哪个部门的服务器开放了哪些端口跑的是什么业务。这一步做完之后很多分析就可以基于资产维度来做了效率会高很多。第五个动作是敏感信息脱敏。安全日志里经常会出现用户名、口令哈希、甚至偶尔有明文密码。我们做了几套脱敏规则比如用户名字段统一做hash处理后存储原始值只保留在专门的加密区分析任务默认拿不到明文。这在2020年的时候很多团队还不重视但从合规和数据保护的角度这是必须提前设计的。2.3 离线链路与实时链路的职责划分数据分析链路的设计我当时反复和团队强调一个原则不要什么都上实时也不要什么都做离线。实时计算成本高、维护复杂如果只是做个T1的统计报表用Flink纯属浪费。反过来如果威胁检测需要秒级响应你用Spark跑批处理等结果出来黄花菜都凉了。所以我们在架构设计上把分析任务分了两大类。第一类是离线分析每天凌晨定时跑输出前一天的统计结果、行为基线、关联分析结果写入ES或HDFS供查询。第二类是实时分析通过Flink消费Kafka里的实时日志流做规则匹配、简单关联、风险评分结果实时推送给告警平台。举个具体的例子暴力破解检测就是一个典型的混合场景。离线段每天计算每个账号来源IP的历史登录失败率基线实时段用这个基线来判定当前窗口内的失败次数是否超过正常波动范围。如果超过就触发告警。单纯看实时或单纯看离线都不够准确两者结合效果才会好。3. 实操过程与核心环节实现3.1 场景一登录行为异常检测的完整实现登录行为分析是安全数据分析中最基础也最常用的场景。2020年我们接到的很多客户需求都聚焦在这个点上比如内部账号被暴力破解、离职员工账号被异地登录、服务账号在非工作时间突然登录等。我拿这个场景把从Spark分析到最终可视化的完整链路拆给大家看。首先是特征提取。我们从统一字段模型里筛选出登录相关的事件包括登录成功、登录失败、密码修改、权限变更等。然后按账号源IP目标资产组合维度做聚合计算的特征包括登录失败次数、失败占比、登录成功次数、首次登录时间、末次登录时间、登录IP数量、常用登录时段等。这部分用Spark SQL写起来非常顺手核心逻辑就类似这样SELECT user_name, src_ip, dst_ip, COUNT(*) AS login_attempts, SUM(CASE WHEN event_type login_failure THEN 1 ELSE 0 END) AS fail_count, MIN(event_time) AS first_ts, MAX(event_time) AS last_ts, COUNT(DISTINCT src_ip) AS ip_count FROM normalized_login_log WHERE event_time 2020-06-01 00:00:00 AND event_time 2020-06-02 00:00:00 GROUP BY user_name, src_ip, dst_ip这就是一个最简单的特征宽表后面异常判定就基于这个表来做。然后是异常判定逻辑。我们设计了一套组合规则每个规则给出一个得分最后汇总得到风险分。规则是这样的规则判定条件得分规则1暴力破解嫌疑同一账号失败次数 10次且失败占比 80%40分规则2异常地理位置登录账号近期登录IP归属地与本次归属地跨省30分规则3非常用时段登录登录时间在凌晨2点到5点且账号历史上从不在此时间段出现20分规则4账号登录IP数激增单日登录IP数 历史基线均值的3倍20分规则5新资产首次登录账号登录了30天内从未登录过的新资产10分总分超过60分就生成一条可疑事件推给运营人员复核。这条规则集看着简单但背后有一个关键依赖历史基线。历史基线也是Spark离线任务算出来的比如每个账号的正常登录时段分布、常用IP集合、登录IP数的周均值。我们把这些基线数据存进ES实时任务在做判定的时候直接查ES拿基线值大大降低了实时计算的压力。3.2 场景二告警降噪与风险评分的完整思路告警多到看不完这是所有安全运营团队的痛点。我们这边做过一个数据统计某个客户一天产生告警260万条其中被运营确认有价值的只有80多条有效告警率不到万分之三。告警降噪不是为了把告警压下去而是让运营人员把精力放在真正重要的事情上。我们当时用了一个非常务实的降噪方案分层评分。第一层是规则过滤层把明显是误报的告警直接滤掉。比如防火墙拦截策略本身的合规性检测告警、内网设备互相扫描产生的重复告警、测试环境产生的噪音告警这些通过黑白名单和告警指纹的方式过滤掉。告警指纹的概念大家可以理解为一个告警去重逻辑比如同一源IP攻击同一目标IP的同一端口5分钟内只保留一条防止端口扫描产生成千上万条重复告警。第二层是业务关联层把告警和资产重要性绑定。同样一条告警落在核心数据库服务器上和落在测试服务器上风险等级完全不一样。我们把资产分成了四个等级核心资产、重要资产、一般资产、测试资产对应不同的权重系数。告警的原始风险值乘以资产权重就得到了场景化风险分。第三层是威胁情报匹配层。我们把外部威胁情报恶意IP、恶意域名、恶意URL导入系统告警如果关联到情报库里的恶意IOC直接提升风险等级。这一层实际上是用外部数据给告警做加权认证效果非常明显。这套分层下来告警量能压缩掉90%以上剩下的告警按风险分从高到低排序运营人员只需要关注Top 20的告警就行了。当时我们在Grafana上做了一个今日待处理告警排行的面板反响特别好客户每天早上打开第一眼就是看这个面板。3.3 场景三攻击链还原的数据分析视角攻击链还原是安全数据分析里难度比较高的一个应用。所谓攻击链就是攻击者从初始入侵到获取目标权限、横向移动、数据窃取的完整过程业界也叫Kill Chain。传统安全设备只能看到单点告警但攻击者的行为往往是多步骤的单看任何一条告警都不足以判断这是一次有组织的攻击。我们的做法是事件关联分析。思路不复杂把攻击过程中的典型行为事件定义一个攻击阶段然后按时间线把这些阶段串起来。比如一个典型的Web攻击入侵路径大致会经历扫描探测 - 漏洞利用 - 上传webshell - 命令执行 - 权限提升 - 数据外传这几个阶段。我们从日志里提取对应的行为特征比如扫描探测对应的是短时间内大量不同目的端口访问漏洞利用对应的是Web层异常请求数据外传对应的是大流量DNS请求或者异常的外联连接。在数据分析落地的时候我们用了一种比较朴素的关联方式以目标资产为轴心把给定时间窗口内所有与该资产相关的异常事件按时间排序然后与攻击链模板做匹配。如果某个资产在短时间内关联到了3个以上攻击阶段的事件就自动生成一条疑似攻击链记录。这个方案相比复杂的图计算实现成本低很多但效果已经能覆盖大部分场景。2020年的时候图数据库和知识图谱技术在安全领域已经有了一些应用但我们考虑到团队维护成本和数据规模最终选择了这种更可控的关联方式。拿到疑似攻击链之后再让运营人员去人工研判确实帮他们节省了大量排查时间。4. 数据分析过程的可视化落地4.1 基于Grafana的实时监控面板可视化这个环节很多人觉得就是一个展示问题写几个图表放到大屏上就完事了。实际做下来可视化的价值远超展示本身它是数据分析结果真正用起来的最后一公里。我们当时可视化体系分了两层。第一层是Grafana的实时监控面板主要服务日常安全运营值班。比如全网告警实时态势面板左边是Top 10攻击源IP排行中间是攻击类型分布饼图右边是最近1小时的告警趋势折线。这个面板直接对接ES数据延迟在秒级。第二个比较受欢迎的是资产风险总览面板把每个资产的风险分按颜色分级展示在地图上相当于一张动态的资产风险热力图。运营人员一眼就能看出哪些资产处于高风险状态不需要再翻表格。Grafana的好处在于它对ES数据源的支持比较成熟建面板不需要写太多代码而且告警通知可以和钉钉、邮件做对接。我记得当时我们给客户做的第一版面板从开始接入数据到上线总共花了不到一周速度非常快。4.2 自研Web报表系统的设计经验如果Grafana已经能解决大部分可视化问题为什么还要自研呢原因在于Grafana解决的是监控问题但安全数据分析还需要解决研判问题。比如运营人员想针对某个具体账号做历史登录行为回放想看某个IP在所有资产上的活动足迹这类带有强烈交互和分析语义的场景Grafana很难做得好。我们自研的Web报表系统做得比较聚焦核心是三类页面账号行为画像页、IP行为画像页、安全事件研判页。账号行为画像页的设计可以理解为把一个账号的所有历史行为浓缩到一屏。从上到下依次是账号基本信息、近30天登录趋势图、登录地理分布、常用登录IP列表、异常事件时间线。这个页面能在很短的时间内帮运营人员判断一个账号是否正常。IP行为画像页的思路类似只是维度换成了IP。安全事件研判页则偏重操作流。页面下方嵌入了一个时间轴把与该事件相关的所有日志按时间顺序展示运营人员可以直接拖动时间轴查看攻击者的每一步操作不需要再切换到ES的Kibana去写查询。这个设计极大提升了研判效率。这套自研系统的底层技术并不高深就是Python后端加ECharts前端数据查询走ES的聚合接口。关键不是技术本身多牛而是分析思路的梳理和用户体验的打磨。我经常说数据分析的结果如果不能让人轻松看懂、快速使用那分析做得再深也是白做。4.3 数据分析中Python和R的使用场景提到安全数据分析的工具语言很多人默认就是SQL。实际上Python和R在我们的分析链路里扮演了非常重要的角色。Python主要用于两个方向一是数据分析的快速验证二是可视化原型制作。比如在开发暴力破解检测规则之前我会先用Python的pandas库拉取某几天的登录日志做一个快速的数据探索看看登录失败次数的分布形态、异常账号的典型特征验证规则设计是否合理。这个先探后建的习惯帮我避免了很多在Spark SQL里反复调试的麻烦。Python的另一个用途是调用机器学习库做模型原型后面我会讲到。R语言我们用的不如Python多但在特定场景下它确实有优势。比如在安全运营报告的统计分析部分R的ggplot2画出的图表精细度比Python的matplotlib高不少尤其在做攻击源地理分布、时间模式分析这类偏统计制图的场景R更顺手。我个人的体会是工具没有哪个更好的问题只有哪个更合适当前任务的问题。但也要泼一盆冷水。在2020年的大数据生产环境下真正跑数据的还是Spark和Flink这类分布式框架Python和R更多是用于交互式分析和模型原型验证。很多初学者容易陷入工具迷恋觉得会了某个库就等于会做数据分析。实际上数据分析的核心永远是业务理解、特征思维和结果解读能力工具只是手段。5. 常见问题与排查技巧实录5.1 数据倾斜Spark作业跑不动的头号元凶安全日志的数据倾斜问题特别严重。原因也很直观安全日志的价值分布极不均衡某一个热门IP或某一个核心资产产生的日志量可能是普通资产的几百倍。我们遇到过Spark任务跑了一个多小时还没结束一看聚合统计某个reducer处理的数据量比其他reducer大了300多倍。排查数据倾斜有个套路。首先要确认是否存在倾斜最直接的办法是在Spark UI上看stage的task耗时分布如果大部分task几十秒跑完个别task要跑几十分钟基本就能确定是倾斜了。然后定位是哪个key导致的倾斜我们一般通过写一个临时任务按key统计数量降序排列找到Top N的key。安全场景下Top key往往是内网某个扫描器、某个核心DB服务器、或者是NTP/DNS这类公共服务的IP。解决倾斜的手段我们这个场景下最有效的是加盐或随机前缀。加盐的做法是给大key的每条数据加上一个随机前缀让它们分散到多个reducer里去聚合完成后再去掉前缀做二次聚合。这个方法对付单一超大key特别有效。但要注意如果过滤阶段已经能排除掉大key里的大部分噪音数据优先做过滤不要盲目加盐。5.2 时间字段的坑时区问题引发的告警混乱时间问题在安全数据分析里特别常见也特别隐蔽。2020年的时候我们接了一个客户的日志发现每天的告警高峰期出现在早上8点到9点刚开始以为是客户上班时间流量大导致的后来仔细一查发现大批设备的日志时间少加了8小时导致本来发生在凌晨的攻击行为全部被归到了早上8点。如果只看统计曲线完全会误判成上班后的攻击高峰。这个问题的根因是很多安全设备默认使用本地时间写入日志但不同设备、不同配置有的写的是UTC8的北京时间有的写的是UTC还有的写的是设备自定义时区。如果采集端没有做统一换算后面不管是做时间窗口关联还是做基线计算都会出错。我们的解决方案是采集端统一把时间转成UTC后再传输存储层统一以UTC时间戳存储分析层需要展示的时候再转换成本地时区。同时为了避免历史数据的时间混乱我们在清洗阶段加了一个时间合理性校验如果某个设备的事件时间与采集服务器时间偏差超过24小时会产生一条数据质量告警提醒管理员去检查设备的时间配置。5.3 小文件问题HDFS上的隐形杀手安全日志接入HDFS之后小文件问题会越来越严重。原因在于日志采集端为了低延迟会把数据按很小的时间窗口滚动写入Kafka下游的Spark任务消费时也会按小批次落盘。如果每个批次产生的文件都很小日积月累HDFS上会堆满几百万个小文件。小文件太多会导致NameNode内存压力增大、Spark任务读取数据时task数量过多、整体效率下降。解决小文件有两个层面的手段。第一个是写入层控制可以在Spark作业里通过coalesce或repartition控制输出文件数量这个策略需要根据数据量动态调整。第二个是定期合并我们当时写了一个定时合并任务每天凌晨把前一天的小文件读出来重新写一遍按小时分区合并成大文件。这个任务看起来不起眼但对集群稳定性的帮助非常大。5.4 数据质量监控把问题消灭在上游做安全数据分析越久越意识到数据质量监控的重要性。2020年年初的时候我们遇到过一位客户的告警数据莫名丢失了3天排查后发现是采集端Agent升级后配置文件语法错误导致数据没有上报。最可怕的是这个故障持续了3天没有任何人发现因为下游分析任务还在正常跑只是结果数据变少了。从那次之后我们建立了一个数据质量监控体系逻辑其实很简单每个数据源维护一个预期数据量基线比如正常情况下这个防火墙每天产生1200万条日志波动范围在正负20%。如果当天实际数据量与基线的偏差超过阈值就触发告警。同时每条分析任务的结果也加了一个空结果校验如果前一天分析结果为空但历史非空就自动发一条警告消息。这套监控体系上线之后硬件故障、数据丢失这类问题基本能在半小时内发现而且不用人工盯着。我强烈建议所有做数据平台的团队哪怕业务逻辑再简单也一定要把数据质量监控当成一个必做项来做。数据质量出了问题分析做得再漂亮都是空中楼阁。6. 写在最后这些年做安全数据分析的几点体会数据分析这件事在安全领域的难点不在于你会不会用Spark、会不会调模型而在于你对安全业务的理解有多深。2020年我们做这套数据分析和应用最大的收获不是建了多少模型、产出了多少报表而是形成了一个方法论从业务痛点出发设计分析指标再回到数据里去实现和验证。我个人的体会是做安全数据分析一定要避免为了用技术而用技术。有段时间团队里的同学非常热衷于上机器学习模型觉得不用随机森林就显得不够高级。但实际效果往往不如一条精心设计的规则来得稳定和可解释。在安全场景里规则的可解释性至关重要运营人员需要知道这个告警为什么产生才能快速做出判断。黑盒模型在这个行业里落地难度很大。另外一个建议是数据分析结果一定要注重交付体验。同样一份分析报告做成一个10页的PDF文档和做成一个交互式的可视化页面给客户带来的价值感是完全不同的。2020年之后我们越来越强调分析结果即服务的理念就是让分析结果主动推送到用户面前而不是等用户去寻找答案。最后提一个后续可以扩展的方向把安全数据分析结果与自动化响应联动起来。比如分析模型发现某个IP存在明显的扫描行为系统不只生成告警还能自动在防火墙上生成临时封禁策略这样数据分析的价值就不仅是发现问题还能解决问题。这个方向当时我们已经在探索虽然没有完全落地但我认为它代表了安全数据分析的未来。希望这篇文章能给正在做安全数据分析的同学一些参考和启发。
返回列表