### MongoDB 注入方式

**MongoDB 注入的原理**

MongoDB 注入的核心原理是**利用MongoDB 查询中的特殊操作符或特性，来绕过应用程序的认证或执行未授权的数据库操作**。当应用程序将用户输入直接拼接或用于构建查询对象时，攻击者可以通过构造恶意的输入来改变查询的逻辑

例如，一个典型的登录查询可能看起来像这样：

```js
db.collection.findOne({
    username: request.body.username,
    password: request.body.password
});
```

如果攻击者在`username`字段输入`{"$ne": null}`，在`password`字段输入`{"$ne": null}`，那么查询就会变成：

```js
db.collection.findOne({
    username: {"$ne": null},
    password: {"$ne": null}
});
```

这个查询的含义是“查找 `username` 和 `password` 都不为空的任何文档”。这就可以**绕过密码验证**，成功以第一个匹配的用户身份登录

**常见的 MongoDB 注入方式**

**1. 逻辑操作符注入**

这是最常见、最基础的注入方式。攻击者利用 MongoDB 的**逻辑操作符**，如`$ne`（不等于）、`$gt`（大于）、`$lt`（小于）等来改变查询的逻辑

**认证绕过**

利用 `$ne` 操作符，可以构造登录认证绕过

- **用户名**：`'{"$ne": null}'`
- **密码**：`'{"$ne": null}'`

在某些情况下，也可以使用**布尔类型**来绕过：

- **用户名**：`'admin'
- **密码**：`'{"$gt": ""}'` (即密码大于空字符串的任何值)

这种方法简单且有效，因为它利用了数据库自身的查询特性

**2. 数组操作符注入**

MongoDB 的 **`$in` 操作符**可以用来查询某个字段是否在给定的数组中。攻击者可以利用这个特性进行注入

例如，一个查询可能用来检查用户的角色：

```js
db.users.findOne({
    username: request.body.username,
    role: "admin"
});
```

攻击者可以尝试在 `username` 字段输入一个数组，来绕过这个检查：

- **用户名**：`'{"$in": ["admin", "guest"]}'`
- **密码**：`'password'`

如果应用程序没有正确处理，这个查询可能被解析为： `db.users.findOne({ username: { "$in": ["admin", "guest"] }, role: "admin" });`

这可以用来**枚举**用户或**绕过**某些基于角色的访问控制

**3. 正则表达式注入**

MongoDB 支持**正则表达式查询**，这使得攻击者可以利用它来进行更复杂的攻击，比如**盲注**

假设存在一个查询，用来查找匹配用户名的文档：

```js
db.users.find({ username: request.body.username });
```

攻击者可以构造一个正则表达式，通过**布尔盲注**的方式来猜测数据

- **`$regex`**：用于匹配正则表达式
- **`$where`**：这个操作符允许在查询中使用 JavaScript 代码，是**最高危**的注入点之一

**盲注步骤**：

1. **测试是否存在注入点**：
   - 输入`{"$where": "this.username == 'admin'"}`，如果返回管理员信息，则说明存在注入
2. **布尔盲注猜解数据**：
   - 构造一个查询来猜解管理员的密码长度
     - `{"$where": "this.username == 'admin' && this.password.length > 5"}`
   - 如果响应正常（例如返回管理员信息），则说明密码长度大于 5
   - 否则，说明小于等于 5
3. **逐位猜解密码**：
   - 构造一个正则表达式来猜解密码的每一个字符
     - `{"$where": "this.username == 'admin' && this.password.match(/^a/)"}`
   - 这个查询会检查管理员密码是否以 `a` 开头
   - 通过**二分法**或**逐位**猜测，攻击者可以逐步猜解出完整的密码

**4. `eval`注入**

在早期版本中，MongoDB 的 `db.eval()` 命令允许在服务器端执行 JavaScript 代码。这在功能上非常强大，但同时也是一个巨大的安全隐患，因为攻击者可以直接执行任意代码，包括**操作系统命令**