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, 安全测试, 攻击性安全, 无后门, 测试用例生成, 语法引擎, 逆向工具