先例:路由值或具有相同名称的POST表格?

问题描述 投票:4回答:2

假设我有一条看起来像/controller/action/UserID的路线,可以接受POST。

然后假设某人发布到该URL,并且将名为UserID的变量设置为其他名称。

我想弄清楚的是,是否存在一个安全问题,其中一个值“偷偷摸摸”通过了我进行的权限检查。

asp.net-mvc security asp.net-mvc-4 post
2个回答
1
投票

参数源优先级的顺序由ValueProviderFactories.Factories集合确定,其中(默认情况下)在模型绑定期间POST版本的参数优先于路由数据。

因此,如果有人将User ID = 666 POST到控制器/controller/action/777中的UserId URL,则为666。

本文的Value Providers部分很好地概述了其工作原理:

在运行时,ASP.NET MVC使用在ValueProviderFactories类评估模型的请求值粘合剂可以使用。

默认情况下,值提供者集合从各种资源按以下顺序排列:

  1. 先前绑定的动作参数,当该动作是子动作时动作
  2. 表单字段(Request.Form
  3. JSON中的属性值请求正文(Request.InputStream),但仅当请求为AJAX请求
  4. 路由数据(RouteData.Values
  5. 查询字符串参数(Request.QueryString
  6. 已发布文件(Request.Files

1
投票

不管参数优先级如何,您都应检查用户是否有权访问所有POST和GET上的指定UserID

用户可以轻松地潜入一个额外的UserID参数,就像将形式action更改为路径中带有其他UserID的URL一样,因为这些只是客户端变量。

<form method="post" action="/controller/action/1">

很容易更改为

客户端上的<form method="post" action="/controller/action/2">

这就像添加一个隐藏字段一样简单:<form method="post" action="/controller/action/1"> <input type="hidden" name="UserID" value="2" />

如果您的控制器方法签名是

[HttpPost]
public ActionResult Foo(model model, int userId)

并且您仅在输入参数中使用userId(例如,不直接访问Request.Formmodel中的值),那么参数优先级是什么都没有关系。您应该验证当前登录的用户是否有权查看或编辑控制器POST方法中的userId ID,因为无论如何都不能信任所有客户端提供的参数。

例如

[HttpPost]
public ActionResult Foo(model model, int userId)
{
    if (CurrentUserHasPermissionToEdit(userId))
    {
      // Do stuff
    }
    else
    {
      // Reject
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.