2.6. 污点分析配置

Clang 静态分析器使用污点分析来检测代码中与注入漏洞相关的安全问题。Clang SA 中污点分析的核心是 TaintPropagation 模型检查器。报告通过 optin.taint.GenericTaint (C, C++) 检查器发出。 TaintPropagation 检查器有一个默认的与污点相关的配置。内置的默认设置在代码中定义,并且始终生效。检查器还提供一个配置接口,通过 optin.taint.TaintPropagation:Config 检查器配置参数,通过在 YAML 格式的 YAML 格式提供配置文件来扩展默认设置。本文档描述了配置文件的语法,并给出了配置选项的非正式语义。

2.6.1. 概述

污点分析通过检查程序符号执行期间发生的特殊操作来工作。污点分析定义了源、接收器和传播规则。它通过检测从污点源开始,到达污点接收器,并通过传播规则在程序路径中传播的信息流来识别错误。源、接收器或传播污点的操作主要属于特定领域,但 TaintPropagation 检查器提供了一些内置的默认值。可以通过在外部配置中提供 Filters 部分来表达语句对受污点值的清理(参见 示例配置文件过滤器语法和语义)。内置设置中没有定义默认过滤器。检查器文档还指定了如何使用命令行选项提供自定义污点配置。

2.6.2. 示例配置文件

# The entries that specify arguments use 0-based indexing when specifying
# input arguments, and -1 is used to denote the return value.

Filters:
  # Filter functions
  # Taint is sanitized when tainted variables are pass arguments to filters.

  # Filter function
  #   void cleanse_first_arg(int* arg)
  #
  # Result example:
  #   int x; // x is tainted
  #   cleanse_first_arg(&x); // x is not tainted after the call
  - Name: cleanse_first_arg
    Args: [0]

Propagations:
  # Source functions
  # The omission of SrcArgs key indicates unconditional taint propagation,
  # which is conceptually what a source does.

  # Source function
  #   size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream)
  #
  # Result example:
  #   FILE* f = fopen("file.txt");
  #   char buf[1024];
  #   size_t read = fread(buf, sizeof(buf[0]), sizeof(buf)/sizeof(buf[0]), f);
  #   // both read and buf are tainted
  - Name: fread
    DstArgs: [0, -1]

  # Propagation functions
  # The presence of SrcArgs key indicates conditional taint propagation,
  # which is conceptually what a propagator does.

  # Propagation function
  #   char *dirname(char *path)
  #
  # Result example:
  #   char* path = read_path();
  #   char* dir = dirname(path);
  #   // dir is tainted if path was tainted
  - Name: dirname
    SrcArgs: [0]
    DstArgs: [-1]

Sinks:
  # Sink functions
  # If taint reaches any of the arguments specified, a warning is emitted.

  # Sink function
  #   int system(const char* command)
  #
  # Result example:
  #   const char* command = read_command();
  #   system(command); // emit diagnostic if command is tainted
  - Name: system
    Args: [0]

在上面的示例文件中,Propagation 键下的条目实现了概念上的源和传播,而接收器有其专用的 Sinks 键。用户可以通过列出 Filters 键下的条目来定义应该清理受污点值的运算(函数调用)。过滤器模拟程序员对值的清理,提供这些过滤器对于避免误报至关重要。

2.6.3. 配置文件语法和语义

配置文件应具有有效的 YAML 语法。

配置文件可以具有以下顶级键
  • Filters

  • Propagations

  • Sinks

Filters 键下,用户可以指定移除污点的一系列操作(有关详细信息,请参见 过滤器语法和语义)。

Propagations 键下,用户可以指定一系列引入和传播污点的操作(有关详细信息,请参见 传播语法和语义)。用户可以在 Propagation 键中使用 SrcArgs 键来标记污点源,而传播则没有。缺少 SrcArgs 键表示无条件传播,这就是建模源的方式。传播的语义是这样的,如果任何源参数被污染(由 SrcArgs 中的索引指定),那么所有目标参数(由 DstArgs 中的索引指定)也将被污染。

Sinks 键下,用户可以指定一系列操作,如果受污点数据到达这些操作,检查器将发出错误报告(有关详细信息,请参见 接收器语法和语义)。

2.6.3.1. 过滤器语法和语义

Filters 下的条目是一个 YAML 对象,具有以下必填键
  • Name 是一个字符串,指定函数的名称。在符号执行期间遇到此函数时,检查器将清理给定参数所指的内存区域的污点,或返回一个清理过的值。

  • Args 是一个 [-1..int_max] 范围内的数字列表。它指示函数调用中参数的索引。数字 -1 表示返回值;其他数字标识调用参数。这些参数的值在函数调用后被视为干净的。

以下键是可选的
  • Scope 是一个字符串,指定函数在其完全限定名称中的名称前缀。此选项限制了匹配函数调用的集合。它不仅可以编码命名空间,还可以编码结构/类名称以匹配成员函数。

2.6.3.2. 传播语法和语义

Propagation 下的条目是一个 YAML 对象,具有以下必填键
  • Name 是一个字符串,指定函数的名称。在符号执行期间遇到此函数时,将从一个或多个参数传播污点到其他参数,并可能传播到返回值。它有助于模拟函数的与污点相关的行为,而这些函数在其他情况下无法分析。

以下键是可选的
  • Scope 是一个字符串,指定函数在其完全限定名称中的名称前缀。此选项限制了匹配函数调用的集合。

  • SrcArgs 是一个 [0..int_max] 范围内的数字列表,指示函数调用中参数的索引。污点传播在评估函数调用时考虑这些参数的值。如果任何 SrcArgs 参数被污染,则检查器将在调用后将所有 DstArgs 参数视为污染的。

  • DstArgs 是一个 [-1..int_max] 范围内的数字列表,指示函数调用中参数的索引。数字 -1 指定函数的返回值。如果任何 SrcArgs 参数被污染,则检查器将在调用后将所有 DstArgs 参数视为污染的。

  • VariadicType 是一个字符串,可以是 NoneDstSrc 之一。它与 VariadicIndex 结合使用,以指定可变参数列表中的参数。 Src 的值将把可变参数列表中作为一部分的每个调用站点参数都视为与传播规则相关的源(就像由 SrcArg 指定的那样)。 Dst 的值将把可变参数列表中作为一部分的每个调用站点参数都视为与传播规则相关的目标。 None 的值将不考虑可变参数列表中作为一部分的参数(此选项是多余的,但可以用于暂时关闭对特定可变参数选项的处理,而无需删除 VariadicIndex 键)。

  • VariadicIndex 是一个 [0..int_max] 范围内的数字。它指示函数签名中可变参数的起始索引。

2.6.3.3. 接收器语法和语义

Sinks 下的条目是一个 YAML 对象,具有以下必填键
  • Name 是一个字符串,指定函数的名称。在符号执行期间遇到此函数时,如果使用 Args 指定的任何参数在调用站点都被污染,则会发出与污点相关的诊断。

  • Args 是一个 [0..int_max] 范围内的数字列表,指示函数调用中参数的索引。如果任何指定的参数被污染,检查器会报告错误。

以下键是可选的
  • Scope 是一个字符串,指定函数在其完全限定名称中的名称前缀。此选项限制了匹配函数调用的集合。