你能告诉我express-mongo-sanitize是否有效吗?

Can you tell me if express-mongo-sanitize is working?

提问人:Bugwhacker 提问时间:8/22/2021 更新时间:8/25/2023 访问量:2443

问:

我正在尝试为我不起眼的小型 MERN Web 应用程序设置一些安全中间件,我目前正在使用 helmet 和 express-mongo-sanitize,专门用于防止 NoSQL 注入攻击。

但是,我已经在我的服务器.js文件中进行了如下设置:

const express = require('express')
const helmet = require('helmet')
const mongoSanitize = require('express-mongo-sanitize')

...

app.use(mongoSanitize())
app.use(helmet())

// Routes below

...

我试图通过进行模拟注册来测试它,例如:

用户名: {“$gt”: “”} password: 'TestPassword'

因此,req.body 将是:

{

username: '{"$gt": ""}',

password: 'TestPassword'

}

但是 express-mongo-sanitize 似乎没有捕捉到它,它会进入我的数据库。我是不是误会了什么?用户名键的值是一个字符串,所以也许它已经可以了?请原谅我的无知,我正在学习。

JavaScript MongoDB 安全性 SQL注入 MERN

评论


答:

2赞 breaths 8/24/2021 #1

express-mongo-sanitize 的作用是清理以美元符号开头的密钥。

username: '{"$gt": ""}' --> this isn't a key starting with a dollar sign. Rather, the value of username is just a string.

请尝试将以下对象发送给它:

{

"username": { "$gt": "" }

}
1赞 A10n 10/28/2021 #2

据我了解,从调试和浏览代码来看,它清理的键是具有 $ 或点的查询和 post 参数的 key=value 对中的任何潜在键。它还会尝试清理请求正文和标头中的任何键。

例如,即使是上面上一个用户提供的 json 也无法做到这一点。

但 https://your-domain/?$user=json 将被清理为 user=json。

它不会像您和我所期望的那样从参数的值中删除 $。我还在 github 上向创建者提出了一个问题,看看他怎么说。我认为安全风险是针对密钥和值的。如果您不保存 mongodb 的密钥而是保存值,这没有任何好处。

作为参考,它会检查以下 HTTP 部分以删除任何可能有害的 $ 或 .

['body', 'params', 'headers', 'query'].forEach(function (key) ...

0赞 Charlie 11/28/2022 #3

我认为@A10n的答案是正确的,因此“express-mongo-sanitize”似乎只是一个部分解决方案。我添加了我的快速和肮脏的解决方案,以从每个 req.body/params 对象中删除大括号(这应该可以钝化大多数 NoSQL 攻击),如下所示:

// Middleware that replaces all {} symbols with [] to prevent NoSQL attack
    const removeCurlies = (req, res, next) => {
      Object.keys(req.body).forEach((key) => {
        req.body[key] = _.replace(req.body[key], "{", "[");
        req.body[key] = _.replace(req.body[key], "}", "]");
      });
      Object.keys(req.params).forEach((key) => {
        req.params[key] = _.replace(req.params[key], "{", "[");
        req.params[key] = _.replace(req.params[key], "}", "]");
      });
      next();
    };

然后,在您的路线之前:

    app.use(removeCurlies);
1赞 Tony 1/4/2023 #4

遇到了同样的问题,对我有用的是在使用包之前解析传入的请求正文。喜欢这个。。。mongoSanitize

const express = require("express")
const mongoSanitize = require("express-mongo-sanitize')

const app = express()

app.use(express.json())
app.use(mongoSanitize())

0赞 dimitris tseggenes 8/25/2023 #5

仔细阅读文档

此模块在以 $ 符号开头的对象中搜索任何 或包含 .、来自 req.body、req.query 或 req.params。然后它可以 也:

  • 从对象中完全删除这些键和关联数据,或者
  • 将禁止的字符替换为另一个允许的字符。

它搜索 KEYS 而不是值。所以在这种情况下

{ username: '{"$gt": ""}', password: 'TestPassword'}

$ 符号存在于 key 的值中,而不是 key 本身。这就是为什么 express-mongo-sanitize 没有捕获它的原因。username

为了更好地理解它,请看这个例子

// req.body
{ 
    "username": "{'$gt': ''}", 
    "password": "TestPassword",
    "$ne": "1",
    "$gt": "",
}

// the default implementation of express-mongo-sanitize will remove 
// the last two keys and not the first one.
// So, right after the middleware you will get this 
{ 
    username: "{'$gt': ''}", 
    password: "TestPassword",
}