Mongoose 搜刮注入漏洞分析

打印 上一主题 下一主题

主题 863|帖子 863|积分 2589

漏洞简介

CVE-2024-53900 Mongoose 8.8.3、7.8.3 和 6.13.5 之前的版本容易受到 $where 运算符不当使用的影响。此漏洞源于 $where 子句能够在 MongoDB 查询中执行任意 JavaScript 代码,这可能导致代码注入攻击以及未经授权的数据库数据访问或操纵。
CVE-2025-23061 Mongoose 8.9.5、7.8.4 和 6.13.6 之前的版本容易受到 $where 运算符不当使用的影响。此漏洞源于 $where 子句能够在 MongoDB 查询中执行任意 JavaScript 代码,可能导致代码注入攻击以及未经授权的数据库数据访问或操纵。该问题的存在是因为CVE-2024-53900的修复不完整。
Mongoose 是一个用于 Node.js 的 MongoDB 对象建模工具,它使得与 MongoDB 数据库交互变得更加简朴和高效。我们可以看到这两个漏洞描述大体相同,都是因为在使用 $where 运算符时出现了问题。
环境搭建

安装 MongoDB 不知道是不是本地环境的问题,错误百出,于是照旧采用 docker 来安装 docker pull mongo docker run --name mongodb -d -p 27017:27017 mongo

快速创建一个项目并指定 mongoose 版本
  1. npm init -y
  2. npm install mongoose@6.13.4 --save
  3. node test.js
复制代码
漏洞复现

根据漏洞特点我编写了一个 js 脚本,在不同版本下执行,比力不同情况对应的结果
  1. const mongoose = require("mongoose");
  2. // 连接 MongoDB
  3. const MONGO_URI = "mongodb://localhost:27017/testdb";
  4. async function testWhereInjection() {
  5.  await mongoose.connect(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });
  6.  // 定义 User 模型和 Post 模型
  7.  const UserSchema = new mongoose.Schema({
  8.    username: String,
  9.    isAdmin: Boolean,
  10.    password: String
  11.   });
  12.  const PostSchema = new mongoose.Schema({
  13.    title: String,
  14.    content: String,
  15.    author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
  16.   });
  17.  const User = mongoose.model("User", UserSchema);
  18.  const Post = mongoose.model("Post", PostSchema);
  19.  // 插入测试数据
  20.  await User.deleteMany({});
  21.  await Post.deleteMany({});
  22.  
  23.  const users = await User.insertMany([
  24.    { username: "admin", isAdmin: true, password: "admin123" },
  25.    { username: "user1", isAdmin: false, password: "user123" },
  26.    { username: "user2", isAdmin: false, password: "user456" }
  27.   ]);
  28.  await Post.insertMany([
  29.    { title: "Post 1", content: "Content 1", author: users[0]._id },
  30.    { title: "Post 2", content: "Content 2", author: users[1]._id }
  31.   ]);
  32.  console.log("√ 已插入测试数据");
  33.  // 1. 正常的 populate 查询
  34.  try {
  35.    const result = await Post.findOne().populate({
  36.      path: 'author',
  37.      match: { username: "admin" }
  38.    });
  39.    console.log("√ 正常 populate 查询结果:", result);
  40.   } catch (err) {
  41.    console.error("× 正常 populate 查询失败:", err.message);
  42.   }
  43.  // 2. 测试 populate match 中的 $where 注入
  44.  try {
  45.    const result = await Post.findOne().populate({
  46.      path: 'author',
  47.      match: { $where: "this.isAdmin" }  // 修改这里,去掉 return
  48.    });
  49.    console.log("√ `$where` populate 查询成功,说明可能存在漏洞:", result);
  50.   } catch (err) {
  51.    console.error("× `$where` populate 查询被拦截:", err.message);
  52.   }
  53.  // 3. 测试深层嵌套的 $where 注入
  54.  try {
  55.    const result = await Post.findOne().populate({
  56.      path: 'author',
  57.      match: {
  58.        $and: [
  59.          { nested: { $where: "this.isAdmin" } }  // 修改这里,去掉 return
  60.        ]
  61.      }
  62.    });
  63.    console.log("√ 嵌套 `$where` populate 查询成功,说明可能存在漏洞:", result);
  64.   } catch (err) {
  65.    console.error("× 嵌套 `$where` populate 查询被拦截:", err.message);
  66.   }
  67.  // 4. 测试数组中的 $where 注入
  68.  try {
  69.    const result = await Post.findOne().populate({
  70.      path: 'author',
  71.      match: [{ $where: "this.isAdmin" }]  // 修改这里,去掉 return
  72.    });
  73.    console.log("√ 数组中的 `$where` populate 查询成功,说明可能存在漏洞:", result);
  74.   } catch (err) {
  75.    console.error("× 数组中的 `$where` populate 查询被拦截:", err.message);
  76.   }
  77.  await mongoose.disconnect();
  78. }
  79. testWhereInjection().catch(console.error);
