一文看懂漏洞管理中的CPE
大概是中文领域中讲解的最详细的一篇
0x00 什么是CPE
CPE(Common Platform Enumeration),中文译为通用枚举平台,是采用了一种结构化命名的方式,基于URI(Uniform Resource Identifiers)一种通用语法规则,通俗的讲:CPE是用来描述漏洞影响了哪些产品/组件的哪些版本。
在2011年8月,NIST发布CPE的最新版本2.3版,同时CPE 2.3版也包含在SCAP的1.2版本中。CPE 2.3版和过去的版本有着很大的改变,在新版本中设计了成为了一种堆栈式的结构,从栈低依次是Naming、Name Matching、Applicability Language、Dictionary。
1. Naming
我们大部分时间讨论的CPE,一般指的就是在Naming层中表示的CPE规则的描述,在新版规则中,定义了三种方式来描述CPE:
- WFN(well-formed CPE name):被称为格式良好的CPE名称,WFN是在一种面向人读的描述方式,CPE的命名规范定义了将WFN绑定到URI、FS和解绑的规则。(官方称这种规则转换为绑定,可以理解为转换)
- URI:URI是兼容旧版的一种机读描述方式
- FS(Formatted String):FS是新版增加具有格式化的机读描述方式
这三种描述方式可以相互转换,而在NVD看到漏洞详情页面展示的都是FS形式的。
1.1 WFN
WFN是一组无序的属性值对,用来描述软件、操作系统、硬件的逻辑结构。
我们先看一个例子:用WFN形式来描述Microsoft Internet Explorer 8.0.6001 Beta:
1 | wfn:[part="a",vendor="microsoft",product="internet_explorer",version="8\.0\.6001",update="beta"] |
在WFN中有下列这些属性:
- part:可以理解为分类,有三种分类:
- a:应用程序
- o:操作系统
- h:硬件设备
- vendor:创建产品个人或者组织/厂商
- product:产品标题或者名称
- version:由厂商提供用来表示产品的特定的发行版本
- update:同样是厂商提供表示产品的更新版本,比version范围更小
- edition:这个属性同样表示版本,属于被弃用的属性,一般是为了兼容更早CPE版本,默认值为ANY
- language:表示产品在操作界面所支持的语言
- sw_edition:表示产品是针对某些特定市场或类别的目标用户
- target_sw:产品运行需要的软件环境
- target_hw:产品运行需要的硬件环境
- other:表示无法归类上上述其他属性的值
如果在WFN未使用某个属性,则称为未指明的属性,默认值未ANY。sw_edition
target_sw
target_hw
other
是新引入的属性,被称作扩展属性。
WFN有两种逻辑属性值:
- ANY:任意值,当属性没有可接受值
- NA:不适用,该属性没有合法或者有意义的值
另外WFN对于值的规则,也有具体的描述:
- 首先WFN属性值应该是可以输出的UTF-8格式的非空连续字符串,十六进制编码位于x00-x7f之间,这意味着CPE中的字符限制为英文、数字和常见的一些符号,即时中文产品也需要用拼音或者有对应的英文名字的形式来表示
- 属性值用””包裹起来
- 可以使用大小写字符和数字
- 下划线可以使用,用来代替空白字符
- 可以使用反斜杠表示转义字符
- *号和?号有特殊含义,如果要使用请使用转义字符,*号和?的具体含义由其他CPE规定解释,可以加在字符串的开头和结尾
- 其他可以输出的非字母数字符号,在使用时需要放在引号内
下面是一些在WFN中可以使用值的例子:
1 | "foo\-bar" (hyphen is quoted) |
1.2 URI
接下来我们在看看URI,同样的先看一个例子:用URI方式来描述 Microsoft Internet Explorer 8.0.6001 Beta
。
1 | cpe:/a:microsoft:internet_explorer:8.0.6001:beta |
每个URI形式的名称都是以 cpe:
开始的,下图中采用来 ABNF 表示法,解释了 WFN 与 URI 的绑定关系:
1.3 FS
FS 是 CPE2.3 的新功能,它看起来和 URI 类似,前缀字符串为 cpe:2.3
,FS以固定的顺序绑定WFN,用冒号作为分隔:
1 | cpe:2.3:part:vendor:product:version:update:edition:language:sw_edition:target_sw: target_hw:other |
下图用 ABFN 解释了 FS 和 WFN 的绑定关系:
2. Name Matching
在上一节中描述了最基础的CPE名称的定义规则,在这一节将要说明CPE的匹配规则。
CPE名称匹配定义是将一种源CPE与目标CPE进行1对1比较的方法,简单来说,就是通过匹配规则来发现目标系统是上是否安装了目标产品,假设一个安全团队需要确定哪些主机上安装了Microsoft Internet Explorer 8,以及包括的各种小版本,这个时候可以使用WFN来表示:
1 | wfn:[part="a",vendor="microsoft",product="internet_explorer",version="8\.*",update=ANY,edition=ANY,language=ANY] |
使用符合 CPE 规则的资产管理工具收集信息,并搜索结果和上述WFN进行比较,假设报告为:
1 | wfn:[part="a",vendor="microsoft",product="internet_explorer",version="8\.0\.6001",update=NA,edition=NA,language="en\-us"] |
可以明确这个两个WFN(第一个为源WFN,第二个为目标WFN)的集合关系(相等,超集)。
在Name MAtching中定义了四种关系:
- ⊃:源是目标的超集
- ⊂:源是目标的字集
- =:源和目标相等
- ≠:源和目标不相交
3. Dictionary
Dictionary是CPE名称和与名称相关联的元数据存储库,Dictionary的中的每个CPE名称都标识了世界上的一类IT产品。举个例子:假如我有一台电脑,型号是MacBook Pro 2021,那么字典标识的类是MacBook Pro 2021这一类,而不是我手上这一台的实例。
Dictionary的数据表现方式和Naming一致,也是用三种不同的格式标识,常用的则是FS格式的表现方式。
Dictionary的数据模型通过标准的xml语法构建,它有三种不同前缀:
- cpe_dict:CPE Dictionary 2.3 XML模式
- cpe_dict_ext:CPE Dictionary 2.3 XML模式扩展类型
- cpe-name:CPE Naming类型的XML模式
采用cpe_dict
前缀通过一个树状结构来描述各个元素的关系:
<cpe_dict:cpe-list>
:根节点<cpe_dict:generator>
:文档的信息,包括Dictionary模式,时间,生成它应用程序的名称和版本<cpe_dict:product_name>
:生成Dictionary程序的名称<cpe_dict:prodyct_version>
:生成Dictionary程序的版本<cpe_dict:scheme_version>
:写入文档验证的架构版本<cpe_dict:timestamp>
:文件生成时间<cpe_dict:cpe-item name="" deprecated_by="" >
:单个字典条目的容器以及其元数据<cpe_dict:title>
<cpe_dict:notes>
<cpe_dict:references>
<cpe_dict:check>
<cpe_dict:cpe23-item>
在这个结构中我们只需要关注<cpe_dict:cpe23-item>中的CPE数据即可。
4. Applicability Language
Applicability Language被称作适用性语言,通俗的讲,Applicability Language也是通过标准的xml语法构建来一种CPE逻辑组合方式,来描述一个组合型产品。
举个例子:Photoshop 2021版这个软件出现了一个提权漏洞,但是只在windows7和windows10上实现,此时如果直接用CPE方式描述,无法描述出有平台依赖关系的CPE,这个时候就需要进行组合来描述,这也就是Applicability Language的简单的实例。
下面来说用XML如何描述这个“组合”:
1 | <cpe:platform-specification> |
先通过一个树状结构来描述各个元素的关系:
<cpe:platform-specification>
<cpe:platform>
<cpe:title>
<cpe:remark>
<cpe:logical-test>
<cpe:logical-test>
<cpe:logical-test>
- …
<cpe:fact-reft>
<cpe:check-fact-ref>
<cpe:fact-reft>
<cpe:check-fact-ref>
<cpe:platform-specification>
作为XML文件最外层的根节点,也可以称为一个容器,在一个文件中只存在一个,并且是在最外层。在<cpe:platform-specification>
的下一层就是<cpe:platform>
<cpe:platform>
表示多个CPE组成的平台,并且有一个属性是id,在同一个容器中,id要保持唯,同时在一个容器中可以有多个平台。
在<cpe:platform>
的下一层包含三个元素<cpe:title>
、<cpe:remark>
、<cpe:logical-test>
,<cpe:title>
表示这个平台的名称,可以支持多个<cpe:title>
,用来区分不同语言。<cpe:remark>
表示是对这个平台的评论或者描述,也支持多条描述,但在大多数时候都是空的。<cpe:logical-test>
表示这个平台的下的第一层逻辑关系,在与<cpe:platform>
直接接触这一层,只存在一个<cpe:logical-test>
,而在它之下可以无限嵌套或平行<cpe:logical-test>
来构建组合。
<cpe:logical-test>
有两个属性值:operator
表示下一层各个元素之间但关系,它有两个值,AND和OR。另外一个是negate
,表示对operator
计算结果是否进行取反操作。
另外在每一个<cpe:logical-test>
之下还有另外两个元素,<cpe:fact-reft>
就是CPE一条规则。<cpe:check-fact-reft>
则是对<cpe:fact-reft>
的检查描述信息,大多数时间也是空的。
0x01 NVD网站上的CPE怎么看
NVD漏洞详情页面上提供了三种类型的CPE匹配信息:Basic
、Running on/with
、Advanced
,不管哪一种信息,都提供了一个Configuration
,这个可以理解为一个容器,并且是安装顺序序号排列下来的。
1. Basic
在Basic中也存在不同的情况:
1.1 第一种
第一种是最简单的,NVD提供了一个匹配的语法,只要点击Show Matching CPE(s)即可看到最终从Dictionary匹配出的结果
1.2 第二种
第二种告诉了匹配这条CPE时候,update字段的上限
1.3 第三种
第三种,则提供匹配的下限和上限
2. Running on/with
在Running on/with种则是一种特定组合关系,它的意思Running on/with上面的CPE信息需要依赖下面的环境,才能触发该漏洞。
3. Advanced
Advanced则提供了在Applicability Language种完整组合关系的这种。产生更复杂依赖关系。
在实际情况种Basic和Running on/with基本涵盖了几乎全部数据,只有少量会出现Advanced的这种情况。
0x02 总结
上述内容详细描述了各个模块的定义与说明。简单来说,在Naming中,定义了基本的CPE的写法;在Dictionary中,是所有细化的产品的枚举字典,而在Name Matching定义了怎么通过cpe匹配模式,匹配出最终的目标产品。而在Applicability Language中,则定义了一种基于逻辑结构的cpe高级用法,可以进行多个CPE的组合形式,来描述IT平台。
在NVD的漏洞详情页面,有三种形式的展示方式:
- Basic:最基本匹配方式,直接可以通过给出cpe匹配范围,直接进行匹配,然后得出cpe字典列表
- Running On/With:一种组合的匹配方式,
- Advanced:一种组合的匹配方式
0x03 官方文档
https://csrc.nist.gov/projects/security-content-automation-protocol/specifications/cpe
0x04 一个处理CPE的Py包
备注:这个包在处理CPE2.3版本时候到匹配有BUG,需要使用2.2版本来进行匹配,然后用2.3版本输出,算是一个曲线救国的方式。
0x05 参考链接
https://nvd.nist.gov/vuln/vulnerability-detail-pages
https://www.fooying.com/common_vulnerability_management_and_scap/