Spring MVC 的 input type="hidden" 可能存在的危险和安全问题
Posted
技术标签:
【中文标题】Spring MVC 的 input type="hidden" 可能存在的危险和安全问题【英文标题】:Possible danger and security issues with input type="hidden" with Spring MVC 【发布时间】:2014-10-25 03:09:59 【问题描述】:我在我的项目中使用 Spring MVC 和 Thymeleaf。假设我想实现非常简单的用法 - 编辑用户表单。我使用 SessionAttributes:
@Controller
@RequestMapping(value="/admin/")
@SessionAttributes(value="user")
public class UsersController implements Serializable
在请求 GET 中,我得到了简单的映射:
@RequestMapping(value="user/id", "user/id/", method=RequestMethod.GET)
public String edit(Model model, @PathVariable(value="id") Long id, RedirectAttributes redirectAttributes)
String username = SecurityUtils.getLoggedUsername(); //for example, Spring Security
User user = userService.getByIdAndUsername(id, username);
model.addAttribute("user", user);
return "admin/user";
很简单 - 检查会话记录用户是否有权编辑具有指定 ID 的用户(在本例中 - 只有他的 ID)。带有 id 的字段不会通过“隐藏”字段填充到他的 html 表单中,它将存储在 SessionAttributes 中并在调用 POST 方法后合并。 到目前为止,一切都很好。但是问题来了。如果 - 可以说 - “非常聪明”的用户在他的 HTML 调试器中插入 / 生成一个 POST 请求,其中手动添加了带有 name = "user.id" (或 general = "[object name].[object property] 的隐藏输入)并调用POST 方法?不会合并 SessionAttributes,因为在我的 HTTP 请求属性中存在“ID”。
@RequestMapping(value="user/id", method=RequestMethod.POST)
public String action(@ModelAttribute("user") User user, BindingResult bindingResult, Model model, RedirectAttributes redirectAttributes)
通过这种方式,任何人都可以编辑某人的 ID(假设其他用户的 ID 已知)并编辑其他用户。如何保护系统的这一部分? 目前我只有一个解决方案 - 将任何用户视为潜在的窃贼,并以与 GET 方法相同的方式检查 POST 方法:
@RequestMapping(value="user/id", method=RequestMethod.POST)
public String action(User user, BindingResult bindingResult, Model model, RedirectAttributes redirectAttributes)
String username = SecurityUtils.getLoggedUsername(); //for example, Spring Security
User otherButTheSameUser = userService.getByIdAndUsername(id, username); //remember to evict this user from hibernate session
if(otherButTheSameUser!=null)
userService.update(user);
这应该足够安全,但是由于双重 SQL 检查查询,因此出现了 SQL 性能问题。这是一个好方法吗?还有另一种方法可以实现吗?也许将@SessionAttributes 与具有 sessionAttributes 优先级的请求对象合并?如何实现?
【问题讨论】:
1) 带有斜杠的映射是多余的。 2)整个方法需要返工;尝试修改时需要进行授权检查。这会让你现在遇到的问题烟消云散。 请注意,这不仅适用于 Spring MVC,而且基本上适用于任何绑定请求参数的框架。以 Spring Security 为例,您可以简单地检查当前用户是否正在编辑同一个用户(不需要 SQL,只需带有 SpEL 表达式的@PreAuthorize
注释)。
【参考方案1】:
据我了解,您可以使用DataBinder.setAllowedFields() 或DataBinder.setDisallowedFields() 方法。 Excerpt from javadoc:
In the case of HTTP form POST data for example, malicious clients can
attempt to subvert an application by supplying values for fields or
properties that do not exist on the form. In some cases this could
lead to illegal data being set on command objects or their nested
objects. For this reason, it is highly recommended to specify the
allowedFields property on the DataBinder.
所以,我建议尝试这样的事情:
@InitBinder
protected void initBinder(WebDataBinder binder)
// please check that it's really working
binder.setDisallowedFields("user.id");
【讨论】:
是的,“setDisallowedFields”是一个很好的解决方案,但据我了解,您必须指定具体字段列表,而不是通过“user.*”放置所有字段,因为用户表单中的任何字段允许修改的不会改变。 是的,我已经更新了我的答案。但我也试图证明你可以使用星号作为简单的正则表达式。以上是关于Spring MVC 的 input type="hidden" 可能存在的危险和安全问题的主要内容,如果未能解决你的问题,请参考以下文章
POST JSON 失败,出现 415 Unsupported media type, Spring 3 mvc
在ASP.NET MVC Razor模式里面提交表单数据时,都有一个type=submit的input按钮,
Http请求中Content-Type讲解以及在Spring MVC中的应用