繁体   English   中英

JavaScript NoSQL 注射预防 MongoDB

[英]JavaScript NoSQL Injection prevention in MongoDB

如何防止 JavaScript NoSQL 注入 MongoDB?

我正在处理一个 Node.js 应用程序,我正在将req.body传递到 mongoose 模型的保存 function 中,这是一个 json object。我认为幕后有保护措施,但事实并非如此。

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); 

猫鼬司机

在遵循模式时,如果密码是字符串字段,它将把对象{ $ne: 1 }为字符串,并且不会造成任何损坏。 在这种情况下,您无需清理,只需记住设置适当的架构即可。

尽管该帖子已过时,但我正在回答。

我知道三种方式。

首先:有一个多功能的内容过滤器 还通过过滤方式提供MongoDB注入保护。

第二个: mongo-sanitize ,帮助程序针对查询选择器注入清理mongodb查询。

第三:在这里看到可以用于MongoDB的此解决方案。 实现起来真的很简单。 仅使用JavaScript的内置escape()函数。

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

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

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

注意我的答案不正确。 请参考其他答案。

-

客户端程序在MongoDB中组装查询时,将构建BSON对象而不是字符串。 因此,传统的SQL注入攻击不是问题。

有关详细信息,请遵循文档

更新

避免像eval这样的表达式可以执行任意JS。 如果要从用户那里获取输入并运行类似eval表达式而不清除输入,则可能会搞砸。 如JoBu1324所指出的,诸如wheremapReducegroup允许直接执行JS表达式。

为了防止来自结构未知的数据对象的查询选择器注入

使用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)清理对象(包括嵌套对象)是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 } }

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

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

通过将任何具有名称以 $ 开头的属性的嵌套对象包装在 $eq 中,来净化查询过滤器以防止查询选择器注入攻击。

您还可以将其设置为默认敏感:

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 }); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM