### 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 代码。这在功能上非常强大,但同时也是一个巨大的安全隐患,因为攻击者可以直接执行任意代码,包括**操作系统命令**