复制代码
mongoose@6.13.4

[img=720,372.5019731649566]https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202502201543661.png[/img]

mongoose@6.13.5

[img=720,303.6792452830189]https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202502201543662.png[/img]

mongoose@6.13.6

[img=720,205.225]https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202502201543663.png[/img]

通过执行结果我们发现,在 mongoose@6.13.4 中,$where 语句可以任意执行语句,颠末修复后的 mongoose@6.13.5 中,只能通过嵌套来执行插入的语句,mongoose@6.13.6 已经修复了通过嵌套执行插入语句的问题。
【----帮助网安学习,以下所有学习资料免费领!加vx:yj520400,备注 “博客园” 获取!】
 ① 网安学习成长路径头脑导图
 ② 60+网安经典常用工具包
 ③ 100+SRC漏洞分析陈诉
 ④ 150+网安攻防实战技术电子书
 ⑤ 最权威CISSP 认证测验指南+题库
 ⑥ 超1800页CTF实战技巧手册
 ⑦ 最新网安大厂面试题合集(含答案)
 ⑧ APP客户端安全检测指南(安卓+IOS)
漏洞分析

https://github.com/Automattic/mongoose/compare/6.13.4...6.13.5?diff=split&w=
[img=720,326.3768115942029]https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202502201543664.png[/img]

第一次举行修复
1. 首先判定 match 是否为一个数组,使用 Array.isArray(match)举行检查。
2. 假如 match 是一个数组,则使用 for...of 循环遍历数组中的每个元素 item。
3. 对于每个 item,举行以下检查:
  假如item 不为 null (item !\= null),并且 item 对象中存在 $where 属性(item.$where),则抛出一个 MongooseError 非常,错误信息为 "Cannot use $where filter with populate() match"。这是因为在 populate() 查询中不允许使用 $where 操纵符。
4. 假如 match 不是一个数组,则举行另一个判定:
  假如 match 不为 null (match !\= null),并且 match 对象中存在 $where 属性(match.$where !\= null),同样抛出一个 MongooseError 非常,错误信息为 "Cannot use $where filter with populate() match"。
举行 populate() 查询时,防止使用 $where 操纵符,检查传入的 match 参数是否包罗 $where 属性,无论 match 是一个数组照旧一个对象。假如发现 match 中存在 $where 属性,就会抛出一个 MongooseError 非常,提示不能在 populate() 查询中使用 $where 过滤器
https://github.com/Automattic/mongoose/compare/6.13.5...6.13.6?diff=split&w=
[img=720,324.13069786204113]https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202502201543665.png[/img]

[img=720,224.46886446886447]https://m-1254331109.cos.ap-guangzhou.myqcloud.com/202502201543666.png[/img]

第二次修复
1. 函数接受一个参数 match,表示要检查的对象。
2. 首先举行两个条件判定:
  假如 match​ 为null 或 undefined,直接返回,不举行后续检查。
  假如 match​ 的类型不是对象,也直接返回,不举行后续检查。 这两个判定是为了避免对非对象类型举行遍历和递归。
3. 使用 Object.keys(match) 获取 match 对象的所有属性键,并使用 for...of 循环遍历每个属性键 key。
4. 对于每个属性键 key,举行以下检查:
  假如 key​ 等于 '$where',表示在 match​ 对象中发现了 $where 操纵符,抛出一个 MongooseError 非常,错误信息为 "Cannot use $where filter with populate() match"。
5. 假如当前属性的值 match[key] 不为 null 或 undefined,并且其类型为对象,则递归调用 throwOn$where 函数,将 match[key] 作为参数传入,对嵌套的对象举行相同的检查。
通过递归调用 throwOn$where​ 函数,可以对 match​ 对象举行深度遍历,检查此中是否包罗 $where 操纵符,无论 $where 操纵符位于对象的哪个层级。
 
[img=720,347.4125874125874]https://www.yijinglab.com/headImg.action?news=3af353e8-e9dc-4626-a973-f501d10212b7.png[/img]

更多网安技能的在线实操训练,请点击这里>>
  

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

兜兜零元

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表