### fuzz 普通程序和数据库有哪些不同点

**1. 输入和协议的复杂性**

- **普通程序**：通常处理简单格式的输入，如文件、命令行参数或简单的网络数据包。这些输入的格式相对单一，fuzzer 很容易理解和变异。例如，对一个图片解析器进行fuzzing，输入就是图片文件
- **数据库**：数据库的输入是复杂的、有状态的网络协议和查询语言。fuzzer 需要理解和生成符合特定数据库协议（如 MySQL 的二进制协议、PostgreSQL 的文本协议）的数据包。更重要的是，数据库的**查询语言（SQL）**本身就极为复杂，包含多种数据类型、函数、联结操作和语法结构。fuzzer 不仅要生成畸形的协议数据，还要生成语法正确但语义畸形的 SQL 查询语句，比如超长的字符串、负数、特殊字符等

**2. 状态管理和序列依赖**

- **普通程序**：大多数普通程序是**无状态**的。每次运行fuzzer，程序都从一个干净的状态开始，处理一个单独的输入。这使得fuzzer很容易追踪和重现漏洞
- **数据库**：数据库是**有状态**的。一个查询的执行结果可能依赖于之前的查询。例如，你必须先创建一张表，然后才能向其中插入数据，最后才能查询。这意味着fuzzer需要生成一系列有逻辑关系的查询序列，而不是单个独立的输入。如果一个漏洞需要多次操作才能触发，fuzzer 必须能够管理和生成这个操作序列

**3. 性能和效率**

- **普通程序**：普通程序的fuzzing通常很快。一个文件解析器在毫秒级就能处理一个输入。这使得覆盖率引导的fuzzer（如 AFL）能够每秒测试数千甚至数万次，从而快速找到漏洞
- **数据库**：数据库的fuzzing通常很慢。每次建立连接、发送查询、接收响应都需要时间。此外，一个查询可能需要几毫秒甚至几秒来执行。这大大降低了fuzzer的测试速度，因此需要更智能的fuzzing策略

**4. 漏洞类型和检测方法**

- **普通程序**：fuzzing通常用于寻找内存安全漏洞，如缓冲区溢出、空指针解引用等。当程序崩溃时，fuzzer会立即捕获到异常
- **数据库**：数据库的漏洞类型更为多样，不仅包括内存安全问题，还包括：
  - **逻辑漏洞**：错误的查询结果、数据损坏等。这些漏洞不会导致程序崩溃，fuzzer需要有专门的逻辑来检测
  - **权限绕过**：在低权限下执行高权限操作
  - **SQL 注入**：这是一种特殊的逻辑漏洞，fuzzing可以用于寻找新的注入点

由于很多数据库漏洞不会导致程序崩溃，fuzzer需要额外的断言（assertions）或 Oracle 来检测。例如，fuzzer可以执行一个查询，然后用一个已知正确的查询来验证结果是否一致。如果不一致，就可能存在逻辑漏洞

**5. 架构和环境的复杂性**

- **普通程序**：通常在一个单一进程中运行，fuzzer可以直接附加或作为子进程运行
- **数据库**：数据库是复杂的系统，通常是多进程或多线程的。这使得传统的fuzzer很难精确地追踪代码覆盖率。例如，一个主进程可能接受连接，然后派生出多个子进程来处理查询。fuzzer需要能够跟踪和监控这些子进程

| 特性     | Fuzzing 普通程序               | Fuzzing 数据库                               |
| -------- | ------------------------------ | -------------------------------------------- |
| 输入     | 单一，通常是文件或简单网络数据 | 复杂，包含协议和查询语言                     |
| 状态     | 无状态，每个输入独立           | 有状态，需要管理查询序列                     |
| 速度     | 非常快，每秒数千次以上         | 较慢，受网络和查询执行速度影响               |
| 漏洞类型 | 主要是内存安全漏洞（崩溃）     | 内存安全、逻辑漏洞、权限问题等               |
| 检测方法 | 捕获崩溃                       | 捕获崩溃，并需要断言或Oracle来检测非崩溃漏洞 |
| 挑战     | 探索代码路径和绕过输入验证     | 管理状态、生成复杂输入、处理低速和多进程环境 |