MongoDB中的JavaScript NoSQL注入预防

e4eetjau  于 2023-01-04  发布在  Java
关注(0)|答案(5)|浏览(197)

如何防止JavaScript NoSQL注入MongoDB?
我正在处理一个Node.js应用程序,我正在将req.body(一个json对象)传递到mongoose模型的保存函数中,我以为在幕后有安全措施,但事实似乎并非如此。

tyg4sfes

tyg4sfes1#

    • Sushant的答案不正确。需要**了解MongoDB中的NoSQL注入。
    • 示例**(摘自此处)
User.findOne({
    "name" : req.params.name, 
    "password" : req.params.password
}, callback);

如果req.params.password{ $ne: 1 },则用户将在不知道密码的情况下被检索($ne表示 * 不等于1 *)。

    • MongoDB驱动程序**

您可以使用mongo-sanitize
它将去掉输入中以'$'开头的任何键,因此您可以将其传递给MongoDB,而不必担心恶意用户覆盖。

var sanitize = require('mongo-sanitize');

var name = sanitize(req.params.name);
var password = sanitize(req.params.password);

User.findOne({
    "name" : name, 
    "password" : password
}, callback);
    • Mongoose 司机**

由于它遵循一个模式,如果 * password * 是一个字符串字段,它会将对象{ $ne: 1 }转换为字符串,并且不会造成任何损害。在这种情况下,您不需要清理,只需记住设置一个适当的模式。

dxpyg8gm

dxpyg8gm2#

虽然帖子已经过时了,但我还是要回复。
我知道三种方法。

***第一:***有一个多用途的content-filter。还提供MongoDB注入保护过滤的方式。
***第二个:***mongo-sanitize,帮助清理mongodb查询以防止查询选择器注入。
***第三:***我见过over here这个解决方案,它也可以应用于MongoDB,实现起来非常简单,只需要使用JavaScript内置的escape()函数。

escape()将字符串转换为ascii代码。$ne将转换为%24ne

var privateKey = escape(req.params.privateKey);

App.findOne({ key: privateKey }, function (err, app) {
  //do something here
}
ymdaylpp

ymdaylpp3#

为了防止来自未知结构的数据对象的查询选择器注入
使用mongo-sanitize通过递归进行深度清理:

const deepSanitize = (value) => {
    if(Array.isArray(value)){
        value.forEach(elm=>deepSanitize(elm))
    }
    if(typeof(value) === 'object' && value !== null){
        Object.values(value).forEach((elm)=>{
            deepSanitize(elm)
        })
    }
    return sanitize(value)
}

例如,对于sanitize(req.query),将不会删除嵌套查询选择器:

const req = {} 
req.query = { _id : { $ne: 1 } } 

console.log(req.query))               // { _id: { '$ne': 1 } }
console.log(sanitize(req.query))      // { _id: { '$ne': 1 } }

使用deepSanitize(req.query)清理的对象(包括嵌套的)会发生变化:

console.log(deepSanitize(req.query))       // { _id: {} }
console.log(req.query)                     // { _id: {} }

使用{...req.query}消除对象突变:

console.log(deepSanitize({...req.query}))  // { _id: {} }
console.log(req.query)                     // { _id: { '$ne': 1 } }
nbnkbykc

nbnkbykc4#

如果您在Mongoose 6中使用Mongoose,则他们引入了sanitizeFilter选项,可按如下方式使用(参见他们的文档):

const obj = { username: 'val', pwd: { $ne: null } };
sanitizeFilter(obj);
obj; // { username: 'val', pwd: { $eq: { $ne: null } } });

通过在$eq中 Package 任何具有名称以$开头的属性的嵌套对象,对查询过滤器进行消毒,防止查询选择器注入攻击。
您也可以将其设置为默认敏感:

mongoose.set('sanitizeFilter', true);

您还可以使用trusted()跳过默认的敏化:

const user = await User.findOne({
  // Tell Mongoose to not sanitize `{ $ne: true }`
  deleted: mongoose.trusted({ $ne: true }),
  email: req.body.email,
  hashedPassword: req.body.hashedPassword
}).setOptions({ sanitizeFilter: true });
rlcwz9us

rlcwz9us5#

    • 注**我的答案不正确,请参考其他答案。

--
当客户端程序在MongoDB中组装查询时,它构建了一个BSON对象,而不是字符串,因此传统的SQL注入攻击不是问题。
有关详细信息,请参阅文档

    • 更新**

避免使用eval这样的表达式,因为它可以执行任意的JS。如果你从用户那里获取输入,然后运行eval这样的表达式,而不清理输入,你可能会搞砸。正如JoBu1324所指出的,wheremapReducegroup这样的操作允许直接执行JS表达式。

相关问题