开贴讨论如何避免MongoDB注入
发布于 10 年前 作者 crystaldust 6480 次浏览 最后一次编辑是 8 年前 来自 问答

最近闲来无事看到MongoDB的注入问题。目前使用Express.JS,假设构建一个如下的登陆http请求: http://yourdomain?email=hello@world.com&password[$ne]=idontknow

bodyParser解析之后,从拿到的参数就是: { email : ‘hello@world.com’, password : { ‘$ne’ : ‘idontknow’ } }

那么去MongoDB执行查询的时候,查询就变成: db.accounts.findOne( { email : ‘hello@world.com’, password : { ‘$ne’ : ‘idontknow’ } } ); 因为 password : { ‘$ne’ : ‘idontknow’ } } 这个条件一般都会成立(至少密码会做个加密什么的,当然idontknow这个字符串也可以写成空字符串),判断成账号存在,然后返回账号信息,这样,在不知道密码的情况下就能拿到信息了。

目前我的思路是:所有的http参数key-value,value都必须是string,如果传递复杂的类型,value先转换成JSON字符串,服务器解析。Express.JS的第一个router或者middleware对参数的类型进行判断,只允许string或number,把object类型过滤掉。简单粗暴但是感觉不怎么体面,所以开个帖子大家来讨论一下,欢迎拍砖。

6 回复

简单的做法自然就是不接受 object 类型的参数。但是有的系统是用到了 object 类型的参数的,这时我觉得只要递归地检查所有的 key 中没有美元符号(或者不以美元符号开头)就行了,似乎 MongoDB 所有的的操作符都是美元符号开头。

@jysperm 嗯,比较稳妥的做法就是把MongoDB的操作过滤一下

比较同意在查询DB前,检查查询对象中的美元符号

如果不想让 http 参数嵌套的话,bodyparser 有一个参数可以控制只解析第一层的嵌套,深嵌套不解析,以字符串返回。 不过我更赞同在 controller 里面做这个事情:每个 user input 都需要按某种方式过滤。

@alsotang 多谢指点,收益颇丰啊

回到顶部