[英]JavaScript NoSQL Injection prevention in MongoDB
How can I prevent JavaScript NoSQL injections into MongoDB?如何防止 JavaScript NoSQL 注入 MongoDB?
I am working on a Node.js application and I am passing req.body
, which is a json object, into the mongoose model's save function. I thought there were safeguards behind the scenes, but this doesn't appear to be the case.我正在处理一个 Node.js 应用程序,我正在将
req.body
传递到 mongoose 模型的保存 function 中,这是一个 json object。我认为幕后有保护措施,但事实并非如此。
Sushant 's answer is not correct. Sushant的答案不正确。 You need to be aware of NoSQL injection in MongoDB.
您需要了解MongoDB中的NoSQL注入。
Example (taken from here ) 示例 (从此处获取 )
User.findOne({
"name" : req.params.name,
"password" : req.params.password
}, callback);
If req.params.password
is { $ne: 1 }
, the user will be retrieved without knowing the password ( $ne
means not equals 1 ). 如果
req.params.password
为{ $ne: 1 }
,则将在不知道密码的情况下检索用户( $ne
表示不等于1 )。
MongoDB Driver MongoDB驱动程序
You can use mongo-sanitize : 您可以使用mongo-sanitize :
It will strip out any keys that start with '$' in the input, so you can pass it to MongoDB without worrying about malicious users overwriting.
它将去除输入中以“ $”开头的所有键,因此您可以将其传递给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 Driver 猫鼬司机
As it follows a schema, if the password is a string field, it will convert the object { $ne: 1 }
to string and no damage will be done. 在遵循模式时,如果密码是字符串字段,它将把对象
{ $ne: 1 }
为字符串,并且不会造成任何损坏。 In this case, you don't need to sanitize, just remember to set a proper schema. 在这种情况下,您无需清理,只需记住设置适当的架构即可。
Although the post is obsolete, I'm answering. 尽管该帖子已过时,但我正在回答。
I know three ways. 我知道三种方式。
First: There is a multipurpose content-filter . 首先:有一个多功能的内容过滤器 。 Also provides MongoDB injection protection by filtering way.
还通过过滤方式提供MongoDB注入保护。
Second: mongo-sanitize , Helper to sanitize mongodb queries against query selector injections. 第二个: mongo-sanitize ,帮助程序针对查询选择器注入清理mongodb查询。
Third: I'd seen over here this solution which can be applied for MongoDB too. 第三:我在这里看到了可以用于MongoDB的此解决方案。 It's really simple to implement.
实现起来真的很简单。 Only use built-in
escape()
function of JavaScript. 仅使用JavaScript的内置
escape()
函数。
escape()
converts the string into ascii
code. escape()
将字符串转换为ascii
代码。 $ne
is converted into %24ne
. $ne
转换为%24ne
。
var privateKey = escape(req.params.privateKey);
App.findOne({ key: privateKey }, function (err, app) {
//do something here
}
Note My answer is incorrect. 注意我的答案不正确。 Please refer to other answers.
请参考其他答案。
-- -
As a client program assembles a query in MongoDB, it builds a BSON object, not a string. 客户端程序在MongoDB中组装查询时,将构建BSON对象而不是字符串。 Thus traditional SQL injection attacks are not a problem.
因此,传统的SQL注入攻击不是问题。
For details follow the documentation 有关详细信息,请遵循文档
UPDATE 更新
Avoid expression like eval
which can execute arbitrary JS. 避免像
eval
这样的表达式可以执行任意JS。 If you are taking input from user and running eval
like expressions without cleaning the input you can screw up. 如果要从用户那里获取输入并运行类似
eval
表达式而不清除输入,则可能会搞砸。 As pointed by JoBu1324, operations like where
, mapReduce
and group
permit to execute JS expressions directly. 如JoBu1324所指出的,诸如
where
, mapReduce
和group
允许直接执行JS表达式。
In order to guard against query selector injections from a data object with unknown structure 为了防止来自结构未知的数据对象的查询选择器注入
Use mongo-sanitize to deeply sanitize via recursion: 使用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)
}
For example with sanitize(req.query)
nested query selectors will not be removed: 例如,使用
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 } }
Using deepSanitize(req.query)
sanitized objects (including nested) are mutated: 使用
deepSanitize(req.query)
清理对象(包括嵌套对象)是deepSanitize(req.query)
:
console.log(deepSanitize(req.query)) // { _id: {} }
console.log(req.query) // { _id: {} }
Eliminate object mutation with {...req.query}
: 用
{...req.query}
消除对象变异:
console.log(deepSanitize({...req.query})) // { _id: {} }
console.log(req.query) // { _id: { '$ne': 1 } }
If you are using Mongoose
in Mongoose 6
they introduced the sanitizeFilter option that could be used as follows (from the their documentation):如果您在 Mongoose 中使用
Mongoose
Mongoose 6
他们引入了sanitizeFilter选项,可以按如下方式使用(来自他们的文档):
const obj = { username: 'val', pwd: { $ne: null } };
sanitizeFilter(obj);
obj; // { username: 'val', pwd: { $eq: { $ne: null } } });
Sanitizes query filters against query selector injection attacks by wrapping any nested objects that have a property whose name starts with $ in a $eq.通过将任何具有名称以 $ 开头的属性的嵌套对象包装在 $eq 中,来净化查询过滤器以防止查询选择器注入攻击。
You can also set it up to be sensitized by default:您还可以将其设置为默认敏感:
mongoose.set('sanitizeFilter', true);
And you can also skip the default sensitizing by using trusted()
:您还可以使用
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.