ARTICLE DETAIL

资讯详情

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

攻击者画像关键技术:从日志聚类到团伙处置的工程实践

攻击者画像关键技术:从日志聚类到团伙处置的工程实践 简介这是一份面向网络安全从业者、安全态势感知研究人员及高校相关专业学生的技术文献聚焦攻击者画像这一主动防御关键环节帮助读者理解如何从攻击行为中识别意图、预测威胁并辅助溯源。资源为单份PDF文档压缩包约1008KB内容源自《信息技术与信息化》2018年第8期作者王祖俪含摘要、引言、研究现状、关键技术与未来方向等完整章节。文中系统梳理了攻击者画像的作用与现状指出传统溯源多局限于IP定位进而重点阐述威胁情报、机器学习与网络行为画像三大关键技术并讨论多源数据共享、聚类与深度学习在画像构建中的应用同时展望社会网络分析、动态画像更新等方向。目前已有290人学习适合需要快速掌握攻击者画像技术框架、撰写论文或开展安全防御研究时参考。1. 攻击者画像到底在画什么从一份 PDF 标题说开去拿到「网络安全中攻击者画像的关键技术研究.pdf」这个标题时很多人第一反应是去找一份论文来读。但真正在企业里做过威胁情报、做过 SOC 告警研判的人会告诉你攻击者画像不是一篇论文能讲完的东西它是一套从日志、流量、样本、情报里把「人」还原出来的工程链路。你手上可能只有一堆 IP、域名、样本哈希和告警时间戳但你需要回答的是这批攻击来自哪个组织、惯用手法是什么、下一步可能打哪里、我该优先封哪条链路。这就是攻击者画像要解决的问题。它适合三类人一是做安全运营和应急响应的工程师天天被告警淹没想从「单点封禁」升级到「按团伙处置」二是做威胁情报分析的同学手里有大量开源情报和商业情报但不知道怎么把 IOC 变成可行动的画像三是做安全算法或数据平台的开发者想用机器学习把零散日志聚成攻击者档案。这篇文章不假装我读过那份 PDF而是按这个方向最常见的落地路径把画像的字段设计、数据来源、聚类方法、验证手段和踩坑点讲清楚让你能照着搭一版最小可用的攻击者画像系统。2. 攻击者画像的字段体系与数据来源先定标签再谈模型2.1 画像不是给 IP 打标签而是给「攻击者实体」建档案很多团队一开始就把攻击者画像做成 IP 信誉库给每个 IP 打上「恶意」「扫描」「爆破」几个标签然后觉得已经完成了画像。这是最常见的误解。IP 是易变的攻击者用云主机、代理池、CDN 节点同一个 IP 今天扫你、明天可能就换人了。攻击者画像的核心实体应该是「攻击者」或「攻击团伙」IP、域名、样本、邮箱、证书只是这个实体的观测点。常见做法是建立一个实体解析层先把所有观测点归并到候选实体再对候选实体做画像。字段体系一般分四层。第一层是身份层攻击者编号、别名、疑似归属组织、首次发现时间、活跃周期。第二层是基础设施层常用 IP 段、ASN、域名注册商、证书指纹、样本家族。第三层是行为层攻击目标行业、攻击时段偏好、初始访问手法、持久化手法、横向移动工具、外传通道。第四层是能力层工具链成熟度、0day 使用情况、反检测水平、资金与人力推测。这四层里身份层最难行为层最有价值能力层最需要长期积累。提示如果团队刚开始做不要追求四层全填满。先把行为层的「初始访问手法」和「常用工具」两个字段做扎实就能支撑大部分应急响应决策。2.2 数据来源的优先级流量与终端日志比情报 feed 更可靠攻击者画像的数据来源大致分四类网络流量与日志、终端与主机日志、样本与沙箱行为、外部威胁情报。很多团队一上来就买商业情报 feed结果发现情报里的 IP 和自家日志对不上或者情报更新滞后攻击者早就换基础设施了。我的经验是内部数据优先外部情报做补充和关联。网络侧数据包括防火墙日志、NDR 流量元数据、DNS 查询日志、HTTP 代理日志。这些数据能回答「谁在什么时候从哪里用什么协议访问了什么」。终端侧数据包括 EDR 进程树、命令行审计、注册表变更、计划任务创建。这些数据能回答「攻击者进来后做了什么」。样本侧数据包括沙箱行为报告、静态特征、C2 通信配置。这些数据能回答「攻击者的工具长什么样」。外部情报包括开源情报、商业情报、行业共享情报用来给内部发现打上组织标签。数据来源典型字段画像贡献常见问题防火墙/NDR五元组、时间、字节数基础设施、攻击时段NAT 导致 IP 混淆DNS 日志查询域名、响应 IP、TTLC2 域名、DGA 识别加密 DNS 覆盖不全EDR进程树、命令行、父进程工具链、TTP终端覆盖不全沙箱行为序列、释放文件、网络样本家族、持久化反沙箱逃逸威胁情报组织标签、IOC、报告归属推测、关联时效性差、误报2.3 从原始日志到画像特征一个可复现的字段提取流程下面这段 Python 代码演示如何从 DNS 日志和 EDR 进程日志里提取攻击者画像的基础特征。假设你已经有两份 JSON 行格式的日志一份是 DNS 查询日志一份是进程创建日志。代码不依赖特定平台用标准库和 pandas 就能跑。import json import pandas as pd from collections import defaultdict # 读取 DNS 日志提取每个源 IP 的查询域名集合和查询时间分布 def load_dns_features(path): dns_records [] with open(path, r, encodingutf-8) as f: for line in f: obj json.loads(line) dns_records.append({ src_ip: obj.get(src_ip), query: obj.get(query, ).lower(), ts: obj.get(timestamp), resp_ip: obj.get(resp_ip, ) }) df pd.DataFrame(dns_records) # 按源 IP 聚合域名数量、唯一响应 IP 数、查询间隔方差 features df.groupby(src_ip).agg( domain_count(query, nunique), resp_ip_count(resp_ip, nunique), query_count(query, count) ).reset_index() # 计算查询时间间隔的变异系数用于识别 DGA 或心跳行为 def interval_cv(group): ts pd.to_datetime(group[ts]).sort_values() if len(ts) 3: return 0.0 intervals ts.diff().dt.total_seconds().dropna() if intervals.mean() 0: return 0.0 return intervals.std() / intervals.mean() cv_map df.groupby(src_ip).apply(interval_cv).to_dict() features[interval_cv] features[src_ip].map(cv_map) return features # 读取进程日志提取每个主机上的工具链特征 def load_process_features(path): proc_records [] with open(path, r, encodingutf-8) as f: for line in f: obj json.loads(line) proc_records.append({ host: obj.get(host), process: obj.get(process_name, ).lower(), cmdline: obj.get(cmdline, ).lower(), parent: obj.get(parent_process, ).lower() }) df pd.DataFrame(proc_records) # 标记常见攻击工具关键词 suspicious_keywords [mimikatz, psexec, cobaltstrike, beacon, powershell -enc] df[is_suspicious] df[cmdline].apply( lambda x: any(k in x for k in suspicious_keywords) ) host_features df.groupby(host).agg( suspicious_proc_count(is_suspicious, sum), unique_process_count(process, nunique), has_encoded_powershell(cmdline, lambda x: x.str.contains(powershell -enc).any()) ).reset_index() return host_features if __name__ __main__: dns_feat load_dns_features(dns_log.jsonl) proc_feat load_process_features(process_log.jsonl) print(dns_feat.head()) print(proc_feat.head())这段代码的逻辑说明DNS 特征里domain_count高且interval_cv低往往说明有周期性心跳或 DGA 行为resp_ip_count少但域名多可能是同一 C2 基础设施。进程特征里suspicious_proc_count和has_encoded_powershell是强信号但要注意误报比如运维脚本也可能用编码 PowerShell。参数方面suspicious_keywords列表需要根据你所在行业的常见工具调整不要直接照搬interval_cv的阈值一般取 0.3 以下作为疑似心跳但要看你的日志采样频率。注意这段代码只是特征提取不是画像本身。画像还需要实体归并和标签体系下一步才是聚类和关联。3. 用机器学习做攻击者聚类从特征到团伙的落地路径3.1 为什么无监督聚类比分类更适合起步阶段攻击者画像的一个核心任务是把大量观测点归并成少数几个攻击者实体。有监督分类需要标注数据而攻击者标注成本极高且新团伙不断出现分类模型很快失效。所以常见做法是先用无监督聚类做初步归并再用人工分析和情报关联做校正。聚类算法里DBSCAN 和 HDBSCAN 比 K-Means 更适合因为攻击者簇的形状不规则、数量未知、还有大量噪声点。K-Means 强制每个点都归入某个簇会把正常行为也塞进攻击者簇里。特征工程上不要把 IP 本身作为特征而要用行为特征查询域名集合的 Jaccard 相似度、工具链重合度、攻击时段分布、目标端口偏好、TLS 指纹等。下面是一个用 HDBSCAN 对 DNS 行为做聚类的示例依赖scikit-learn和hdbscan库。import pandas as pd import numpy as np from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity import hdbscan # 假设 dns_df 包含 src_ip 和 query 两列每个 src_ip 有多条查询记录 def build_domain_similarity(dns_df): # 把每个源 IP 的查询域名拼成一个文档 docs dns_df.groupby(src_ip)[query].apply(lambda x: .join(x)).reset_index() vectorizer TfidfVectorizer(analyzerchar_wb, ngram_range(3, 5), min_df1) tfidf_matrix vectorizer.fit_transform(docs[query]) sim_matrix cosine_similarity(tfidf_matrix) return docs[src_ip].tolist(), sim_matrix def cluster_attackers(ip_list, sim_matrix, min_cluster_size3): # 将相似度转换为距离 distance_matrix 1 - sim_matrix clusterer hdbscan.HDBSCAN( metricprecomputed, min_cluster_sizemin_cluster_size, min_samples2 ) labels clusterer.fit_predict(distance_matrix) result pd.DataFrame({src_ip: ip_list, cluster: labels}) return result if __name__ __main__: # 这里用示例数据代替真实日志 sample pd.DataFrame({ src_ip: [10.0.0.1, 10.0.0.1, 10.0.0.2, 10.0.0.2, 10.0.0.3], query: [bad-c2.com, bad-c2.com, evil-domain.net, evil-domain.net, normal.com] }) ips, sim build_domain_similarity(sample) clusters cluster_attackers(ips, sim, min_cluster_size2) print(clusters)逻辑说明TfidfVectorizer用字符 n-gram 而不是词级是因为恶意域名经常是随机字符串词级切分没有意义。cosine_similarity得到相似度矩阵后转成距离矩阵HDBSCAN 用precomputed模式聚类。min_cluster_size控制最小簇大小太小会碎片化太大会漏掉小团伙一般从 3 开始调。min_samples影响噪声点判定值越大噪声越多。聚类结果里cluster-1是噪声点需要人工看是否是独立攻击者还是正常行为。3.2 把聚类结果变成可读画像标签生成与人工校验聚类只是把相似的东西放在一起离「画像」还差一步标签生成。常见做法是对每个簇提取高频特征出现最多的域名后缀、最常用的工具、最集中的攻击时段、最常打的目标端口。然后把这些特征映射成自然语言标签比如「使用 Cobalt Strike 的勒索软件前导团伙偏好凌晨攻击目标为金融行业」。这一步可以用规则模板也可以让分析师手工写但一定要有人工校验环节。人工校验的重点是看簇内一致性。如果某个簇里既有扫描行为又有数据外传行为可能是聚类粒度太粗需要调整特征权重或增加特征维度。另一个重点是看簇间关系有些簇可能属于同一个攻击者的不同阶段需要做时序关联。下面是一个简单的标签生成函数把簇特征转成结构化画像。def generate_profile(cluster_df, dns_df, proc_df): profiles [] for cluster_id, group in cluster_df.groupby(cluster): if cluster_id -1: continue ips group[src_ip].tolist() # 从 DNS 日志里找这些 IP 的高频域名后缀 cluster_dns dns_df[dns_df[src_ip].isin(ips)] top_domains cluster_dns[query].str.extract(r\.([a-z0-9-]\.[a-z]{2,})$)[0].value_counts().head(3).index.tolist() # 从进程日志里找这些主机的高频工具 cluster_proc proc_df[proc_df[host].isin(ips)] top_tools cluster_proc[process].value_counts().head(3).index.tolist() profiles.append({ cluster_id: cluster_id, ip_count: len(ips), top_domain_suffix: top_domains, top_tools: top_tools, sample_ips: ips[:5] }) return pd.DataFrame(profiles)参数说明top_domains提取的是域名后缀不是完整域名因为完整域名太细后缀更能反映基础设施偏好。top_tools取进程名实际使用时应该结合命令行参数因为同一个进程名可能被正常软件和恶意软件共用。sample_ips只取前 5 个用于展示完整列表应该存到数据库里。3.3 画像的验证用历史事件做回溯测试画像做完不能直接上线要用历史事件做回溯测试。具体做法是拿过去半年已经确认的攻击事件看画像系统能不能把这些事件里的观测点归到同一个簇并且簇标签和已知攻击者描述一致。如果画像系统把两个已知不同团伙归到一个簇说明特征区分度不够如果把同一个团伙拆成多个簇说明特征太细或聚类参数太严。回溯测试的指标可以用簇纯度、召回率和 F1。簇纯度指一个簇里多数观测点属于同一个已知团伙的比例。召回率指已知团伙的观测点被正确归入同一簇的比例。这两个指标往往互相矛盾需要根据业务需求权衡。如果用于应急响应召回率优先宁可多归并一些如果用于情报生产纯度优先宁可漏掉一些。提示回溯测试的数据集要包含正常行为作为负样本否则画像系统会把所有东西都归成攻击者。4. 攻击者画像系统的避坑与排查五条血泪经验4.1 坑一把 NAT 后的多个用户当成一个攻击者现象画像系统把公司出口 NAT IP 标记为攻击者导致整个办公网被误封。原因NAT 后面有几百个用户他们的行为被聚合到同一个 IP 上特征看起来像扫描或爆破。解决在特征提取阶段加入用户代理、登录账号、设备指纹等维度不要只依赖 IP。如果只有 IP至少要把 NAT IP 加入白名单或者用时间窗口和端口分布做区分。4.2 坑二情报 feed 的 IOC 直接当画像输入现象画像系统把商业情报里的 IP 全部标记为高危结果发现很多是 CDN 节点或公共 DNS。原因情报 feed 的 IOC 没有上下文很多是历史数据或低置信度数据。解决情报输入要带置信度和时间戳只使用高置信度且近期活跃的 IOC。同时要用内部日志验证内部没有观测到的 IOC 只能作为参考不能直接触发封禁。4.3 坑三聚类特征里混入了时间戳本身现象聚类结果完全按时间分簇同一时间段的所有 IP 被归到一起。原因特征向量里直接用了原始时间戳数值差异主导了距离计算。解决时间特征要做周期编码或分桶比如把小时映射到 0-23 的周期特征或者只保留「是否在凌晨」这样的布尔特征。不要直接把 Unix 时间戳放进特征矩阵。4.4 坑四样本沙箱报告里的 C2 域名已经失效现象画像系统提取的 C2 域名在 DNS 日志里查不到导致关联失败。原因沙箱分析有延迟攻击者已经更换基础设施。解决沙箱报告要记录分析时间C2 域名要同时做被动 DNS 查询和历史流量回溯。如果域名已失效可以用证书指纹、JA3 指纹、URL 路径等更稳定的特征做关联。4.5 坑五画像更新频率跟不上攻击者变化现象画像系统一周更新一次但攻击者两天就换一批 IP。原因批处理架构延迟太高。解决把画像系统拆成实时层和批处理层。实时层用流式计算做简单规则匹配和快速聚类批处理层做深度关联和标签生成。实时层的结果可以覆盖批处理层的旧标签保证画像的时效性。5. 让画像真正可行动从簇标签到封禁策略的最后一公里画像做完之后最大的挑战是让它可行动。很多团队的画像报告写得很漂亮但到了封禁环节还是靠人工看 IP 列表。我的习惯是给每个画像簇打一个「行动等级」直接对应处置策略。行动等级分四级观察、限速、封禁、隔离。观察级只记录不阻断限速级对特定端口或协议做速率限制封禁级直接丢包隔离级把主机踢出网络并触发终端排查。行动等级的判定不能只看聚类结果还要结合资产重要性和攻击阶段。比如同一个攻击者簇如果只扫描了低价值资产可以观察如果已经尝试横向移动就要封禁如果已经拿到凭据就要隔离。下面是一个简单的决策表可以用在 SOAR 平台里做自动化编排。画像特征资产重要性攻击阶段行动等级新出现的簇仅扫描低侦察观察已知恶意簇扫描爆破中初始访问限速簇内主机出现横向工具高横向移动封禁簇内主机出现凭据窃取高凭据访问隔离簇内主机出现外传行为高外传隔离取证这个表的关键是「攻击阶段」的判定。攻击阶段可以从进程树和命令行里推断比如出现net use、psexec、wmic可以判为横向移动出现mimikatz、lsass转储可以判为凭据访问。这些规则不需要机器学习用正则和进程树匹配就能做而且可解释性强适合应急响应场景。最后说一个我自己的教训早期做画像时我总想把模型调得更准花了很多时间在特征工程和参数调优上结果上线后发现分析师根本不看画像报告因为他们更信任自己手头的告警。后来我把画像结果直接嵌入到告警详情页里每个告警旁边显示「该源 IP 属于哪个画像簇、该簇的历史行为、建议行动等级」使用率才上来。画像的价值不在于模型多复杂而在于能不能在决策点出现。希望帮到你。本文还有配套的精品资源点击获取
返回列表