CWE视图层级关系的解析 之 CWE节点关系的查询
1. CWE转换成SQLite表
依据《CWE视图层级关系的解析 之 CWE节点的存储和定义》 中对CWE在xml文件中存储的结构和定义的描述。我们将CWE存储在xml文件中的信息转换到数据库中。数据库采用了轻量级的SQLite。
1.1. 存储CWE信息的数据库表
根据CWE的结构定义,提取了我们需要的主要信息,进行数据库表的设计。CWE数据库存储表的定义如下图:
- CWE数据库表的含义:
- cwe_node: CWE节点的主要信息;
- cwe_relation: CWE关联关系;
- cwe_applicable_platforms: CWE 适用的应用平台
- cwe_detection_method: CWE的检测方式
- cwe_taxonomy_mappings: CWE与业界规范的关系;
- cwe_demostrative_example: CWE的样例代码;
- cwe_observed_example: CWE观察到的示例;
- cwe_potential_mitigation: CWE的消减措施;
- cwe_attack_patterns: CWE的攻击模式;
- cwe_common_consequence: CWE造成的危害。
1.2. CWE节点和节点关系表的定义
本文重点关注CWE之间的关系,所以在这里只对CWE节点的定义和节点之间的关系表做了描述。两个表的定义如下:
-- CWE 节点的定义
DROP INDEX IF EXISTS "cwe_node_ind";
DROP TABLE IF EXISTS "cwe_node";
CREATE TABLE "cwe_node" (
"cweId" INTEGER NOT NULL UNIQUE,
"nodeType" TEXT NOT NULL,
"nameEn" TEXT NOT NULL,
"nameCn" TEXT DEFAULT '',
"status" TEXT DEFAULT '',
"filter" TEXT DEFAULT '',
"structure" TEXT DEFAULT '',
"description" TEXT DEFAULT '',
"extendedDscription" TEXT DEFAULT '',
"likelihoodOfExp" TEXT DEFAULT '',
"version" TEXT NOT NULL,
PRIMARY KEY("cweId")
);
CREATE INDEX "cwe_node_ind" ON "cwe_node" (
"cweId",
"nodeType"
);
-- CWE节点关系
DROP INDEX IF EXISTS "cwe_relation_ind";
DROP TABLE IF EXISTS "cwe_relation";
CREATE TABLE "cwe_relation" (
"cwe_relation_id" INTEGER NOT NULL UNIQUE,
"cweId" INTEGER NOT NULL,
"nodeType" TEXT NOT NULL,
"viewId" INTEGER NOT NULL,
"relation" TEXT NOT NULL,
"targetCweId" INTEGER NOT NULL,
"ordinal" TEXT DEFAULT '',
"version" TEXT NOT NULL,
PRIMARY KEY("cwe_relation_id" AUTOINCREMENT)
);
CREATE INDEX `cwe_relation_ind` on `cwe_relation` (`viewid`,`cweId`,`targetCweId`,`relation`);
1.3. 将xml的信息存储到数据库
- 解析CWE xml文件将xml种的信息存入Sqlite数据库,具体步骤略过(这个会代码的不难实现);
- 采用DB Browser for SQLite作为查询界面;
- 为了便于查询,我们将节点关系为"ChildOf"的类型都换成"Has_Member"。
1.4. 以CWE-1000 研究者视图为例
我们仍以CWE-1000 研究者视图为例:
select * from cwe_relation where viewId = 1000 and relation = 'Has_Member' order by cwe_relation_id
查询结果如下:共得到1077条记录。
2. CWE关系的查询
CWE之间的关系是以父、子节点的方式存储在表cwe_relation中的。SQLite提供了递归的查询方式来遍历树形结构。我们可以利用SQLite的这个特性来完成CWE间关系的查询。
我们先来介绍下这个特性的关键技术公用表表达式(Common Table Expression)。
2.1. 公用表表达式(Common Table Expression)
1999年,公用表表达式(Common Table Expression),简称CTE成为ANSI SQL 99标准的一部分。
CTE可以看做是一个临时的结果集。使用公用表达式CTE可以让语句更加清晰简练。
-
CTE带来的好处:
- 查询语句的可读性更好;
- 在一个查询中,可以被引用多次;
- 能够连接多个CTE;
- 能够创建递归查询;
- 能够提高SQL执行性能;
- 能够有效地替代视图
-
CTE和临时表、表变量的比较。
- 临时表:需要在临时数据库TempDB中通过I/O操作来创建表结构,一旦用户推出环境则自动被删除;
- 表变量:在内存中以表结构的形式存在,其定义与变量一致,其使用与表类似,不需要产生I/O;
- 公用表表达式:定义在内存中保存的临时存储结果集对象,不产生I/O,不需要按照表变量这样定义,使用方法和表类似。可以自己引用,也可以再查询中被多次引用。
-
公用表表达式的作用类似于仅在单个SQL语句期间存在的临时视图。按照是否递归,可以将公用表表达式分为递归公用表表达式和非递归公用表表达式:
- 普通: 普通的公共表表达式通过将主查询中的子查询分解出来,有助于使查询更易于理解;
- 递归公用表表达式: 提供了对树和图进行分层或递归查询的功能。
由于CTE的众多好处,特别是对树和图的处理能力的增强。各种数据库纷纷实现CTE功能:
- 2005年SQL Server2005版本的引入CTE;
- 2009年PostgreSQL 8.4版本的引入CTE;
- 2013年Oracle 12.1 版本的引入CTE;
- 2014年SQLite 3.8.3 版本的引入CTE;
- 2017年MySQL在8.0.1版本被引入CTE;
2.2. SQLite中的递归查询
- SQLite With的语法
递归公用表表达式可用于编写遍历树或图的查询。递归公用表表达式具有与普通公用表表达式相同的基本语法,但具有以下附加属性:
- "select-stmt"必须是复合select。也就是说,CTE主体必须是两个或多个单独的SELECT语句,这些语句由复合运算符(如UNION,UNION ALL,INTERSECT或EXCEPT)分隔。
- 组成该复合的单个SELECT语句中的一个或多个必须是“递归的”。如果SELECT语句的FROM子句恰好包含对CTE表(在AS子句的左侧命名的表)的一个引用,则该SELECT语句是递归的。
- 复合中的一个或多个SELECT语句必须是非递归的。
- 所有非递归SELECT语句必须出现在任何递归SELECT语句之前。
- 递归SELECT语句必须与非递归SELECT语句分开,并且必须由UNION或UNION ALL运算符彼此分开。如果有两个或多个递归SELECT语句,则必须使用相同的运算符将它们彼此分开,该运算符将第一个递归 * SELECT与最后一个非递归SELECT语句分开。
- 递归SELECT语句可能不使用 聚合函数或窗口函数。
递归公用表表达式必须类似于以下内容:
- 计算递归表内容的基本算法如下:
- 运行初始选择并将结果添加到队列中。
- 当队列不为空时:
- 从队列中提取一行。
- 将那一行插入递归表
- 假设刚提取的单行是递归表中的唯一行,然后运行递归选择,将所有结果添加到队列中。
2.3. CWE在视图中的位置
查找一个CWE在视图中的位置。可以转化成查找一个节点的父节点。
- 这里通过level字段来反映出所在节点的从最高层到当前节点的层级;
- 通过符号"->"来反映节点的链路关系。
例如:需要查找CWE-120在研究者视图CWE-1000中的位置。
-
CWE-120实际的位置
-
参考SQL
WITH RECURSIVE tc(level, targetCweId,target)
as (select 0 level,targetCweId, targetCweId target from cwe_relation where viewid=1000 and cweid = 1000 and relation='Has_Member'
UNION
select tc.level+1 level,r.targetCweId, tc.target||"->"||r.targetCweId target from cwe_relation r,tc where r.viewid=1000 and r.relation='Has_Member' and r.cweid = tc.targetCweId
)
SELECT * FROM tc where tc.targetCweId = 120
- 查询结果
level | targetCweId | target |
---|---|---|
3 | 120 | 664->118->119->120 |
从查询结果可以看到CWE-120的父节点依次为:CWE-119,CWE-118, CWE-664。这个结果与实际的页面展示相同。
- 注意:由于CWE在定义时,CWE之间不完全是正交关系,所以存在一个CWE 在不同分支的场景。在具体使用时需要用户对实际缺陷的上下文场景做分析后确认。例如:
CWE-425 直接请求(强制性浏览)就存在这种场景,如下面的查询结果。
level | targetCweId | target |
---|---|---|
2 | 425 | 693->424->425 |
3 | 425 | 284->285->862->425 |
3 | 425 | 284->287->288->425 |
4 | 425 | 710->657->638->424->425 |
5 | 425 | 284->285->862->638->424->425 |
2.4. CWE的子节点
查找某个CWE下包含的CWE。这个场景可以转化成查找某个节点的子节点来实现。
例如查找CWE-119的下所有的节点
- 参考SQL
WITH RECURSIVE tc(level, targetCweId,target)
as (select 0 level,targetCweId, targetCweId target from cwe_relation where viewid=1000 and cweid = 119 and relation='Has_Member'
UNION
select tc.level+1 level,r.targetCweId, tc.target||"->"||r.targetCweId target from cwe_relation r,tc where r.viewid=1000 and r.relation='Has_Member' and r.cweid = tc.targetCweId
)
SELECT * FROM tc
- 查询结果
level | targetCweId | target |
---|---|---|
0 | 120 | 120 |
0 | 125 | 125 |
0 | 466 | 466 |
0 | 680 | 680 |
0 | 786 | 786 |
0 | 787 | 787 |
0 | 788 | 788 |
0 | 805 | 805 |
0 | 822 | 822 |
0 | 823 | 823 |
0 | 824 | 824 |
0 | 825 | 825 |
1 | 785 | 120->785 |
1 | 126 | 125->126 |
1 | 127 | 125->127 |
1 | 124 | 786->124 |
1 | 127 | 786->127 |
1 | 121 | 787->121 |
1 | 122 | 787->122 |
1 | 123 | 787->123 |
1 | 124 | 787->124 |
1 | 121 | 788->121 |
1 | 122 | 788->122 |
1 | 126 | 788->126 |
1 | 806 | 805->806 |
1 | 415 | 825->415 |
1 | 416 | 825->416 |
3. CWE数据库中得到的其他信息
我们将CWE的信息转换到数据库后,还可以快速得到很多有用的统计信息。
3.1. CWE 关联的业界规范
CWE的外部视图中,很多是业界规范对CWE的映射关系。我们可以通过这些规范对CWE的覆盖情况来分析这些规范的侧重点和重合情况,从而在安全防御的措施制定时,根据自己的实际情况,进行全面的防御。
例如:查看CWE视图中关联的业界规范对CWE的引用情况。
- 参考SQL
select taxonomyName,count(*) from cwe_taxonomy_mappings m group by taxonomyName
- 查询结果
taxonomyName | count(*) |
---|---|
7 Pernicious Kingdoms | 89 |
CERT C Secure Coding | 228 |
CLASP | 105 |
Landwehr | 9 |
OMG ASCMM | 20 |
OMG ASCPEM | 15 |
OMG ASCRM | 29 |
OMG ASCSM | 22 |
OWASP Top Ten 2004 | 71 |
OWASP Top Ten 2007 | 31 |
PLOVER | 304 |
SEI CERT Oracle Coding Standard for Java | 8 |
SEI CERT Perl Coding Standard | 30 |
Software Fault Patterns | 296 |
The CERT Oracle Secure Coding Standard for Java (2011) | 139 |
WASC | 55 |
3.2. CWE的消减措施
查看CWE 所标识的安全消减措施,用于某些安全问题的安全防御。
例如查看CISQ规范关联CWE的风险消减措施。
- 参考SQL
select cweId,nodetype,
sum(case when phase='Requirements' then 1 else 0 end) as 'Requirements',
sum(case when phase='Architecture and Design' then 1 else 0 end) as 'Architecture and Design',
sum(case when phase='Documentation' then 1 else 0 end) as 'Documentation',
sum(case when phase='Build and Compilation' then 1 else 0 end) as 'Build and Compilation',
sum(case when phase='Implementation' then 1 else 0 end) as 'Implementation',
sum(case when phase='Testing' then 1 else 0 end) as 'Testing',
sum(case when phase='System Configuration' then 1 else 0 end) as 'System Configuration',
sum(case when phase='Operation' then 1 else 0 end) as 'Operation'
from (
select distinct a.cweid, a.nodeType,b.phase from (
select c.cweid, c.nodeType from cwe_relation r, cwe_node c where r.viewid=1340 and r.relation = 'Has_Member' and c.cweId= r.targetCweId ) a left join
(select * from cwe_potential_mitigation m) b on a.cweid=b.cweId
)a group by cweId,nodetype
- 查询结果(部分):
4. 参考:
- CWE: https://cwe.mitre.org/
- SQLite with子句: https://www.SQLite.net.cn/lang_with.html
5. 小结
- 设计了CWE Xml文件中存储的主要信息对应SQLite的数据库表;
- 简单介绍了数据库中公用表表达式(CTE)用于树或图的递归查询使用方法;
- 借助公用表表达式实现CWE在视图中所归属的分析信息(父节点)和所包含的CWE(子节点)的信息;
- 依据CWE数据库实现CWE收录的业界规范的关联关系的分析;
- 依据CWE数据库实现CISQ关联的CWE的弱点消减措施;
- 依据以上的分析,可以更好的帮助我们完成软件安全的全面防御。
- 点赞
- 收藏
- 关注作者
评论(0)