使用 Mongoose 减轻 MongoDB 注入攻击

Joh*_* P. 7 mongoose mongodb node.js nosql-injection

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

const UserSchema = new mongoose.Schema({ userName: String, password: String });
Run Code Online (Sandbox Code Playgroud)

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

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
    });
});
Run Code Online (Sandbox Code Playgroud)

我会接受以下 JSON 有效负载的注入攻击,它总是会找到一个用户:

{
    "email": { "$gte": "" },
    "password": { "$gte": "" }
}
Run Code Online (Sandbox Code Playgroud)

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

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

const userName = request.body.userName.toString();
Run Code Online (Sandbox Code Playgroud)

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

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

我在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

Joh*_*yHK 7

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

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