NOSQL注入是一种脆弱性,攻击者能够将任意文本注入NOSQL查询。
NOSQL注射与传统的SQL注入攻击非常相似,只是攻击是针对NOSQL数据库的攻击。</em> nosql是任何不使用SQL的数据库的一般术语使用NOSQL的系统(DBMS)是mongodb。
在这篇文章中,我想描述以下内容以显示如何防止NoSQL注入:
- 构建一个简单的nodejs应用
- 了解NOSQL注射攻击是什么
- 使用
npm
软件包来防止攻击
对于先决条件,让我们假设我们有一个现成的蒙古群集群或本地蒙古德安装,并且具有连接URI,例如。 http://localhost:27017。
项目设置
让我们初始化node.js应用并安装几个软件包。在空文件夹中运行以下命令。
$ npm init -y
$ npm i express mongoose
$ npm i nodemon dotenv -D
或,使用Yarn
代替。
$ npm init -y
$ yarn add express mongoose
$ yarn add nodemon dotenv –-dev
创建app.js
和models/user.model.js
。
app.js
require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const routes = require('./routes/index');
const app = express();
app.use(express.json());
app.use(routes);
mongoose
.connect(process.env.MONGODB_URI)
.then(() => {
console.log('Mongoose connected 🍃');
app.listen(3000, () => {
console.log('Server is up and running 🚀');
});
})
.catch((error) => {
console.log(error);
});
型号/user.model.js
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
username: {
type: String,
unique: true
},
password: {
type: String,
unique: true
}
});
const User = mongoose.model('User', userSchema);
module.exports = User;
随着设置的范围,让我们首先查看简单的NOSQL攻击。
出于演示目的,我将创建一个简单的路由文件。
路线/索引
const express = require('express');
const User = require('../models/user.model');
const router = express.Router();
router.get('/users', async (req, res, next) => {
return res.json({
users: await User.find({}).exec()
});
});
router.post('/login', async (req, res, next) => {
const { username, password } = req.body;
const user = await User.findOne({ username, password }).exec();
res.json({
message: `Logged in as ${user.username}`
});
});
module.exports = router;
是时候向/users
提出请求以查看我们拥有的东西了。如前所述,我们将使用 Postman 。
// GET localhost:3000/users
{
"users": [
{
"_id": "6125401c491c0b0bfd123165",
"username": "test1",
"password": "123456",
"__v": 0
},
{
"_id": "6125401c491c0b0bfd123166",
"username": "test2",
"password": "abcdef",
"__v": 0
},
{
"_id": "6125401c491c0b0bfd123167",
"username": "test3",
"password": "sdjndsn",
"__v": 0
}
]
}
这是服务器返回的响应。从上面的代码块中可以看出,我们有三个用户(例如用于演示目的)。
接下来,尝试使用其中一个凭证登录。在下面的请求正文中向/login
提出帖子请求。
{
"username": "test1",
"password": "123456"
}
我们会得到以下回应。到目前为止,一切似乎都很正常,所以让我们更深入地深入研究!
// POST localhost:3000/login
{
"message": "Logged in as test1"
}
执行演示NOSQL注入!!!
要执行NOSQL注入攻击,只需将体内的密码值从"123456"
更改为{ "$ne": "null" }
。因此,新请求主体看起来如下:
{
"username": "test1",
"password": { "$ne": null }
}
请抓住!
$ne
操作员做什么?让我解释一下。
。
$ne
操作员告诉Mongo检查不等于。也就是说,MongoDB不要检查密码是否正确的值,而是简单地检查密码字段是否为null。由于在任何情况下都不能无效密码字段,因此我们可以在不知道密码的情况下欺骗MongoDB。
使用新修改的请求主体向/login
提出后请求后,我们将从服务器中获得以下响应。
// POST localhost:3000/login
{
"message": "Logged in as test1"
}
哦,天哪!ð±
有不止一种做同一件事的方法。例如,我们本可以使用{ "$gt": "" }
而不是$ne
运算符。
幸运的是,防止这种攻击与执行它一样容易。接下来,让我们看一下如何防止NOSQL注入攻击。
介绍NPM模块
我们将从NPM安装express-mongo-sanitize
软件包。运行以下命令:
$ npm i express-mongo-sanitize
或,
$ yarn add express-mongo-sanitize
我们可以在此处学习有关此模块的详细信息:
https://www.npmjs.com/package/express-mongo-sanitize
要求包装返回中间件功能,然后可以按照下面的示例使用。
// Prevent NoSQL injection
const mongoSanitize = require('express-mongo-sanitize');
...
// Prevent NoSQL injection
app.use(
mongoSanitize({
onSanitize: ({ req, key }) => {
// Throw an error
// Catch with express error handler
}
})
);
我希望这篇文章有助于防止NOSQL注入攻击时进行Node.js Express Server。
有关完整的源代码,请参阅此github repo:
https://github.com/liyang51827/express-nosql-injection-demo