Node.js NoSQL操作
1.10.1 【必须】校验参数值类型
- 将HTTP参数值代入NoSQL操作前,应校验类型。如非功能需要,禁止对象(Object)类型传入。
// bad:执行NOSQL操作前,未作任何判断
app.post("/", (req, res) => {
db.users.find({ username: req.body.username, password: req.body.password }, (err, users) => {
// **TODO:** handle the rest
});
});
// good:在进入nosql前先判断`__USER_INPUT__`是否为字符串。
app.post("/", (req, res) => {
if (req.body.username && typeof req.body.username !== "string") {
return new Error("username must be a string");
}
if (req.body.password && typeof req.body.password !== "string") {
return new Error("password must be a string");
}
db.users.find({ username: req.body.username, password: req.body.password }, (err, users) => {
// **TODO:** handle the rest
});
});
为什么要这么做?
JavaScript中,从http或socket接收的数据可能不是单纯的字符串,而是被黑客精心构造的对象(Object)。在本例中:
- 期望接收的POST数据:username=foo&password=bar
- 期望的等价条件查询sql语句:select * from users where username = 'foo' and password = 'bar'
- 黑客的精心构造的攻击POST数据:username[$ne]=null&password[$ne]=null
或JSON格式:{"username": {"$ne": null},"password": {"$ne": null}}
- 黑客篡改后的等价条件查询sql语句:select * from users where username != null & password != null
- 黑客攻击结果:绕过正常逻辑,在不知道他人的username/password的情况登录他人账号。
1.10.2 【必须】NoSQL操作前,应校验权限/角色
- 执行NoSQL增、删、改、查逻辑前,应校验权限
// 使用express、mongodb(mongoose)实现的删除文章demo
// bad:在删除文章前未做权限校验
app.post("/deleteArticle", (req, res) => {
db.articles.deleteOne({ article_id: req.body.article_id }, (err, users) => {
// TODO: handle the rest
});
});
// good:进入nosql语句前先进行权限校验
app.post("/deleteArticle", (req, res) => {
checkPriviledge(ctx.uin, req.body.article_id);
db.articles.deleteOne({ article_id: req.body.article_id }, (err, users) => {
// TODO: handle the rest
});
});
关联漏洞:高风险 - 越权操作,高风险 - NoSQL注入