- 本文参考多篇文章写作而成,出处在文末注明(本文在课题开展过程中长期保持更新)。
二进制成分分析
SCA(Software Composition Analysis)软件成分分析,通俗的理解就是通过分析软件包含的一些信息和特征来实现对该软件的识别、管理、追踪的技术。通常用来对软件源码、二进制软件包等进行静态分析,挖掘其所存在的开源合规、已知漏洞等安全合规风险,是一种业界常见的安全测试手段。
SCA关注的对象是从文件层面的文件内容,以及文件与文件之间的关联关系以及彼此组合成目标的过程细节。由于SCA分析过程中不需要把目标程序运行起来,因此具有分析过程对外部依赖少,分析全面,快捷、效率高的优点;
源码SCA的检测对象为源代码,适合在软件编码开发和构建时使用,可以尽早的发现问题,实现安全测试左移。二进制SCA的检测对象为二进制软件包,可以在软件测试、发布和运维阶段使用,它不需要源代码测试更方便,同时具备所见即所得的长处—测试结果反映的就是终端用户使用软件的情况,同时也很好的规避和解决了一些会引起源码SCA检测不了或检测不准的场景(比如:引用的二进制开发库,只引用开源软件部分功能代码等)。
产品包或固件中因不当使用开源软件、配置不合规等会产生漏洞或合规性风险,及时的发现和修复相关问题可以减少被攻击者利用的风险。通过二进制成分分析可以做到对产品包/固件进行全面分析,基于各类检测规则,获得相关被测对象的开源软件、信息泄露、安全配置等存在的潜在风险。
支持平台,如:桌面应用(Windows和Linux)、移动应用程序(APK、IPA、Hap等)、嵌入式系统固件等。
扫描原理
对用户提供的软件包/固件进行全面分析,通过解压获取包中所有待分析文件,基于组件特征识别技术以及各种风险检测规则,获得相关被测对象的组件BOM清单和潜在风险清单。主要包括以下几类:
- 开源软件风险:检测包中的开源软件风险,如已知漏洞、License合规等。
- 安全配置风险:检测包中配置类风险,如硬编码凭证、敏感文件(如密钥、证书、调试工具等)问题、OS认证和访问控制类问题等。
- 信息泄露风险:检测包中信息泄露风险,如IP泄露、硬编码密钥、弱口令、 GIT/SVN仓泄露等风险。
组件识别技术难点: 如何根据二进制文件识别出含有的组件和对应的版本。 问题转化为 ==> 二进制代码相似性检测问题。
同时,为了符合工业界生产环境使用的需要,在细粒度的组件识别和版本识别上要兼顾准确率和效率。传统方法很难做到兼顾,因此需要研究基于深度学习的方法。
从SCA原理可以知道影响分析准确性的因素分两个方面:其一是SCA工具支持组件的数量和检测算法,其二是应用程序引用开源软件的方式。因为SCA工具是根据样本组件特征来匹配被测程序中的特征来判断应用程序是否引用该组件的,因此支持组件的数量越多,那么检测率也就越高,支持的组件数量越少,越会导致检测遗漏;另外检测算法和特征设计是否合理也直接影响到分析的准确性和分析效率。
应用程序在引用开源软件时,不同的应用程序即使引用同一个组件也存在引用不同的功能,引用功能的多少也各不相同,这样带来的结果就是在应用程序中包含该组件的特征数量也是大小不同的,引用功能多包含的特征一般也多,引用的功能少包含的特征也少。而应用程序包含组件特征的多少直接影响到SCA工具的检测的准确性,组件特征越少SCA工具检测越困难,因此即使两个不同应用都引用了相同组件,可能一个应用可以检测到,另外一个应用则无法检测出该组件。这种场景对SCA工具检测二进制文件尤其明显。
- 二进制文件的SCA检测能发现构建过程中工具链引入的安全问题,而源代码的SCA则不能,SolarWinds事件就很好的说明了这一点。
- 目前SCA工具检测开源软件的已知漏洞是基于组件名称+版本号来关联出已知漏洞的,对部分编译场景(只有部分组件代码被编译到二进制文件中)和patch打补丁场景(漏洞已修复),误报率高。
实现思路:二进制代码相似性检测
编译生成二进制代码的影响因素非常的多,同一套源代码基于不同因素的组合可以生成非常多不同二进制程序。
- CPU架构:X86、ARM、MIPS、PPC、RISC-V;
- 架构位数:32bits、64bits;
- OS:Linux、Windows、Android、鸿蒙、VxWork;
- 编译选项:O0~O3;
- 安全编译选项:BIND_NOW、NX、PIC、PIE、RELRO、SP、FS、Ftrapv等;
从源代码编译生成二进制过程中,有很多有助于理解代码意图的信息会被丢失,比如:函数名称、变量名称、数据结构定义、变量类型定义、注释信息等;其次,为了更好的保护二进制代码的知识产权或最大程度的提升对二进制代码的理解难度,还会对二进制代码进行混淆处理,使得混淆后的二进制代码与编译器编译出来的二进制之间又存在很大的不同。
《A Survey of Binary Code Similarity》根据过往在顶级期刊和会议上发表的相关文献做一个总结:
输入比较: 一对一(21种)、一对多(30种)、多对多(10种);
比较方法: 大多数方法使用单一类型的比较:相似性(42种)、等效性(5种)和相同(2种);即使方法中仅使用一种类型的比较,它也可能有不同的输入比较不同;
分析粒度: 分为输入粒度、方法粒度;有8种不同的比较粒度,分别是指令级、基本块、函数以及相关集合、执行轨迹、程序。
- 最常见的输入粒度是函数(26个),然后是整个程序(25个)和相关的基本块(4)
- 最常见的方法粒度是函数(30个),然后是基本块(20)
语法相似性: 通过语法方法来捕获代码表示的相似性,更具体地说,它们比较指令序列。最常见的是序列中的指令在虚拟地址空间中是连续的,属于同一函数。
语义相似性: 语义相似性是指所比较的代码是否具有类似的效果,而语法相似性则是指代码表示中的相似性。其中有26种计算语义相似度的方法。它们中的大多数以基本块粒度捕获语义,因为基本块是没有控制流的直线代码。有三种方法用于捕获语义:指令分类、输入-输出对和符号公式。
结构相似度: 结构相似性计算二进制代码的图表示上的相似性。它位于句法和语义相似性之间,因为图可以捕获同一代码的多个句法表示,并可以用语义信息注释。结构相似性可以在不同的图上计算。常见的有控制流图CFG、过程间控制流图ICFG、调用图CG;(子)图同构—大多数结构相似性方法是检查图同构的变化,其中涉及到方法有K子图匹配、路径相似性、图嵌入。
基于特征的相似度: 计算相似性的常见方法(28种)是将一段二进制代码表示为向量或一组特征,使得类似的二进制代码具有相似的特征向量或特征集。这里应用最多的是利用机器学习来实现。
Hash匹配相似度: 对于多维向量数据相似度快速匹配,通常使用局部敏感hash算法LSH来实现。
跨架构比较方法: 对不同CPU架构二进制代码的相似度比较,通常跨体系结构方法通过计算语义相似性来实现。方法之一是通过转换成与架构无关的中间语言IR来处理(7种),另外一种是使用基于特征的相似性方法(9种)。
分析类型: 从分析类型来看有:静态分析、动态分析、数据流分析3种类型;
归一化方法: 语法相似性方法通常会对指令进行规范化,来尽量减少语法上的差异;有33种方法使用指令规范化。具体的包括操作数移除法、操作数归一化法、助记符归一化法。
Reference
- 带你了解几种二进制代码相似度比较技术 华为云开发者联盟 安全技术猿
- 成分分析的扫描原理是什么,主要识别哪些风险? 华为云漏洞扫描服务 VSS 文档
- 漫谈软件成分分析(SCA)安全测试技术 安全技术猿