本文的所有内容与作者的日常工作无关,其观点也仅代表作者个人意见,与作者的雇主无关。

用机器学习等算法解决网络安全问题常遇到数据模型与规则模型的效果之争,覆盖率与误报率的平衡,模型独检结果和防火墙整合的遥遥无期,这些都是数据科学家在设计算法时的纠结。然而一位资深安全研究员大哥喝高了一曲《有多少爱可以重来》扶着我吐露了他的内心:

“算法才分对错,攻防只讲成本”

数据模型的自我纠结以及与安全运营的矛盾都来自于脆弱的模型预测结果,或者说,很多数据模型只是给安全运营团队或者安全产品使用者抛出了一个半成品,导致了“你这个模型没法用”,“我为什么信你的结果”等等负面反馈。应用机器学习等算法解决网络安全问题并不仅是算法本身的工作,它是一个系统工程,其脆弱性来自于系统的每一步。接着上篇特征空间和样本标记的讨论,我们简单谈谈系统工程框架下如何理解算法的脆弱,工程的脆弱,以及运营的脆弱,并有效的避免其对解决方案的负面影响。这里的讨论也不仅限于网络安全行业,多数内容也适用于其他使用算法模型的工业界场景。

算法的脆弱

除了准确度召回率等衡量预测质量的指标,为解决网络安全领域问题设计的算法对预测结果的茁壮性也有若干特别的要求,最重要的是识别错误结果并且提供妥善的处置方法,就像基于机器视觉的自动驾驶一样,需要保证即使模型误判也不会撞墙。然而业界对这个主要原因的讨论甚至少于非平衡数据和小数据集标记等引起算法脆弱的其他原因。

错误的预测结果客观存在,作为算法提供方的数据科学家不能忽视,也不能惧怕它的存在。一个看似完美的 AUC 是多数论文的结论,而它只是所有工业界工作的开始。在机器学习论文里常见0.1% 误报率可能会被工业界以亿为基本计量单位的海量数据放大成几十万条运营数据,每一条预测结果数据都与运营的时间人力资源相关。因为运营或者产品团队关于误报带来成本的反馈,数据科学家作为算法的提供方惧怕误报,并限制了算法构建时的思路,比如说,为了极少的精度提高而在判别模型的召回率上的较大妥协,手工添加大量名单规则对结果过滤,甚至因为模型精确度没有上90%即放弃等等。忽视或者惧怕错误的预测结果是算法脆弱性的最主要原因。

与其忽视或惧怕,不如正视其成因并开始思考如何妥善处理。从算法角度来看误报,其最大原因是源自对事件观测的信息不全,这是网络安全在防守方的客观劣势。攻击方可以在多个角度设计并投入攻击资源,而防守方只能以自己观测到的部分建模,即使在防守方的资产上布满了完备的检测点,我们也很难完全透析攻击方的所有动作,更何况完备的检测点本身也是挂一漏万。正如鲁迅真的说过这样,“于是所见的人或事,就如同盲人摸象,摸着了脚,即以为象的样子像柱子。”* 在信息不全的情况下建模带来的不确定性要求从系统工程角度容忍不确定性并识别处理错误结果。

当然算法的脆弱来自于多个方面,我们也不能忽视数据集的选择偏差带来的算法偏向性,比如某犯罪预测模型默认地域和肤色与犯罪率的极高相关性,也不能削弱样本采集和标记的统计误差的影响,比如某保险风控模型认为100岁以上老人结婚率很低,更不能期望“未知的未知”威胁*可以通过已知的建模轻松解决,比如业界某些产品声称自己的 AI 模型可以检测并处理所有 APT 攻击。我们先从当前市场上最主要的脆弱性着手,一步一步前进。

工程的脆弱

业界绝大多数的论文不会涉及算法的工程实现,而工程实现上保证模型结果的可用性是脆弱的另一个主要来源,它包括上下游数据的可用性,算力的支持,监测和恢复系统等,同时数据可访问难度也是一个重要因素。

