13《不要将错误配置归咎于用户》
[x]SPEX用于从软件源代码自动推断配置需求(称为约束),然后使用推断出的约束:(1)暴露错误配置漏洞(即,系统对配置错误的不良反应,如崩溃、挂起、无声故障);以及(2)检测某些类型的易出错配置设计和处理。
一个配置参数的约束规定了它的数据类型、格式、取值范围、与其他参数的依赖性和关联性等,
方法:通过分析配置参数的读取和使用方式,从源代码中自动推断配置约束。1)通过注入违反约束的错误来加固系统,以暴露错误配置的漏洞;(2)检测某些类型的容易出错的配置设计和处理,以使其更加方便用户。
-
数据类型有两类:基本类型(整数、字符、布尔值、浮点数、字符串等)和语义类型("字符串 "参数可能指的是一个文件路径或一个IP地址)。
-
值范围。配置参数可以通过一些可接受的有效值范围来进一步约束,比如最小值和最大值,或者像枚举式那样的可接受值列表。
-
控制依赖性。多个配置参数可能有依赖性。(P,V,⋄)→Q,这意味着参数Q的使用依赖于参数P的设置,条件是P⋄V,其中⋄∈{<,>,=,!=,≥,≤},而V是一个常值。
-
值的关系。除了两个参数之间的控制依存关系外,它们的值的关系也可能施加约束。Ӏft_max_word_lenӀ should be greater than Ӏft_min_word_lenӀ.
推断约束条件:SPEX首先需要识别源代码中的配置变量。然后,它跟踪与配置参数相对应的每个程序变量的数据流,并记录在数据流路径上发现的任何约束条件。
-
SPEX对源代码进行了两次扫描。在第一遍中,它推断每个参数的数据流路径,并寻找每个参数的数据类型和数据范围约束。
-
为了进一步推断涉及多个参数的约束(即控制依赖和值关系),SPEX再次扫描代码,但这次只扫描包含每个参数的数据流的程序片。
-
将 参数映射到变量 :三个接口之一将配置参数映射到程序变量中:结构(struct config_int ConfigureNamesInt[])、比较(strcasecmp)和容器(所有的配置参数存储在一个中央容器中,并使用普通的getter函数来检索值)。
-
类型推断: SPEX从源代码中的类型信息推断出每个参数的基本类型。 SPEX通过沿着参数的整个数据流路径搜索以下模式来推断语义类型约束:
-
参数被传递给已知的函数调用(例如,系统和库调用)或已知的数据结构;
-
参数与已知函数调用的返回值(例如,时间系统调用的返回值)相比较,或者被分配给已知的函数调用。
-
-
数据范围推断: SPEX推断两种类型的范围:数值型和枚举型。
-
对于数字比较,SPEX将常数视为数据范围的阈值。
-
如果参数被用于开关语句或 "if...else if...else "逻辑中,则推断出枚举范围。 图3(d)显示了OpenLDAP的一个范围推断的例子,其中 "index intlen "的范围被分为(-∞,4),[4,255],和(255,+∞)。(-∞,4)和(255,+∞)都是无效的,因为参数在这些范围内被重置。
-
-
控制依赖性推断: 从一个参数Q的使用语句开始,以自下而上的方式寻找支配这些语句的条件分支。如果条件涉及的变量是另一个参数P的数据流的一部分,SPEX就会以(P,V,⋄)→Q的形式记录P和Q之间的控制依赖关系。
-
值关系推断: 如果来自不同参数的数据流路径的两个变量相互比较,SPEX就会以P⋄Q的形式推断出这两个参数的价值关系。
-
60%的研究良好实践建议是具体的( 建议将其设置为大于2000 ),而不仅仅是一般性建议( 建议将其设置为较大值 )。
-
97%手册中推荐的特定良好实践未在源代码中检查。
-
61%的具体良好做法建议不等同于默认设置。
-
六份研究手册的组织结构相似。六本手册采用HTML或XML格式,其中的参数以类似的结构描述:<key>:<value>
-
将手动文本分成句子,并通过两个过滤步骤提取推荐句子:基于关键词的过滤(粗粒度)和基于句法模式的过滤(细粒度)。
-
首先识别推荐语句中的语义实体(例如,参数名称和值),然后通过将它们与语义模式匹配,将其转换为正式规范。
-
将软件手册预处理并解析为 参数名称、元信息( 类型和默认值 )和自由文本描述。
-
过滤包含建议语句:
-
关键字: 例如“recommend”、“suggest” ,将研究的 261 个推荐句子分解为单个单词和二元组(两个连续单词),并将它们用作候选关键字 T。PracExtractor 使用逆文档频率(IDF)对候选关键词进行排名。
-
基于 句法模式的过滤:经过关键词过滤后,剩下的句子中有 7.3% 是推荐的。 推荐还包含一个设置短语,一个描述推荐什么设置的名词/动词短语。这样的设定短语和关键词之间,存在一定的句法关系(模式),这在非推荐句中是不存在的。 ( amod——从名词到形容词修饰语的链接; nsubj – 动词/名词和介词短语之间的关系; attr – 动词/形容词和补语等之间的关系。)
-

