Mongoose 搜索注入漏洞 CVE-2024-53900 到 CVE-2025-23061

admin 2025年2月20日18:52:42评论23 views字数 4661阅读15分32秒阅读模式

漏洞简介

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 运算符时出现了问题。

环境搭建

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

Mongoose 搜索注入漏洞 CVE-2024-53900 到 CVE-2025-23061

快速创建一个项目并指定 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. constUserSchema=new mongoose.Schema({

  8. username:String,

  9. isAdmin:Boolean,

  10. password:String

  11. });

  12. constPostSchema=new mongoose.Schema({

  13. title:String,

  14. content:String,

  15. author:{ type: mongoose.Schema.Types.ObjectId, ref:'User'}

  16. });

  17. constUser= mongoose.model("User",UserSchema);

  18. constPost= mongoose.model("Post",PostSchema);

  19. // 插入测试数据

  20. await User.deleteMany({});

  21. await Post.deleteMany({});

  22. const users = await User.insertMany([

  23. { username:"admin", isAdmin:true, password:"admin123"},

  24. { username:"user1", isAdmin:false, password:"user123"},

  25. { username:"user2", isAdmin:false, password:"user456"}

  26. ]);

  27. await Post.insertMany([

  28. { title:"Post 1", content:"Content 1", author: users[0]._id },

  29. { title:"Post 2", content:"Content 2", author: users[1]._id }

  30. ]);

  31. console.log("√ 已插入测试数据");

  32. // 1. 正常的 populate 查询

  33. try{

  34. const result = await Post.findOne().populate({

  35. path:'author',

  36. match:{ username:"admin"}

  37. });

  38. console.log("√ 正常 populate 查询结果:", result);

  39. }catch(err){

  40. console.error("× 正常 populate 查询失败:", err.message);

  41. }

  42. // 2. 测试 populate match 中的 $where 注入

  43. try{

  44. const result = await Post.findOne().populate({

  45. path:'author',

  46. match:{ $where:"this.isAdmin"}// 修改这里,去掉 return

  47. });

  48. console.log("√ `$where` populate 查询成功,说明可能存在漏洞:", result);

  49. }catch(err){

  50. console.error("× `$where` populate 查询被拦截:", err.message);

  51. }

  52. // 3. 测试深层嵌套的 $where 注入

  53. try{

  54. const result = await Post.findOne().populate({

  55. path:'author',

  56. match:{

  57. $and:[

  58. { nested:{ $where:"this.isAdmin"}}// 修改这里,去掉 return

  59. ]

  60. }

  61. });

  62. console.log("√ 嵌套 `$where` populate 查询成功,说明可能存在漏洞:", result);

  63. }catch(err){

  64. console.error("× 嵌套 `$where` populate 查询被拦截:", err.message);

  65. }

  66. // 4. 测试数组中的 $where 注入

  67. try{

  68. const result = await Post.findOne().populate({

  69. path:'author',

  70. match:[{ $where:"this.isAdmin"}]// 修改这里,去掉 return

  71. });

  72. console.log("√ 数组中的 `$where` populate 查询成功,说明可能存在漏洞:", result);

  73. }catch(err){

  74. console.error("× 数组中的 `$where` populate 查询被拦截:", err.message);

  75. }

  76. await mongoose.disconnect();

  77. }

  78. testWhereInjection().catch(console.error);

[email protected]

Mongoose 搜索注入漏洞 CVE-2024-53900 到 CVE-2025-23061

[email protected]

Mongoose 搜索注入漏洞 CVE-2024-53900 到 CVE-2025-23061

[email protected]

Mongoose 搜索注入漏洞 CVE-2024-53900 到 CVE-2025-23061

通过执行结果我们发现,在 [email protected] 中,$where 语句可以任意执行语句,经过修复后的 [email protected] 中,只能通过嵌套来执行插入的语句,[email protected] 已经修复了通过嵌套执行插入语句的问题。

漏洞分析

https://github.com/Automattic/mongoose/compare/6.13.4...6.13.5?diff=split&w=

Mongoose 搜索注入漏洞 CVE-2024-53900 到 CVE-2025-23061

第一次进行修复

  • 首先判断 match 是否为一个数组,使用 Array.isArray(match) 进行检查。

  • 如果 match 是一个数组,则使用 for…of 循环遍历数组中的每个元素 item。

  • 对于每个 item,进行以下检查:

    • 如果 item 不为 null (item != null),并且 item 对象中存在 $where 属性 (item.$where),则抛出一个 MongooseError 异常,错误信息为 “Cannot use $where filter with populate() match”。这是因为在 populate() 查询中不允许使用 $where 操作符

  • 如果 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=

Mongoose 搜索注入漏洞 CVE-2024-53900 到 CVE-2025-23061

Mongoose 搜索注入漏洞 CVE-2024-53900 到 CVE-2025-23061

第二次修复

  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 操作符位于对象的哪个层级。

阶段 分析
在最初状态下,没有对 populate() 查询中的 $where 操作符进行任何检查和限制。这意味着用户可以在 match 参数中自由使用 $where 操作符,但这可能会导致一些安全和性能问题。
CVE-2024-53900 第一次修复引入了代码来检查 match 参数是否包含 $where 操作符。代码首先判断 match 是否为数组,如果是,则遍历数组的每个元素,检查是否包含 $where 属性;如果 match 是一个对象,则直接检查其 $where 属性。如果发现 $where 操作符,就抛出一个 MongooseError 异常。这样可以在 populate() 查询中禁止使用 $where 操作符,提高了安全性。但是,这种方式只能检查一层嵌套,对于更深层次的嵌套对象,可能无法完全检查到。
CVE-2025-23061 第二次修复对代码进行了重构,引入了一个单独的函数 throwOn$where。该函数接受 match 对象作为参数,并递归地检查其中是否包含 $where 操作符。函数首先对 match 进行类型检查,如果不是对象类型则直接返回。然后遍历 match 对象的属性键,如果发现 $where 键,则抛出异常;对于嵌套的对象,函数会递归调用自身进行检查。这种递归的方式可以对任意深度嵌套的对象进行全面检查,提供了更完善的 $where 操作符限制。同时,代码的可读性和可维护性也得到了提高。

Mongoose 搜索注入漏洞 CVE-2024-53900 到 CVE-2025-23061

原文始发于微信公众号(蚁景网络安全):Mongoose 搜索注入漏洞 CVE-2024-53900 到 CVE-2025-23061

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年2月20日18:52:42
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Mongoose 搜索注入漏洞 CVE-2024-53900 到 CVE-2025-23061http://cn-sec.com/archives/3764786.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息