网络安全行业的多数算法模型根据自身或者客户平台采集的日志等数据源建模,这些日志由专门的团队负责采集,保存为互不相同的文件格式,有着不同的实时性和可靠性,并利用不同的数据平台输出,加之各种情报和第三方五花八门的格式,以及数据里各种字段的定义和冲突,这些学术论文里不会提到的数据采集的工作是数据科学家建模之前必须要面对的几件棘手工作之一。

即使能够顺利采集并整理出可用的数据集,稳定并及时的计算结果也是工程脆弱性的另一个因素。比如作者在实现前文提到的 domain2vec 这个将序列共现概率转化为几何向量空间的模型时,每小时约10亿条 DNS 记录要求的算力为其工程化带来不小的挑战。因为每个时间段的 DNS 数据流量可能有完全不同的模式,我们必须在该时间段内完成数据的采集和模型的计算,以避免结果的延迟和计算平台的阻塞。

数据质量和模型完成的监控与恢复也常被忽视,其负面影响直到出现重要事故或者入侵事件时才发现,模型本来可以检测并阻止这些事件的发生,但是因为上游数据的丢失或延迟、共用计算平台的排队过长、模型的白名单版本错误、模型代码 OOM 等原因,导致了最终结果的无效。有些安全团队和公司并不认为这些监控和恢复是核心工作,往往不投入足够的资源和优先级,而这恰好是“千里之堤溃于蚁穴”的典型案例。

在理想条件下,数据科学团队可以不受限制访问所需的数据,而在监管环境的要求以及公司利益的博弈下,数据的持有者和可以构建数据模型的团队并不能完美融合,这样的数据壁垒也是导致工程脆弱性的一个重要因素。

运营的脆弱

多数安全运营团队缺少处理模型预测结果的相关机制,它无形中推高了每个案例的运营成本,这是运营脆弱的主要原因,而网络安全对领域知识的门槛也使得数据科学团队难以助力。它主要有两方面因素,算法模型是否支持运营所需的信息,以及运营是否理解模型预测的结果。

数据科学家往往觉得模型的任务仅限于提供预测结果,如果正确就万事大吉,错误的话,大不了损失点召回率换精度也可以。可是正确的结果也需要运营,就好比模型检测出某个视频内含有暴恐内容,而运营团队需要一帧一帧查找这一个多小时的视频,又好比模型检测出新的 APT C&C,却让运营团队挨个排查几十台主机几百个进程和文件。正如坊间传言在亚马逊负责包裹分发算法的团队要跟着快递卡车送了一个月快递,对运营团队的工作置身事外的数据科学团队也做不出有效的数据模型。

运营团队的相关机制、工具框架以及培训也没有跟上数据科学时代的步伐。多数运营团队并不分级而是全力投入所有人力处理检测结果,这就导致了不管案例复杂程度都随机分配给团队中经验等级不同的安全研究员。同时,事件调查和进一步行动所需的上下文信息也分布在数据系统的各个角落,需要使用多种工具按需查询。安全研究员理解并使用算法的预测结果也有一定阻碍,包括对结果的归因分析,如何在例如防火墙等产品中应用预测结果,以及合理处置因预测的不确定性带来的影响等。这些阻碍带来的运营焦虑感进一步阻碍了安全研究员使用数据模型的结果,数据科学和安全运营团队的对话常常终结于“你就明确告诉我能不能阻断吧”。

在以上两个因素之上的,还有安全运营团队与数据科学团队因为领域知识构成的不同造成的沟通交流障碍也导致“反馈迭代”这个常规方法不能顺利执行,安全运营团队更看重对事件的作为个体的特点,同时也专注于特定事件的具体描述,而数据科学团队却因为背景知识的缺乏而难以从这些具体描述中剥离并抽象出模型上的共性,交流的双方总觉得鸡同鸭讲,讨论也没有什么结果。这些大大小小因素的堆积导致了运营的脆弱。

关于如何坚强起来的一些建议

从系统工程角度看,消除脆弱性及其影响差不多需要这些工作:

  • 识别错误的结果,并提供对正确和错误结果的解释。
  • 建立现代化成熟的数据仓库和相关工程框架,保证模型的可用性
  • 为模型预测结果的运营建立相关机制,提供工具和培训

