都知道在PHP里,/?key[arr]=value
会被解析为
array(1) { ["key"]=> array(1) { ["arr"]=> string(5) "value" } }
却一直没注意到expressjs里也会如此,
// GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse
req.query.order
// => "desc"
req.query.shoe.color
// => "blue"
req.query.shoe.type
// => "converse"
而在req.query里仅仅是这样不太显眼的一笔带过,似乎嵌套解析已成标配。
但是不得不说的是嵌套解析至少在Node.js里很危险。
例如
app.get('/', function(req, res){
sql.find({_id:req.query.id})
.exec(function(err, data){
res.json({data:data});
});
});
访问/?id[$ne]=1
则会返回不该有的数据,正如这里。
当然这不是mongodb的问题,参数的属性也可能被劫持
app.get('/', function(req, res){
if(req.query.name.length <= 5){
// TODO
res.json({'err':null, 'name':req.query.name});
}else{
res.json({'err':'名字过长!'});
};
});
使用/?name[length]=1
即能绕过这个名字长度的限制。
同样的利用方法在更奇怪的环境可能会造成更严重的后果,最终导致code injection也并非不可能。
大概是意识到了这点,开发团队在下一个Web框架koa里取消了对嵌套解析的支持。
后续分离的cookie-parser也不支持嵌套解析。
最后,我的粗略的解决方案是
app.get('/', function(req, res){
var name = (typeof req.query.name == 'string')?req.query.name:undefined;
// TODO
});
或是使用中间件
app.use(function(req, res, next){
for(var i in req.query)if(typeof req.query[i] != 'string')delete req.query[i];
for(var i in req.body)if(typeof req.body[i] != 'string')req.body[i] = JSON.stringify(req.body[i]);
next();
});
总之,务必先验证req.query.name
,req.body.name
以及req.param('name')
的类型
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论