googleprojectzero/domato

GitHub: googleprojectzero/domato

Google Project Zero 推出的一款基于上下文无关文法的 DOM 模糊测试工具,专门用于生成复杂的 HTML、CSS 和 JavaScript 样本来挖掘浏览器引擎中的内存安全漏洞。

Stars: 1776 | Forks: 284

# Domato 🍅 #### 一个 DOM 模糊测试工具 由 Ivan Fratric 编写和维护, 版权所有 2017 Google Inc. 保留所有权利。 根据 Apache 许可证 2.0 版(“许可证”)获得许可; 除非遵守许可证,否则您不得使用此文件。 您可以在以下网址获取许可证副本: ``` http://www.apache.org/licenses/LICENSE-2.0 ``` 除非适用法律要求或书面同意,否则根据许可证分发的软件 均按“原样”分发, 不附带任何明示或暗示的担保或条件。 有关许可证下特定语言的权限和 限制,请参阅许可证。 #### 用法 要查看用法信息,请运行以下命令: `python3 generator.py --help` 要生成单个 .html 样本,请运行: `python generator.py --file <输出文件>` 要使用您编写的模板生成单个 .html 样本,请运行: `python generator.py --file <输出文件> --template <您的自定义模板文件>` 要通过单次调用生成多个样本,请运行: `python generator.py --output_dir <输出目录> --no_of_files <输出文件的数量>` 生成的样本将被放置在指定目录中,并命名为 fuzz-<number>.html,例如 fuzz-00001.html、fuzz-00002.html 等。一次生成多个样本的速度更快,因为输入语法文件只需加载和解析一次。 #### 代码组织 generator.py 包含主脚本。它将 grammar.py 用作库,并包含用于 DOM 模糊测试的额外辅助代码。 grammar.py 包含生成引擎,该引擎主要与具体应用程序无关,因此可用于其他(即非 DOM)基于生成的模糊测试工具。由于它可以作为库使用,因此其用法将在下面的单独章节中描述。 .txt 文件包含语法定义。有 3 个主要文件:html.txt、css.txt 和 js.txt,分别包含 HTML、CSS 和 JavaScript 语法。这些根语法文件可以包含来自其他文件的内容。 #### 使用生成引擎和编写语法 要将生成引擎与自定义语法结合使用,可以使用以下 Python 代码: ``` from grammar import Grammar my_grammar = Grammar() my_grammar.parse_from_file('input_file.txt') result_string = my_grammar.generate_symbol('symbol_name') ``` 以下各节介绍语法文件的语法规则。 ##### 基本语法 Domato 基于一个引擎,该引擎在给定上下文无关语法(格式如下所述)的情况下,能够根据该语法生成样本。 语法被描述为具有以下基本格式的一组规则: ` = a mix of constants and s` 每个语法规则包含左右两侧,由等号分隔。左侧包含一个符号,而右侧包含有关如何展开该符号的详细信息。在展开一个符号时,右侧的所有符号都会被递归展开,而所有不是符号的内容则直接复制到输出中。请注意,单个规则不能跨越输入文件的多行。 考虑以下 CSS 语法的简化示例: ``` = { } = a = b = width:100% ``` 如果我们指示语法引擎解析该语法并生成 'cssrule',我们最终可能会得到: `a { width:100% }` 或 `b { width:100% }` 请注意,'selector' 符号有两条规则。在这种情况下,当生成器被要求生成 'selector' 时,它将随机选择要使用的规则。也可以使用 'p' 属性指定规则的概率,例如: ``` = a = b ``` 在这种情况下,字符串 'a' 的输出频率会高于 'b'。 除了概率之外,还有其他可以应用于符号的属性。这些属性将在单独的章节中列出。 考虑另一个生成 HTML 样本的示例: ``` = html/html = head.../head = body.../body ``` 请注意,由于 '<' 和 '>' 在语法语法中具有特殊含义,因此这里我们改用 `` 和 ``。这些符号是内置的,无需用户定义。所有内置符号的列表在单独的章节中提供。 ##### 生成编程语言代码 要生成编程语言代码,可以使用类似的语法,但有一些区别。编程语言语法的每一行将对应输出中的一行。因此,语法格式将更加自由,以允许表达各种编程语言中的构造。其次,在生成一行代码时,除了输出该行之外,还可以创建一个或多个变量,并且这些变量可以在生成其他行时重用。再次说明,让我们看一个简化的示例: ``` !varformat fuzzvar%05d !lineguard try { } catch(e) {} !begin lines = document.getElementById(""); .doSomething(); !end lines ``` 如果我们指示引擎生成 5 行代码,我们最终可能会得到类似于以下内容: ``` try { var00001 = document.getElementById("hw"); } catch(e) {} try { var00001.doSomething(); } catch(e) {} try { var00002 = document.getElementById("feezcqbndf"); } catch(e) {} try { var00002.doSomething(); } catch(e) {} try { var00001.doSomething(); } catch(e) {} ``` 请注意 - 编程语言行被括在 '!begin lines' 和 '!end lines' 语句中。这为语法解析器提供了必要的信息,即介于两者之间的行是编程语言行,因此会以不同的方式进行解析。 - 我们使用了 `` 而不是 ``。这指示生成器创建一个类型为 'element' 的新变量,而不是展开 'element' 符号。 - `` 是内置符号之一,因此无需定义。 - [可选] 您可以使用 !varformat 语句来定义要使用的变量格式。 - [可选] 您可以使用 !lineguard 语句来定义在每行周围插入的额外代码,以捕获异常或执行其他任务。这样您就无需为每一行单独编写这些代码。 - 除了 '!begin lines' 和 '!end lines',您还可以使用 '!begin helperlines' 和 '!end helperlines' 来定义仅在生成其他行时需要用到的代码行(例如,辅助行可能会生成“主”代码所需的变量,但您永远不希望这些辅助行在不需要时出现在输出中)。 ##### 注释 行中第一个 '#' 字符之后的所有内容都被视为注释,例如: ``` #This is a comment ``` ##### 防止无限递归 语法语法提供了一种方法,可以告知模糊测试器哪些规则是非递归的,即使在达到最大递归级别时也可以安全使用。这是通过 'nonrecursive' 属性实现的。下面是一个示例。 ``` !max_recursion 10 = = foo = bar ``` 首先,可选的 '!max_recursion' 语句定义了最大递归深度级别(默认为 50)。请注意,'foobar' 的第二个产生式规则被标记为非递归。如果达到最大递归级别,生成器将强制使用 'foobar' 符号的非递归规则,从而防止无限递归。 ##### 包含和导入其他语法文件 在 Domato 中,包含和导入语法是两个不同的概念。 包含比较简单。您可以使用: ``` !include other.txt ``` 将 other.txt 中的规则包含到当前正在解析的语法中。 导入的工作方式略有不同: ``` !import other.txt ``` 告诉解析器创建一个新的 Grammar() 对象,随后可以通过使用特殊的 `` 符号从当前语法中引用该对象,例如: ``` = ``` 您可以从命名空间的角度来考虑导入和包含:!include 会将被包含的语法放入单一的命名空间中,而 !import 会创建一个新的命名空间,随后可以使用 `` 符号和通过 'from' 属性指定的命名空间来访问该命名空间。 ##### 包含 Python 代码 有时您可能希望在语法中调用自定义的 Python 代码。例如,假设您想使用该引擎生成一个 HTTP 响应,并且希望正文长度与 'Size' 头部相匹配。由于这是常规语法规则无法做到的,因此您可以像这样包含自定义的 Python 代码来实现: ``` !begin function savesize context['size'] = ret_val !end function !begin function createbody n = int(context['size']) ret_val = 'a' * n !end function =
= Size: = ``` Python 函数定义在 '!begin function ' 和 '!end function' 命令之间。可以通过两种方式调用这些函数:使用 'beforeoutput' 属性和使用 `` 符号。 通过在某个符号中指定 'beforeoutput' 属性,相应的函数将在该符号被展开时调用,就在展开结果输出到样本之前。展开结果将通过 `ret_val` 变量传递给该函数。然后,该函数可以自由修改 `ret_val`、将其存储以备后用,或执行任何其他操作。 当使用特殊的 `` 符号时,该函数(在 'function' 属性中指定)将在语言生成过程中遇到该符号时被调用。该函数存储在 `ret_val` 中的任何值都将被视为展开的结果(`ret_val` 会包含在样本中)。 您的 Python 代码可以访问以下变量: - `context` - 一个在整个样本生成过程中传递的字典。您可以使用它来存储值(例如在上面的示例中存储大小),并在随后触发的规则中检索它们。 - `attributes` - 一个与当前正在处理的符号相对应的字典。您可以使用它将参数传递给您的函数。例如,如果您使用类似 `` 的方式调用函数,则 `attributes['foo']` 将被设置为 'bar'。 - `ret_val` - 将作为函数调用结果输出的值。当使用 `` 符号调用函数时,它被初始化为空值,否则将被初始化为该符号生成的值。 ##### 内置符号 以下符号具有特殊含义,不应由用户重新定义: - `` - '<' 字符 - `` - '>' 字符 - `` - '#' 字符 - `` - CR(回车)字符 - `` - LF(换行)字符 - `` - 空格字符 - `` - 制表符字符 - `` - '!' 字符 - `` - 可用于使用 'code' 属性生成任意 ASCII 字符。例如,`` 对应于 'a'。如果未指定,则生成随机字符。支持 'min' 和 'max' 属性。 - `` - 生成一个随机的十六进制数字。 - ``、``、``、``、``、``、``、``、`` - 可用于生成随机整数。支持 'min' 和 'max' 属性,可用于限制生成的整数范围。支持 'b' 和 'be' 属性,这使得输出以小端/大端格式的二进制形式呈现,而不是文本输出。 - ``、`` - 生成随机浮点数。支持 'min' 和 'max' 属性(如果未指定,则默认为 0 和 1)。支持 'b' 属性,这使得输出为二进制形式。 - `` - 生成一个随机字符串。支持 'min' 和 'max' 属性,用于控制生成的最小和最大字符编码;以及 'minlength' 和 'maxlength' 属性,用于控制字符串的长度。 - `` - 与 `` 相同,但 HTML 元字符将被转义,从而可以安全地将字符串作为 HTML 文本或属性值的一部分嵌入。 - `` - 输出给定数量(通过 'count' 属性指定)的代码行。有关示例,请参见生成编程语言代码的章节。 - `` - 从另一个语法中导入符号,详情请参见包含外部语法的章节。 - `` - 调用与 function 属性对应的用户自定义函数。更多信息请参见在语法中包含 Python 代码的章节。 ##### 符号属性 支持以下属性: - root - 将符号标记为语法的根符号。唯一支持的值是 'true'。当调用 `GenerateSymbol()` 时,如果未指定参数,则会生成根符号。 - nonrecursive - 向生成器提示此规则不包含递归循环,用于防止无限递归。唯一支持的值是 'true'。 - new - 在生成编程语言时使用,表示在此处创建一个新变量,而不是像往常一样展开该符号。唯一支持的值是 'true'。 - from、symbol - 用于从其他语法导入符号时,请参见“包含和导入其他语法文件”章节。 - count - 在 lines 符号中用于指定要创建的行数。 - id - 用于标记多个符号应共享相同的值。例如,在规则 `‘doSomething(, )’` 中,两个整数最终将具有相同的值。只有第一个实例会真正展开,第二个实例只是从第一个实例复制而来。 - min、max - 在生成数值类型时用于指定最小值和最大值。也用于限制字符串中生成的字符集。 - b、be - 在数值类型中用于指定二进制小端格式或大端格式输出。 - code - 在 char 符号中用于通过其编码指定要输出的确切字符。 - minlength、maxlength - 在生成字符串时用于指定最小和最大长度。 - up - 在 hex 符号中用于指定大写输出(默认为小写)。 - function - 在 `` 符号中使用,更多信息请参见“包含 Python 代码”章节。 - beforeoutput - 用于调用用户指定的函数,请参见“包含 Python 代码”章节。 #### 漏洞展示 使用 Domato 发现的部分漏洞: - Apple Safari: CVE-2017-2369, CVE-2017-2373, CVE-2017-2362, CVE-2017-2454, CVE-2017-2455, CVE-2017-2459, CVE-2017-2460, CVE-2017-2466, CVE-2017-2471, CVE-2017-2476, CVE-2017-7039, CVE-2017-7040, CVE-2017-7041, CVE-2017-7042, CVE-2017-7043, CVE-2017-7046, CVE-2017-7048, CVE-2017-7049, CVE-201713796, CVE-2017-13792, CVE-2017-13797, CVE-2017-13795, CVE-2017-13785, CVE-2017-13784, CVE-2017-13783, CVE-2017-13802, CVE-2017-13794, CVE-2017-13798, CVE-2017-13791, CVE-2018-4089, CVE-2018-4200, CVE-2018-4197, CVE-2018-4318, CVE-2018-4317, CVE-2018-4314, CVE-2018-4306, CVE-2018-4312, CVE-2018-4315, CVE-2018-4323, CVE-2018-4328 - Google Chrome: Issues 666246 and 671328 - Microsoft Internet Explorer 11: CVE-2017-0037, CVE-2017-0059, CVE-2017-0202, CVE-2017-8594, CVE-2018-0866 - Microsoft Edge: CVE-2017-0037, CVE-2017-8496, CVE-2017-8652, CVE-2017-8644 - Microsoft JScript: CVE-2017-11903, CVE-2017-11855, CVE-2017-11793, CVE-2017-11906, CVE-2017-11907, CVE-2018-0935, CVE-2018-8353, CVE-2018-8631 - Microsoft VBScript: CVE-2018-8544, CVE-2018-8552, CVE-2018-8625 - Mozilla Firefox: CVE-2017-5404, CVE-2017-5447, CVE-2017-5465 #### 免责声明 这不是一个官方的 Google 产品。
标签:CMS安全, CSS, DOM, Fuzzer, Google Project Zero, HTML, JavaScript, Python, 安全测试, 攻击性安全, 无后门, 测试用例生成, 语法引擎, 逆向工具