这里的每一步都和其他工作相辅相成,实际工作中也有很多案例展示了改善算法修正工程难点,重新设计安全架构降低算法难度等方法。请各位小伙伴从系统工程这一整体来理解以下的建议。

算法需要收集错误结果的渠道。常见的误区来自于错误结果完全依靠用户反馈,这除了惹恼用户之外几乎没有任何意义,反而会导致海量的告警信息阻塞了运营队列,使得使用安全产品的团队或者运营团队不得不依照经验丢弃大部分告警以保证运营带宽。这种情况下,安全团队不仅没有时间提供反馈,甚至会让模型提供方误以为自己的模型很完美,而事实上是用户已经懒得理你了。合适的反馈渠道可以有多个阶段:

  • 基于模型特征的反馈:它一般是基于其他特征的规则或者机器模型。例如算法预测的鱼叉钓鱼页面是 google 首页,它可以通过与流量排序模型交叉验证并利用“高流量网站与鱼叉钓鱼的相关性很低”的事实排除。这类反馈利用多种其他特征有效补充了检测模型观测攻击模式时的视野局限,从理论基础上提供了反馈方式,并可标记绝大多数的错误。
  • 基于关联知识的反馈:如果一个预测结果是正确的,它的关联结果也应该是正确的,直到将关联延伸若干步骤达到一个错误结果。例如算法预测了某个域名为恶意软件 C&C ,它可以通过在 DNS 查询记录对应的 IP 记录关联延伸到沙箱里访问该 IP 的二进制在 VirusTotal 或者其他检测引擎或者安全团队的二进制文件分析结果,直到完成了整个链路的延伸。这类反馈利用了特征空间之外的第三方知识作独立验证,成本略高于模型特征的反馈,是模型特征反馈方法的有效补充。
  • 基于用户使用的反馈:经过前面几个阶段的努力,能够到达用户需要运营的结果已经很少。在算法提供的上下文信息的辅助下,用户可以结合自身的经验和更多的情报,对结果做出判断。这一步的用户反馈不仅是结果的正确与否,更重要的是用户根据哪些相关信息作出的判断。

算法也要尽可能的提供对预测结果的可解释性,不仅是错误结果,算法也需要解释正确的结果。其中包括解释算法本身所用的特征(常见于深度学习模型),标记并定位判断依据(比如恶意脚本代码段的具体哪一行),以及该预测结果的上下文信息(比如上文提到的关联知识,例如该二进制由某 URL 实行分发,该 URL 下的其他已知恶意行为等)。关于解释结果的重要性,这里有一个直观的例子:我们不难发现,在数据模型和规则模型的效果之争里,虽然数据模型在多数情况下有着漂亮的纸面指标,安全运营团队仍然倾向于规则模型。这是因为运营人员可以通过阅读规则本身理解模型依据,加上自身的安全经验,以及从模型提供的信息出发的进一步调研等后续工作,最终可以做出合理的判断。从这一思路出发,Sophos的AI团队开源了一套从机器学习模型的结果转译出相关 yara 规则的代码*,这是一份很有意思的工作,属于解释算法本身所用特征的方法,有兴趣的小伙伴可以自行阅读。值得指出的是,提高模型结果的解释性不只是转译成规则,同时规则模型也没有完美的提供解释性,我们依然没有银弹。

算法也需要提供对错误结果的快速处理方法以及部分的自动化,包括合适的分诊算法,添加足够的上下文信息以辅助运营等。可能是因为学术届和工业界对此的讨论有限,无论是在数据科学方向还是在安全研究方向,分诊算法(Triaging)常常被忽视。常见的场景是一个有效的异常检测模型因为其需要运营的预测事件数量较多而被放弃,这无论对数据科学团队还是安全运营团队都是一个巨大损失,而分诊算法可以有效的对预测结果按照运营优先级排序并合理的安排运营资源。一个例子是作者的同事在 2017 年 botconf 的演讲 Asiaee et al “Augmented Intelligence to Scale Humans Fighting Botnets”*,在每小时亿级的 DNS 日志流量里使用异常检测模型输出所有未见过的域名,并利用 domain2vec 构建域名之间的访问关联,以强关联模式作为运营的重要性指标做分诊排序,将每小时约千万级的异常事件降低到十几个有效的聚类,并成功应用到检测 DGA 恶意软件上。分诊算法有多种指标和方法,包含聚类、排序等,是一个与安全领域知识相关的数据科学方向,在此就不赘述,有兴趣的话可以以后再谈。

