如何防止JavaScript NoSQL注入MongoDB?我正在处理一个Node.js应用程序,我正在将req.body(一个json对象)传递到mongoose模型的保存函数中,我以为在幕后有安全措施,但事实似乎并非如此。
req.body
tyg4sfes1#
User.findOne({ "name" : req.params.name, "password" : req.params.password }, callback);
如果req.params.password为{ $ne: 1 },则用户将在不知道密码的情况下被检索($ne表示 * 不等于1 *)。
req.params.password
{ $ne: 1 }
$ne
您可以使用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);
由于它遵循一个模式,如果 * password * 是一个字符串字段,它会将对象{ $ne: 1 }转换为字符串,并且不会造成任何损害。在这种情况下,您不需要清理,只需记住设置一个适当的模式。
dxpyg8gm2#
虽然帖子已经过时了,但我还是要回复。我知道三种方法。
***第一:***有一个多用途的content-filter。还提供MongoDB注入保护过滤的方式。***第二个:***mongo-sanitize,帮助清理mongodb查询以防止查询选择器注入。***第三:***我见过over here这个解决方案,它也可以应用于MongoDB,实现起来非常简单,只需要使用JavaScript内置的escape()函数。
escape()
escape()将字符串转换为ascii代码。$ne将转换为%24ne。
ascii
%24ne
var privateKey = escape(req.params.privateKey); App.findOne({ key: privateKey }, function (err, app) { //do something here }
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),将不会删除嵌套查询选择器:
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}消除对象突变:
{...req.query}
console.log(deepSanitize({...req.query})) // { _id: {} } console.log(req.query) // { _id: { '$ne': 1 } }
nbnkbykc4#
如果您在Mongoose 6中使用Mongoose,则他们引入了sanitizeFilter选项,可按如下方式使用(参见他们的文档):
Mongoose 6
Mongoose
const obj = { username: 'val', pwd: { $ne: null } }; sanitizeFilter(obj); obj; // { username: 'val', pwd: { $eq: { $ne: null } } });
通过在$eq中 Package 任何具有名称以$开头的属性的嵌套对象,对查询过滤器进行消毒,防止查询选择器注入攻击。您也可以将其设置为默认敏感:
mongoose.set('sanitizeFilter', true);
您还可以使用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 });
rlcwz9us5#
--当客户端程序在MongoDB中组装查询时,它构建了一个BSON对象,而不是字符串,因此传统的SQL注入攻击不是问题。有关详细信息,请参阅文档
避免使用eval这样的表达式,因为它可以执行任意的JS。如果你从用户那里获取输入,然后运行eval这样的表达式,而不清理输入,你可能会搞砸。正如JoBu1324所指出的,where,mapReduce和group这样的操作允许直接执行JS表达式。
eval
where
mapReduce
group
5条答案
按热度按时间tyg4sfes1#
如果
req.params.password
为{ $ne: 1 }
,则用户将在不知道密码的情况下被检索($ne
表示 * 不等于1 *)。您可以使用mongo-sanitize:
它将去掉输入中以'$'开头的任何键,因此您可以将其传递给MongoDB,而不必担心恶意用户覆盖。
由于它遵循一个模式,如果 * password * 是一个字符串字段,它会将对象
{ $ne: 1 }
转换为字符串,并且不会造成任何损害。在这种情况下,您不需要清理,只需记住设置一个适当的模式。dxpyg8gm2#
虽然帖子已经过时了,但我还是要回复。
我知道三种方法。
***第一:***有一个多用途的content-filter。还提供MongoDB注入保护过滤的方式。
***第二个:***mongo-sanitize,帮助清理mongodb查询以防止查询选择器注入。
***第三:***我见过over here这个解决方案,它也可以应用于MongoDB,实现起来非常简单,只需要使用JavaScript内置的
escape()
函数。escape()
将字符串转换为ascii
代码。$ne
将转换为%24ne
。ymdaylpp3#
为了防止来自未知结构的数据对象的查询选择器注入
使用mongo-sanitize通过递归进行深度清理:
例如,对于
sanitize(req.query)
,将不会删除嵌套查询选择器:使用
deepSanitize(req.query)
清理的对象(包括嵌套的)会发生变化:使用
{...req.query}
消除对象突变:nbnkbykc4#
如果您在
Mongoose 6
中使用Mongoose
,则他们引入了sanitizeFilter选项,可按如下方式使用(参见他们的文档):通过在$eq中 Package 任何具有名称以$开头的属性的嵌套对象,对查询过滤器进行消毒,防止查询选择器注入攻击。
您也可以将其设置为默认敏感:
您还可以使用
trusted()
跳过默认的敏化:rlcwz9us5#
--
当客户端程序在MongoDB中组装查询时,它构建了一个BSON对象,而不是字符串,因此传统的SQL注入攻击不是问题。
有关详细信息,请参阅文档
避免使用
eval
这样的表达式,因为它可以执行任意的JS。如果你从用户那里获取输入,然后运行eval
这样的表达式,而不清理输入,你可能会搞砸。正如JoBu1324所指出的,where
,mapReduce
和group
这样的操作允许直接执行JS表达式。