-
规范生成-- 最简单的是将设置短语与预定义的正则表达式匹配并相应地转换它们
-
-
-
识别参数名称: 识别句子与哪个参数相关联。 参数X相关的段落p中的推荐句子s,有四种可能的情况 1)s中只提到X。 2) s中提到了另一个参数Y。 3) s 中没有提到参数。 4)p中没有提到参数,PracExtractor判断句子是针对X的
-
识别设置实体: 根据相关参数的类型从设置短语中识别设置实体(例如值和格式), 可以识别的七种 :<parameter> 用于设置短语描述当前参数相对于另一个参数的情况,例如“设置A 大于B”。 <format>,PracExtractor 根据单词匹配识别参数的常见格式(例如“电子邮件地址”、“绝对路径”)。 所有其他单词/短语都被标识为<string>。
-
-
生成规范: 将设置短语与预定义的语义模式匹配来生成可检查的正式规范。
-
-
检查否定: 检测推荐句子中的否定,并在必要时否定规范。 PracExtractor 在句子中查找直接否定词,例如“not”, “none”和“never”,此外 检测间接否定词和短语,例如“避免”、“谨慎”、“很少”和“很少”等,以识别否定。
-
-
配置中的 违规检测: PracExtractor 根据提取的规范检查解析的参数值,并在检测到违规时生成警告消息。
-
一般统计数据包括可从源代码中提取的配置约束的比例、具有不同基本类型的配置选项的配置约束比例,以及源代码中配置变量的一般存在形式。
-
特定类型约束的一般特征主要集中在各种形式的配置约束、枚举约束的集群定义和声明以及可用于约束的语义信息提取。
-
提取配置约束的障碍主要在于结构配置选项和资源相关配置选项。
-
首先,对于使用统一映射结构的配置选项,我们通过统计分析以及一些语义信息提取了这些配置选项的数值范围。
-
然后,考虑到用于枚举的集群代码段,使用一些文本分析来提取枚举配置选项的值空间。
-
最后,利用函数参数标识符的一些语义信息,我们改进了数据流分析,以获得配置选项的语义。
-
首先,通过搜索官方文档和手册,为每个研究过的软件包构建了配置选项的集合。
-
建立了配置文件中的配置选项与目标软件源代码中的程序变量之间的映射关系。(假设:配置变量通常直接使用,而无需复杂的分配和传播)
-
分类 :
值范围 数值配置选项应满足的值范围。 枚举枚举配置选项应满足的值空间。语义 配置选项的语义含义。值控制多值关系一个配置选项的使用依赖于另一个配置选项。两个或多个不同的配置选项的值关系应该满足。-
复杂类型,它涵盖了所有结构配置选项和软件特定的封装配置选
-
配置类型分为简单类型和复杂类型,其中简单类型包括数字、字符串和枚举
-
-
-
一维约束由语义、值范围和枚举组成,
-
多维约束包括值控制和多值关系。
-
主要考虑五种语义含义,即文件、目录、端口、IP和URL。
-
只有数字配置选项具有值范围约束。
-
枚举指的是配置选项可以分配给的值空间。
-
值控制关系中,配置选项是否生效取决于另一配置选项的值
-
多值关系确定了两个或多个不同配置选项的值应满足的条件。
-
-
-
基于程序分析,我们平均能够提取64%的各种代码形式的配置约束,而当前的研究仅涵盖27%,主要是在if语句情况下。
-
数字配置选项检查得更好,而字符串类型的配置选项检查总是很差。
-
不同软件包中变量的形式可能不同,但它们主要是全局变量或全局结构的成员。
-
配置约束有多种形式,而不是if条件语句。(大多数数值约束是在结构中进行配置选项和相关配置变量之间的映射;我们相应地将它们称为映射约束)
-
不同的软件包中使用了各种形式的枚举约束,而不仅仅限于切换case语句的情况
-
语义信息隐含在使用配置选项的函数的参数中。(使用数据流信息追溯到已知的库函数,)dymap_init(path,var_shlib_directory)
-
由于不同类型软件中的各种结构形式,没有成熟的方法来处理结构配置选项和配置选项的影响范围。
-
大多数研究的软件包没有足够的资源相关配置选项检查机制。
-
为了获取软件系统的日志记录,我们选择注入配置错误,生成与配置选项相关的日志记录
-
日志分析: 如果一条日志记录满足以下条件之一,我们就认为它与被测选项有关:
-
日志记录包含被测选项的名称;
-
它包含选项中所有与普通分隔符相连的词;
-
它包含在配置文件中找到该选项的位置信息(行号)。
-
如果日志记录与被测选项有关,并且为修复配置错误提供了指导,我们认为它包含了配置约束。
-
-
57.0%的配置选项在日志记录中有约束描述。
-
12.5%的日志信息没有明确呈现在日志语句中,而是以各种样式存在,隐含数据流到日志语句中。
-
77.6%的配置选项的日志信息并不包含选项名称。
-
51.8%的配置相关的日志信息可以通过直接匹配日志信息中的选项名称,或找到相关的函数或变量来识别,这意味着识别配置相关的日志信息的可行性。
-
剩下的48.2%的配置选项,根据发现4无法识别相关的日志信息,它们都是数字或布尔类型,并通过一般的逻辑与特定结构中的预定义信息来处理。
-
日志信息选择--> ConfInLog将代码中所有的字符串常量都视为候选日志信息。 一条日志信息可能由几个字符串常量、变量和宏拼接而成,ConfInLog首先将变量转换为特殊标签"_VARIABLE_",并替换常量和宏,然后将它们连接起来。

