开篇先聊个很多人对网络安全大模型的误解。不少团队拿到一张GPU就想把通用大模型拉过来微调,结果折腾几周发现效果还不如用规则引擎,问题基本都出在同一个环节:数据。通用大模型训练用的是百科、论文、新闻这些语义密度高的文本,而网络安全的核心知识大量分布在漏洞公告、攻击流量、恶意代码、告警日志和渗透测试报告里,这些数据噪声极高、格式极度碎片化、敏感信息含量大,直接拿来训练轻则效果拉胯,重则把有害内容学进模型权重。我做了几年安全数据治理,又折腾了大半年大模型落地的项目,可以负责任地说一句:数据获取这一步走稳了,整个训练流程就成功了七成。
这篇是“大模型训练全流程实战指南”系列的第十四篇,专门讲网络安全大模型的数据获取,覆盖数据源规划、采集手段、清洗策略、标注方案、质量评估、合规红线,以及多源融合时的取舍思路。适合正在做安全垂直领域大模型训练、微调或RAG增强的工程师、安全研究员和数据团队参考,也适合刚入门想在安全AI方向打基础的读者建立全局认知。
1. 为什么网络安全大模型的数据获取不是“爬点数据就行”
先说一个最容易被低估的点:通用大模型训练的数据获取思路放在安全领域基本走不通。很多人习惯性认为,数据获取就是去GitHub拉几个安全工具仓库,去CVE网站抓漏洞描述,再找几个SRC平台的公开报告,拼一拼就是训练集了。这么做的结果我见过太多次——模型确实能背出CVE编号,但你要是问它一个真实流量包里有没有SQL注入特征,它就语焉不详了。原因在于,网络安全模型需要的不是“知识”,而是“判断能力”,而判断能力只能从高质量的正负样本对和细粒度的标注中长出来。
这里用一个对比来说明。通用大模型的数据单元是“段落”,一段通顺的文字本身就有完整语义;而安全数据的最小可用单元往往是“事件”——一条告警日志、一段恶意代码、一个HTTP请求的头部、一段DNS解析记录。这些事件单独看几乎没有语义,必须结合上下文、时间线、攻击链位置才能体现价值。数据获取如果只追求“量大”,抓回来的东西可能90%以上都无法直接进入训练流程,反而浪费大量清洗算力和标注人力。
从技术链路倒推,也能看清这件事的复杂度。网络安全大模型的数据获取,本质上是一条多源异构数据汇聚流水线,自下而上包括四层:
- 源层:漏洞库、威胁情报、开源代码、流量样本、恶意文件、安全社区、SRC报告、内部告警日志等;
- 采集层:爬虫、API对接、流量抓取、日志导出、样本共享等方式把原始数据拉回本地;
- 加工层:去重、脱敏、格式统一、时间对齐、事件切分、特征抽取;
- 语料化层:将加工后的安全事件转换成可用于预训练、微调或指令微调的文本样本。
这四层每一层都有专门的坑。源层要解决的是合规和版权边界,采集层要处理反爬和动态加载,加工层要面对的是海量脏数据和样本不均衡,语料化层则要设计统一模板和指令格式。我在后面的章节里逐层拆开讲,并给出实际项目中验证过的处理方案。
2. 数据获取前必须做对的目标定义与源规划
这一节讲的是动手之前先干什么,算是血泪教训换来的优先级。很多团队数据采集工具写得飞快,爬虫脚本一堆,结果两周后数据集评审时发现漏洞描述占了八成,恶意流量样本一个都没有,标注阶段才发现负样本严重缺失,整个项目被迫返工。我自己第一次做安全模型数据时就踩过这个坑,先上工具后定标准,后果就是清洗代码反复改、标注规范来回推倒重来。
2.1 先用“能力清单”反推数据需求
不要先想“有什么数据可以拿”,而要先想“模型必须具备哪些能力”。网络安全大模型的能力可以拆成几个层次,每一层对数据的要求完全不同:
- 漏洞知识问答:需要CVE描述、CVSS评分、漏洞原理文章、补丁公告,数据形态接近通用语料,比较好获取;
- 威胁情报关联分析:需要IOC(失陷指标)数据、攻击组织报告、恶意域名/IP信誉库,要求数据有时间戳和关联关系;
- 日志异常检测与解释:需要大量真实网络日志和告警数据,正样本是历史攻击日志,负样本是正常访问日志,这是最难获取的一类数据;
- 恶意代码识别与解读:需要带标签的恶意软件样本、webshell脚本、混淆代码片段;
- 渗透测试辅助:需要SRC漏洞报告、渗透测试过程记录、漏洞利用代码及对应修复建议。
每一类能力背后的数据量级、采集难度、标注成本差距极大。我建议团队在做规划时列一张“需求-数据源-优先级”的映射表,把能力项、数据来源、获取难度、标注成本、当前缺口这五个维度全部填上,然后按投入产出比排序,先满足最核心能力的数据需求,其余能力放到后续迭代。
2.2 制定数据规模预算与配比目标
数据量不是越大越好,但有一个最低门槛。以我的项目经验,做指令微调阶段,一个安全能力点至少需要数万条经过清洗和标注的样本;做领域预训练或继续预训练,则需要数亿到数十亿token的领域语料,否则领域分布相比通用语料占比太低,模型根本学不到足够的先验知识。如果你做的是RAG增强而不是真正训练模型,那数据规模要求可以放宽,但数据质量要求反而更高,因为索引里的错误信息几乎会原样返回给用户。
配比上,有个经验值供参考:漏洞与知识类数据约占40%,威胁情报与IOC数据占20%,恶意样本与攻击日志占25%,正常流量与误报日志占15%。这个比例不是拍脑袋定的,而是基于安全模型常见任务类型的概率分布设计的——知识问答类任务最多,但恶意检测类任务对负样本的需求极其敏感,宁可数据总量少一点,也要保证正负样本平衡。
2.3 建立数据源台账
这一步看起来像管理动作,实际对工程效率影响很大。我建议在正式采集前建一个数据源台账,字段包括:数据源名称、类型、访问方式、更新频率、数据格式、许可证/授权状态、采集责任人、清洗状态、样本量。不要嫌麻烦,数据源一多,尤其是发展到七八个以上时,没有台账梳理,你根本不知道某份数据从哪里来、能不能用于商用、有没有更新过,后续合规审计也会成为大问题。
3. 五类核心数据源全解析与获取要点
这一节是重头戏,我把网络安全大模型最值得投入的数据源分成五类,逐一说明特点、获取方式、坑点和产出形式。每类数据源我都给出了优先级判断,方便你在资源有限时快速决策。
| 数据源类别 | 典型来源 | 获取难度 | 数据价值 | 核心坑点 | 优先级 |
|---|---|---|---|---|---|
| 漏洞与知识库 | CVE、CNVD、NVD、厂商安全公告、OWASP | 低 | 高 | 格式多样,多语言混杂 | 高 |
| 威胁情报库 | 恶意域名/IP库、APT报告、ATT&CK | 中 | 高 | 时效性强,更新维护成本高 | 高 |
| 开源代码与样本 | GitHub安全工具、恶意代码样本库、漏洞PoC | 中 | 中高 | 版权与法律风险,样本可能带毒 | 中高 |
| 日志与流量数据 | 内部告警日志、公开流量数据集、自建蜜罐 | 高 | 极高 | 隐私问题,标注成本极高 | 高 |
| 社区与报告 | 安全博客、SRC报告、技术社区、会议论文 | 低 | 中 | 权威性参差,信息冗余 | 中 |
3.1 漏洞与知识库数据
这类数据是网络安全大模型的“基础课教材”,获取最方便,清洗也相对简单。需要重点抓取的内容包括:CVE描述和CVSS评分、CWE弱点分类、OWASP Top 10及各类Checklist、厂商安全公告(比如微软、思科、红帽的公告)、漏洞利用代码仓库中的相关说明。
具体采集时可以直接走官方API,以NVD为例,它提供JSON格式的漏洞数据接口,支持按时间范围、CVE编号、关键词过滤,通过API Key可以拿到完整数据。如果做国内项目,还要接入CNVD和CNNVD的公开数据。厂商安全公告基本都是HTML页面,需要写爬虫抓取并解析正文。
这个环节有一个容易被忽略的点:多语言统一。CVE描述是英为主,CNVD有中文描述,厂商公告更是各种语言混杂。如果直接混着喂给模型,训练时模型会学出严重的语言混杂倾向。我的做法是建立一份字段映射表,把不同来源的漏洞描述统一转成“漏洞编号-影响产品-漏洞类型-危害描述-修复建议”的标准格式,英文描述保留原件,同时抓取中文描述作为补充字段,在语料化阶段做语言分离,训练数据里一份样本只保留一种主语言。
3.2 威胁情报与IOC数据
威胁情报数据是安全模型区别于通用模型的“行话课”,教的是模型读懂攻击者留下的指纹特征。这类数据包括:恶意域名、恶意IP、恶意URL、钓鱼网站、勒索软件家族信息、APT攻击组织画像、ATT&CK技战术映射表等。
威胁情报数据有免费和商业两条路。免费的包括:AbuseIPDB的公开API、MalwareBazaar的样本信息、URLhaus的恶意URL列表、PhishTank的钓鱼数据以及MITRE ATT&CK官方数据库,这些都可以脚本化批量拉取。商业威胁情报平台则通常提供更完整的IOC上下文和关联图谱,但价格不低,具体看预算。
这个环节的关键操作是给IOC数据做“时间衰减”处理。威胁情报时效性极强——一个今天还活跃的C2域名,可能两周后就失效了,如果训练集里塞了大量过期IOC,模型反而学会判断正常域名有风险。建议在采集时记录first_seen和last_seen字段,在语料化时对超过90天没有更新的IOC降低权重,或者直接踢出训练集。
3.3 恶意样本与开源代码数据
恶意代码和利用代码是安全模型进行“代码级理解”的必需品。典型的场景是要让模型看得懂一段PowerShell脚本是恶意下载器还是正常管理脚本,这需要大量的代码样本作为训练语料。
恶意样本方面,VirusTotal和MalwareBazaar提供样本检索与下载接口,但需要注意样本本身是带毒的,下载、存储、处理的环境必须隔离,建议在独立的虚拟机或容器里完成,严禁在开发机或办公网上直接打开。开源代码方面,GitHub上有大量安全工具仓库和漏洞PoC集合,可以使用Git Clone批量获取,但获取前要读清许可证,部分仓库明确禁止将代码用于模型训练。
这一类的清洗是重头戏。恶意代码通常经过混淆、加壳、字符串编码,直接拿原始形态训练会让模型学到大量噪声特征。我的建议是至少做一层“解混淆”预处理:对于PowerShell和JavaScript这类常见载荷语言,先提取可读的字符串、URL、IP、Base64解码后的内容,与原始代码同时保存,在语料化时优先使用解码后的可理解内容。同时必须过滤掉样本中的真实攻击目标和真实个人信息,防止训练语料泄露敏感数据。
3.4 日志与流量数据
日志与流量数据是安全模型从“懂知识”走向“会干活”的分水岭,也是难度最大的数据源。这类数据的价值在于它反映了真实攻防场景中模型的输入形态——一条普通的HTTP POST请求和一条包含SQL注入尝试的HTTP POST请求,外表差异可能极小,模型必须学会分辨。
获取渠道主要有三个:
第一是公开数据集。UNSW-NB15、CICIDS2017、CSE-CIC-IDS2018都是学术界常用的网络流量数据集,包含完整的流量抓包和攻击标签,适合做检测类能力的预训练。第二是自建蜜罐。在内网或云上部署蜜罐系统,会有大量真实攻击流量自动送上门来,这是获取最新攻击样本的性价比之选。第三是内部安全设备日志。如果企业有WAF、IDS、EDR等设备,这些日志就是最贴合实际场景的数据,但通常涉及核心业务数据,必须经过严格的脱敏和权限审批才能使用。
日志类数据有一个天然难题:正负样本极不平衡。真实网络环境里99.9%的流量是正常的,攻击流量占比极低,如果不做处理,模型训练出来会把所有流量都判成正常,因为判正常的准确率也能到99.9%。解决办法有两个:一是过采样攻击样本,将攻击类日志按比例重复采样,将正负比拉到1比10到1比20之间;二是对正常流量做“聚焦采样”,只保留边界场景的正常日志(比如带参数的POST请求、异常UA头、非标准端口流量),让模型看到的正常样本本身就有区分度。
3.5 社区报告与SRC文档数据
社区报告类数据决定了模型对“现实攻防语言”的理解程度。渗透测试报告、漏洞分析文章、SRC平台的漏洞提交详情、安全会议论文和技术博客,这些内容里包含了大量“攻击思路”和“绕过技巧”的自然语言描述,是模型学会安全推理的“思想课”。
知名的SRC平台(漏洞提交与奖励平台)上有很多已公开的漏洞报告,可以合法获取用于安全研究和模型训练。技术社区(看雪、先知、FreeBuf、安全客等)的文章同样有极高的语料价值。但这一类的数据质量参差,有些文章的利用代码是阉割版,有些分析结论已经过期,有些文章为了SEO堆砌了大量无效关键词。
这里建议做两层过滤:第一层基于来源过滤,只保留注册作者、有评论讨论或有用投票数量较高的文章;第二层基于内容过滤,用规则或小型分类模型筛掉纯新闻转载和SEO水文。另外这类数据在语料化时要做“AI友好化”改写,将口语化的分析过程转换成结构化的“问题-分析-结论”格式,让模型更容易从文本中提取因果关系。
4. 数据采集工程落地细节与自动化方案
数据源有了列表,接下来就是真正动手把数据搬回本地。这一节讲采集层的具体实现方案,包括架构设计、关键脚本思路和反爬处理经验。
4.1 三种采集模式的选型
根据数据源类型和更新频率不同,我把采集方案分成三类模式,你可以对照自己的场景直接选用:
定时全量拉取(适用于CVE漏洞库、ATT&CK知识库、开源IOC列表等结构稳定、更新不频繁的数据源):写一个定时任务脚本,每天或每周调用官方API或下载全量数据包,直接覆盖本地存储。
增量增量同步(适用于SRC平台新公开报告、安全博客新文章、GitHub新提交代码等持续更新的数据源):记录上次拉取位置(时间戳或分页游标),只抓取新增内容,同时维护一个内容指纹库用于去重。
实时流接入(适用于内部日志、蜜罐数据等持续产生的流式数据):通过Kafka或类似消息队列接入,做实时清洗后直接写入数据湖。
我见过不少团队在采集阶段就上了复杂的分布式爬虫架构,其实大可不必。前期数据积累阶段,单机多线程脚本加上任务调度器就能满足绝大多数场景,等数据量真正到亿级再来考虑分布式也不迟,过早引入分布式只会增加运维负担。
4.2 一个可复用的爬虫采集框架
以爬取安全社区文章为例,这是一个最典型的低频高价值采集任务,可以按照以下结构来写:
import requests from bs4 import BeautifulSoup import hashlib import json import time from typing import Dict, List class SecurityArticleCrawler: """安全社区文章爬虫基础框架""" def __init__(self, source_name: str, api_url: str, headers: Dict[str, str]): self.source_name = source_name self.api_url = api_url self.headers = headers or {"User-Agent": "Mozilla/5.0 (compatible; SecurityCrawler/1.0)"} self.session = requests.Session() self.session.headers.update(self.headers) def fetch_page(self, page_num: int) -> List[Dict]: """获取指定页码的文章列表""" resp = self.session.get(self.api_url, params={"page": page_num}, timeout=15) resp.raise_for_status() data = resp.json() return data.get("data", []) def fetch_article(self, article_url: str) -> str: """获取文章正文HTML""" resp = self.session.get(article_url, timeout=15) resp.raise_for_status() soup = BeautifulSoup(resp.text, "html.parser") # 根据实际站点调整正文选择器 content_div = soup.select_one("article, .article-content, .post-content") if not content_div: return "" # 移除代码块之外的脚本和样式 for tag in content_div.find_all(["script", "style", "nav", "footer"]): tag.decompose() return content_div.get_text(separator="\n", strip=True) def process_and_save(self, raw_data: Dict) -> Dict: """清洗并保存文章,返回结构化记录""" article = { "source": self.source_name, "title": raw_data.get("title", ""), "url": raw_data.get("url", ""), "author": raw_data.get("author", ""), "publish_time": raw_data.get("publish_time", ""), "tags": raw_data.get("tags", []), "content_md5": "", "content": "", } content = self.fetch_article(article["url"]) if not content or len(content) < 500: return None # 过滤掉空文章或正文太短的页面 article["content"] = content article["content_md5"] = hashlib.md5(content.encode("utf-8")).hexdigest() return article def run(self, max_pages: int = 10) -> List[Dict]: """主运行入口""" result = [] for page in range(1, max_pages + 1): try: items = self.fetch_page(page) if not items: break for item in items: saved = self.process_and_save(item) if saved: result.append(saved) time.sleep(1) # 礼貌抓取,避免请求过快 except Exception as exc: print(f"页面 {page} 采集失败: {exc}") continue return result这个框架的核心思路是:页面列表和正文解析分离,各站点之间只改定位器(选择器),整体代码逻辑可以复用。到新的站点采集只需要子类化这个基础类,重写对应选择器就行。代码里做了几个关键处理:正文长度过滤(小于500字的页面对训练基本没价值)、内容MD5指纹用于全局去重、请求间隔限制防止被封IP。
运行采集脚本建议在具备以下特征的机器上执行:一台普通的4核8G云服务器就够用,操作系统选Linux,存储挂载独立数据盘,网络走普通家庭或企业出口即可。我不建议在办公电脑上直接长时间跑爬虫——避免污染个人网络环境,而且掉线断网会导致采集中断,日志恢复又是一笔麻烦事。
4.3 反爬应对和数据质量兜底
安全社区和论坛的反爬强度普遍在中等水平,常见的对策包括:请求频率限制、加Cookies校验、Cloudflare浏览器验证等。我的处理经验按优先级排列:
- 降低请求频率:单线程加1到3秒的请求间隔是最简单有效的方案,比任何代理池都管用;
- 模拟真实浏览器头部:带上完整的User-Agent、Accept、Referer等头字段,不要暴露明显的爬虫标记;
- 从公共接口下手:很多网站在前端有一些用于列表渲染的JSON接口,走接口获取数据比解析HTML容易得多,也稳定得多;
- 适当引入浏览器渲染:遇到动态加载的内容时,用Playwright或Selenium做渲染获取,但只用于必要的页面,避免重型渲染拖慢整体进度。
另外要做一个意识转变:采集到的数据一定有一部分是坏的。可能是一个链接已经404却返回了200空内容,可能是字段解析位置偏移导致正文错乱,也可能是时间戳格式不统一。这部分脏数据在采集阶段就要有兜底逻辑,我习惯在每个采集任务里加一个“健康度自检”环节:统计有效记录数、正文平均长度、字段缺失率,低于阈值直接告警,不要等数据进了清洗管线才发现源头就废了。
5. 数据清洗与结构化标注流水线
数据源杂乱多样,直接进训练环节基本是灾难。这一节讲清洗和标注,是整个数据管道中工作量最大、也最决定模型上限的环节。我常说一句话:标注质量决定模型上限,模型结构和训练技巧只是逼近这个上限的手段。
5.1 统一数据Schema:从“各说各话”到“一个模板”
不同类型的源数据格式千差万别,如果每类数据各自为政,后续语料化时根本没有统一入口。我的做法是设计一个统一的“安全文档对象模型”,所有清洗后的数据都往这个结构上靠:
{ "doc_id": "唯一ID", "source": "数据来源", "data_type": "vulnerability | threat_intel | code_sample | log_traffic | article | srs_report", "title": "标题", "content": "清洗后的正文内容", "metadata": { "publish_time": "发布时间", "author": "作者/来源", "url": "原始链接", "tags": ["关联标签"], "language": "zh | en", "severity": "危害等级", "cve_id": "关联CVE", "attck_id": "关联ATT&CK", "labels": ["样本标签", "如: sql-injection", "正常流量"] }, "content_md5": "内容指纹", "clean_version": "清洗流程版本号" }统一Schema的好处有三个:一是清洗代码可以按data_type分派不同的逻辑,但最终输出结构一致;二是人工审核时只需要看metadata字段就能理解样本背景,不需要重新翻原始数据;三是后续做语料化和指令模板时,同一套代码可以处理所有数据源。
5.2 清洗规则库:去重、去噪、格式化
清洗阶段的规则库需要覆盖以下几类问题,我按处理顺序列出:
首先是在线去重和近似去重。完全相同的文章、相同的CVE描述、被转载多次的安全博客,需要按MD5做精确去重。但现实中大量内容是“改头换面”的转载,标题不同、正文相似度在70%以上,这需要用MinHash或SimHash做近似去重,设定相似度阈值后合并或丢弃。我实测下来,以一篇安全博文数据集为例,近似去重能把数据规模压缩20%到30%,对训练效率提升非常明显。
其次是格式归一。不同来源的时间格式可能是“2024-03-15”“Mar 15, 2024”“2024/3/15”,要统一成ISO 8601标准格式;HTML实体要转义;各类空白字符要归一化;从PDF解析出来的内容要注意处理换行断裂问题。
然后是低质内容过滤。纯标签堆砌页、乱码页面、纯图片无正文页面、正文与主题完全不相关的页面都在此列。我常用的规则是:正文长度低于200字直接丢弃;中文字符占比低于30%且不含代码特征直接丢弃;包含“热门推荐”“阅读全文”“相关文章”等导航片段的内容要做截断处理。
5.3 标签体系设计是标注的灵魂
标注不是简单地给数据打个“是或否”的标签,而是要设计一套能支撑模型完成任务目标的标签体系。以网络安全大模型常见的恶意代码识别能力为例,标签体系至少需要包含以下维度:
- 行为类型:下载器、键盘记录、勒索加密、远控木马、挖矿程序、信息窃取等;
- 载荷形式:PowerShell脚本、JavaScript、VBScript、MS Office宏、二进制可执行文件、Shell命令等;
- 混淆技术:Base64编码、字符串拼接、动态执行、反调试、加壳等;
- 攻击阶段:初始访问、执行、持久化、防御规避、横向移动等,对应ATT&CK的阶段编号;
- 目标系统:Windows、Linux、macOS、跨平台。
这五个维度组合起来,才能让模型在推理时不仅知道“这个是恶意的”,还知道“它恶意在哪里、用什么方式实现的、处于攻击链的什么位置”。如果只打一分类标签,模型学到的是表面特征,换个混淆方式就识别不出来了。
标注过程要区分“机器预标注+人工抽检”和“全人工标注”两种策略。如果做的是日志类数据,真实攻击日志量本来就少,强烈建议全人工标注或安全专家复审;如果做的是漏洞描述或文章语料这类结构化比较强的数据,可以先用规则和LLM做预标注,再由人工抽检纠错。抽检比例至少在10%到20%,保证标注准确率不低于95%。
5.4 LLM辅助标注的效率与风险
现在做大模型项目,标注环节可以引入一个通用大模型作为辅助,将标注效率提升数倍。以给安全文章打标签为例,可以这样写提示词:
你是一位资深网络安全专家。请阅读以下安全技术文章,按以下JSON格式输出结构化标签: { "attack_tactic": "攻击战术(如初始访问、权限提升、防御规避等)", "technique": "具体技术(如SQL注入、钓鱼邮件、漏洞利用等)", "affected_platform": "受影响平台", "severity": "危害等级(低/中/高/严重)", "summary": "不超过100字的核心内容摘要" } 注意事项: 1. 只基于文章内容判断,不要猜测不存在的信息; 2. 如果某字段文章未提及,输出null; 3. 涉及攻击手法的描述不做判定,只做分类。 文章内容如下: {article_content}用通用LLM做预标注的准确率,在技术分类和摘要生成这两类任务上基本能达到80%以上,但有一个明显的风险点:LLM会“编”出原文没有提到的信息,尤其是在影响平台和危害等级这类字段上。所以LLM预标注结果必须经过人工抽检,凡是存在关键字段冲突的样本要单独拉出来复核。
另外,同一个LLM标注的数据去做同一个体系的模型训练,存在一种“标注风格泄漏”问题。模型会学到该LLM的输出格式偏好、措辞习惯甚至中立化腔调,训练完的模型在推理时也会表现出类似特征,所以我不建议100%依赖同一个LLM做全部标注,至少留20%到30%的数据用规则或人工标注,增加数据多样性。
6. 数据质量审计与合规红线
质量审计和合规不是数据项目的“政委”,而是一个数据工程师必须具备的工程素养。网络安全数据天然敏感,做训练语料用和做公开数据集分享用,面对的合规要求完全不同,必须在项目启动时就把红线画清楚。
6.1 质量审计的四层检查
在数据集进入训练环节之前,我习惯做四层质量检查,按顺序执行:
第一层是完整性检查。统计每个字段的缺失率和异常值,比如URL字段为空、时间为NULL、CVE编号不匹配,任何一个字段缺口超过阈值都要回到对应数据源重新补采。
第二层是多样性检查。统计数据集中不同来源、不同类别、不同标签的占比,确保没有某个类别占了90%以上。这一层最直接的价值是防止训练集分布严重偏斜。
第三层是一致性检查。抽检同一样本在不同批次采集中的字段内容是否一致,如果同一CVE的描述在不同批次中存在互相矛盾的结果,说明清洗规则有问题,需要回溯定位。
第四层是“对抗性人工抽检”。直接随机抽取200到500条数据,由安全工程师逐条过目,不看标签只看内容,判断内容本身是否合理、是否和对应标签匹配、是否存在明显的诱导性或有害性。这一层最耗费人力,但也是最值得的,因为模型最终输出的“三观”基本由这些样本决定。
6.2 脱敏处理必须前置
网络安全数据中的敏感信息分为三类:第一类是个人隐私信息,比如日志中的真实用户名、手机号、邮箱地址、个人IP;第二类是业务敏感信息,比如内部系统账号、真实域名、核心系统IP段;第三类是真正的攻击Payload中的攻击目标信息,比如恶意代码里硬编码的受害者内网地址。
脱敏不能靠清洗阶段顺手做,必须在数据进库之前设置一道强制脱敏关卡。IP地址做CIDR模糊化或替换,域名做泛化替换,邮箱和手机号用正则匹配后替换成测试值,Payload中的真实目标地址做替换处理但保留长度和结构特征,比如一个192.168.x.x的内网地址替换成10.10.x.x。这样做既保留了数据的形态特征,又不至于在训练语料里泄露真实信息。
6.3 数据版权与使用边界
训练数据的版权合规问题在安全领域尤其复杂。公开的CVE描述、NVD数据、ATT&CK框架等有明确的开源许可,使用相对自由;但安全博客文章、SRC报告、商业威胁情报数据往往有版权声明,直接抓取用于商用训练可能引发法律纠纷。
我在数据源台账里会为每类数据打上“使用等级”:
- L1自由使用:开放许可的漏洞库、知识库、开源数据集,可用于商用训练;
- L2限范围使用:个人学习或研究可自由使用,商用需获取授权,比如部分SRC平台的报告;
- L3禁止训练使用:明确注明“禁止用于AI训练”或版权方持有异议数据,坚决不用。
这个分级表值得团队内部开会明确,因为一旦触雷,项目本身做得再好也可能面临下架和赔偿,对个人职业发展更是灾难。网络安全行业很看重合规操守,数据获取环节做干净了,后面任何审计问起来都能拿出一套清晰的文件记录,这也是向团队、向客户证明专业度的重要方式。
7. 多源数据融合策略与语料化实战
清洗和标注完成之后,数据的“半成品”状态就出来了,最后还要经过语料化处理,才能真正作为训练数据喂给模型。这一节的内容是容易被头脑发热的团队跳过但又极其重要的一环。
7.1 语料去重与比例再平衡
多源数据融合后第一件事是再做一次全局去重。之前每个数据源内部做了去重,但不同源之间可能存在大量交叉内容,比如同一个CVE的漏洞描述,NVD、CNVD、红帽公告、厂商博客各有一份,如果这四份全保留,模型会在训练中反复看到语义极度接近的内容,造成过拟合和知识分布扭曲。
全局去重后要做比例再平衡。漏洞描述类数据如果占了大头,要控制在一个合理区间内;恶意样本代码类数据虽然价值高,量也不需要无限堆,因为代码类数据的多样性有限,反复堆同类型代码对模型能力提升边际效应递减。这个比例在不同任务目标下要单独调整,不是一成不变的经验值。
7.2 指令微调样本的模板设计
如果目标是做指令微调(让模型像助手一样回答问题),需要设计一套统一的指令模板,把清洗后的安全数据转换成“用户提问-模型回答”的形式。这里给一个最基础的三段式模板参考:
用户:{用户问题} 助手:{标准回答}关键在于“用户问题”和“标准回答”的设计要贴近真实使用场景。以漏洞知识类数据为例,用户问题不应该是“CVE-2024-1234是什么”,而应该是“我的Web服务器是Apache 2.4.49版本,最近有安全团队报告这个版本存在路径穿越漏洞,请确认影响并给出修复方案”。标准回答也应该从CVE描述中提取“影响版本、漏洞类型、危害、修复建议”这些直接可用的信息,而不是把CVE描述原文贴一遍。
模板设计做完之后,要人工通读至少50条指令样本,确认语义通顺、答案正确性可验证。安全领域容错率极低,给出一个错误的修复建议可能意味着真实系统被打穿,这一步质量把关要拿出对待生产事故的态度。
7.3 RAG场景下的数据切块与索引
如果你的项目是给已有大模型做RAG增强而不是从零训练,那语料化的重点就变成数据切块和索引设计,而不是训练样本生成。这一块的经验可以和完整训练流程共享,因为RAG读到的上下文质量同样取决于数据获取的源头质量。
安全文档的切块不适合按固定字数硬切。漏洞分析文章通常有“概述-影响范围-技术细节-修复方案”的结构,硬切会把技术细节和修复方案割裂开。我建议按标题和段落边界智能切分,每个切块里包含尽量完整的上下文。索引字段除了文本嵌入向量之外,建议建立以下结构化过滤字段:CVE编号、时间范围、攻击类型、平台类型、数据来源,这样在检索时可以先用结构化字段过滤缩小范围,再做向量相似度检索,准确率提升很明显。
8. 实战经验:一次完整数据获取项目的复盘
最后这部分,我把自己做过的一个网络安全知识问答模型的数据获取项目做个复盘,把上面几节的内容完整串一遍,也把实际运行中遇到的问题和最后的取舍讲清楚。
8.1 项目规模与投入
目标模型是一个面向安全运维人员的知识问答和告警解释助手,能力范围包括漏洞问答、威胁情报解读、日志初步研判。团队三人,一名安全工程师负责数据源选择和标注校验,一名数据工程师负责采集和清洗管道,一名算法工程师负责语料化和训练对接。项目周期按三个自然月规划,其中六周全部花在了数据上,训练本身只占两周。
最终数据规模为正样本指令数据约15万条,预训练语料约8亿token。这个体量在安全垂直领域不算大,但因为样本质量集中在了核心能力上,最终模型的场景表现超出预期。
8.2 实际踩到的坑与处理方式
第一个坑是API限额。NVD的公开API有速率限制,不加控制地全量拉取很容易触发封禁,只能降低请求频率分批拉取,整个漏洞库拉完花了接近五天。后来发现下载NVD官方JSON数据包再本地导入更为高效,建议优先采用这种方式。
第二个坑是代码样本的“毒性”扩散。从GitHub拉取恶意代码样本后,直接在开发用的集群上做解压和分析,结果样本中的真实目标地址混入了代码索引库,花了大量时间做清理,更惊险的是差点让一台没有隔离的跳板机暴露了网段信息。后来专门分配了一台完全隔离的Linux虚拟机处理样本,所有样本只通过文件指纹传输到训练集群。
第三个坑是标签噪声。用通用LLM做预标注时,模型在“攻击类型”这类分类标签上准确率看起来不低(约90%),但人工复核发现它对“SQL注入”和“命令注入”这类细粒度分类容易搞混,而这恰恰是安全模型的核心能力。后来针对细分混淆项单独做了规则辅助纠错,并要求所有LLM预标注跳过低置信度样本(输出中带不确定措辞的),这类样本由人工标注兜底。
8.3 复盘后的优化方向
项目结束后,我们对数据获取流程做了几个优化决定:一是在采集源头就集成质量自检告警,避免脏数据流向下游;二是把数据源台账升级成全量管理,所有数据都记录生产时间和处理流转记录;三是搭建了一个轻量级数据样本可视化工具,供专家快速浏览和反馈标注质量。这三个动作看似不起眼,但对后续迭代效率的提升非常明显——数据管道不是一次性工程,而是一条持续喂养模型的生命线。
写在最后
做网络安全大模型,数据获取确实是最不性感的环节。没有刷榜的兴奋,没有推理时快感,有的只是无穷无尽的字段对齐和标签审核。但这是我在这条路上走下来最深的体会:一个安全模型的真实水平,在数据获取结束的那一天就基本确定了,剩下的训练和调优只是把已经存在数据里的能力释放出来。数据里的脏、偏、缺,模型会原汁原味还给你。所以如果你正准备启动一个安全大模型项目,我的建议是——先扎扎实实把数据管线做干净,再去纠结用什么基座模型、用什么训练技巧。地基夯实了,上面盖什么楼都稳。