ASP.NET MVC中使用ViewModel时,Edit控制器仍易遭过度提交?如何防范?
关于ViewModel过度提交修改非目标dbModel的疑问与解决方案
你提的这个问题非常关键——是的,这种情况完全有可能发生,而且是过度提交攻击里很典型的一种场景,我来给你拆解清楚:
为什么会有风险?
虽然你在代码里没有手动把viewModel.Id绑定到dbModel上,但ASP.NET的默认模型绑定机制会自动解析请求中的所有参数,包括攻击者恶意构造的Id值,把它填充到viewModel.Id里。接下来你用db.Models.Find(viewModel.Id)去查询数据库,这就等于把控制权交给了攻击者——他们只要在请求里把Id改成任意存在的值,你的代码就会修改那个对应的数据,完全偏离了原本要修改的目标记录。
几个简单有效的防范方法
从可信来源获取Id:不要依赖ViewModel里的Id,而是从路由参数、当前登录用户的关联数据这类攻击者无法篡改的地方获取。比如把Action改成接收路由里的Id:
[HttpPost] public ActionResult Edit(int id, ViewModel viewModel)之后用这个
id去查询dbModel,完全忽略viewModel.Id,从根源上切断攻击者的篡改路径。使用绑定白名单:在ViewModel参数上添加
[Bind]特性,明确指定允许绑定的属性,直接排除Id。比如:public ActionResult Edit([Bind(Include = "Name,Description")] ViewModel viewModel)这样模型绑定只会处理你指定的属性,请求里的
Id参数会被直接忽略,viewModel.Id不会被赋值。创建专用的更新ViewModel:干脆新建一个只包含需要修改的属性的ViewModel,完全去掉
Id字段。比如:public class UpdateModelViewModel { public string Name { get; set; } public string Description { get; set; } }这样不管攻击者怎么构造请求,都没有
Id字段可以提交,彻底消除这个风险。
修改后的示例代码(用路由Id的方式)
[HttpPost] public ActionResult Edit(int id, ViewModel viewModel) { if (ModelState.IsValid) { var dbModel = db.Models.Find(id); if (dbModel == null) { return NotFound(); } // 只绑定需要更新的属性 dbModel.Name = viewModel.Name; dbModel.Description = viewModel.Description; db.Entry(dbModel).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } return View(viewModel); }
内容的提问来源于stack exchange,提问作者justiceorjustus
相关产品推荐
相关产品推荐