-
识别配置相关日志信息的直接方法是检查日志信息中是否包含选项名称信息。
-
寻找与日志信息隐含相关的配置选项. 主要关注与配置选项相关的函数和变量。
-
收集配置选项的相关代码元素
-
如果配置选项的名称字符串在为配置-变量映射定义的结构接口中使用,ConfInLog就会使用最小公因式算法来收集配置变量和配置函数。
-
如果配置选项被映射到容器接口的变量上(基于getter api读取配置值),ConfInLog会收集返回变量作为配置变量。
-
对于比较接口,如果一个配置选项在类似strcmp的条件下被使用,并且后继块少于3行,ConfInLog将收集后继块中assign语句的左边变量作为配置变量。
-
-
日志信息的后向切分
-
从包含日志消息的语句开始切分。一旦在切片中得到一个变量或函数,ConfInLog就会检查它是否是一个配置变量或函数,如果是的话,就认为该日志消息与这个配置选项有关.
-
-
互补性相似性比较
-
某些情况下,ConfInLog没有收集到配置变量,或没有匹配的配置函数, ConfInLog就会应用一种近似的方法,根据配置选项和分片中的变量之间的相似性来识别与配置相关的日志信息。 将配置变量命名为与选项相似的名称
-
-
-
约束推断: 获得了与配置相关的日志信息之后, 用了一种基于NLP(自然语言处理)模式的方法来表示配置约束的描述。 使用POS(Part-Of-Speech)标签序列来表示这些描述,xxxxx