工程的脆弱性对业界有更广泛的影响,我们可以沿用别的领域带来的一般的解决方法,建立数据质量保证系统(Data Quality Assurance)。关于 DQA 的相关建设,请小伙伴们自行阅读参考文献,对这一成熟方向在此依然不需赘述。

工程脆弱性的另一个原因是在网络安全行业更为突出的的数据壁垒问题。除了一些开放数据组织或者联盟之外,技术上必须提到含隐私保护的数据模型工程实现,简单来说就是模型不需要数据明文即可学习并预测。这类方法中的比较广泛使用的是联合学习(Federated Learning),通过服务器-客户端的架构保证了模型和数据方的隐私,同时让模型得到需要的特征。这些联合学习的方法常见于一些 NDR 和 XDR 的初创企业产品中,暂时只在较为简单的一些场景上使用。在联合学习的实现上,FATE*通过一系列开源工作站稳了脚跟,有兴趣的小伙伴可以自行前往参考文献深入阅读。隐私保护计算利用了较高的计算成本在一定程度上缓解了数据壁垒问题,但根本上解决数据壁垒的工作还有很长一段路要走。

运营的脆弱需要数据科学团队和安全运营团地联手解决。在算法模型做到对结果的可解释性并且通过分诊算法将检测结果按重要性排序后,安全运营团队可以根据其提供的上下文快速的做出判断并决定后续的工作。同时,一些方便的数据工具可以帮助快速运营,比如方便好用的图数据库系统,这些可以由工程团队提供。与此同时作者观察到,对数据感兴趣的安全研究员可以是很好的老师,他们可以给数据科学家快速有效的教授相关背景知识,使数据科学团队更深入的理解安全问题并提出数据模型。这些跨越知识鸿沟的努力逐步解决运营的脆弱。

总结

网络安全专业对结果的脆弱性有较高的要求。有经验的网络安全专业研究人员可能也发现了,以上关于脆弱性的讨论也适用于例如使用第三方威胁情报等其他方面,解决脆弱性的一般方法在此也适用,比如使用云上或者运营商流量对威胁情报做进一步自动化验证等,限于篇幅在此就不赘述。同样,由安全研究员领域知识和经验出发的规则模型也面临着结果的脆弱性:巧妙的检测规则需要足够的解释性,大量的陈年老酒型白名单规则需要维护和更新以及对抗蓝军的试验和猜测,模型检出结果缺乏可用的分诊重要性排序等等,这些都是规则模型也需要面对的问题。作者在此抛砖引玉,希望有安全研究的专业人士对规则模型的脆弱性及其解决方法展开讨论。

对于数据科学家来说,从系统工程解决脆弱性甚至比提出有效的检测模型更为重要。在大家一直争论的规则模型和数据模型哪个更实用的同时,我们也看到很多不完美的规则或者数据模型在很好的工程实现和运营支持下得到不错的结果,规则模型和数据模型互相验证和分诊,而非互相竞争。这也提醒我们在构建数据模型的时候,要跳出思维局限的井底,从更宽广的系统工程视角解决问题。

同样,由网络安全专业的需求出发,我们从系统工程角度也对模型的脆弱性进行了讨论,这些讨论和其一般性解决方法也可以适用于图像、视频、语音、风控、自动控制等其他依赖数据模型的行业。总的来说,工业界依赖的数据模型从来都是一个系统工程问题,我们必须从系统工程角度思考设计和解决。

参考文献

https://github.com/sophos-ai/yaraml_rules