7

我正在为 NodeJS 使用Mongoose ODM 包装器,我担心注入攻击。假设我有以下架构:

const UserSchema = new mongoose.Schema({ userName: String, password: String });

如果我要执行如下所示的登录请求:

router.post('/login', (request, response) => {

    const userName = request.body.userName;
    const password = request.body.password;

    User.findOne({ userName: userName }, function (error, user) {
        // ... check password, other logic
    });
});

我将对使用以下 JSON 有效负载的注入攻击持开放态度,该有效负载将始终找到用户:

{
    "email": { "$gte": "" },
    "password": { "$gte": "" }
}

我不关心密码,因为如果找到阻止任何实际登录的用户,它会被散列,但我想确保我的输入被清理,这样攻击者甚至不会做到这一点。

我知道在类似的StackOverflow 帖子中引用的mongo-sanitize NPM 包似乎删除了所有以“$”开头的 JSON 键。无论如何我都打算使用它,但我永远不会允许用户提交原始的、未解析的 JSON。在这种情况下,假设我进行了正确的检查,只在 userName 上调用 toString() 是一种好习惯吗?null

const userName = request.body.userName.toString();

这将消除查询的执行,但感觉不是很安全。我认为以下是一种更好的方法,因为它试图转换userName为 a String

User.findOne({ userName: { "$eq": userName } }, function (error, user) {
     // ... other logic
});

我在Model.findOne() 文档中找不到任何与此相关的内容,这让我相信我忽略了一些东西。

任何见解将不胜感激。

其他参考:

  1. https://blog.websecurify.com/2014/08/hacking-nodejs-and-mongodb.html
  2. https://ckarande.gitbooks.io/owasp-nodegoat-tutorial/content/tutorial/a1_-_sql_and_nosql_injection.html
4

2 回答 2

4

虽然您可以使用$eq来确保在查询中使用相等比较,但您的快速路由处理程序是执行请求格式验证的更好地方。

请求正文中的有效POST /login应该有userNamepassword字符串字段。如果不是,它应该在到达 Mongoose 之前被拒绝。

于 2018-10-15T16:33:48.637 回答
0

此外,您可以使用 npm 包“ mongo-sanitize ”,如下所示:

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

// The sanitize function will strip out any keys that start with '$' in the input,
// so you can pass it to MongoDB without worrying about malicious users overwriting
// query selectors.
var clean = sanitize(req.params.username);

Users.findOne({ name: clean }, function(err, doc) {
  // ...
});

如果 sanitize() 传递了一个对象,它将改变原始对象。

于 2020-07-06T08:16:46.840 回答