【问题标题】:Asp.Net MVC corrupting hidden while updating database [closed]更新数据库时隐藏的 Asp.Net MVC 损坏 [关闭]
【发布时间】:2017-09-21 14:03:47
【问题描述】:

我正在学习 Asp MVC 5 并面临这样的问题。使用为我创建的脚手架视觉工作室更新控制器和视图。编辑值时,我注意到它使用隐藏来识别当前记录。例如:

http://localhost:61551/StoreManager/Edit/6

如果您使用开发工具检查页面 - 您会发现一个值为“6”的隐藏输入。

<input data-val="true" data-val-number="The field AlbumId must be a number." data-val-required="The AlbumId field is required." id="AlbumId" name="AlbumId" type="hidden" value="6">

在视图中我们可以看到 ASP 添加了代码来生成隐藏输入

@Html.HiddenFor(model => model.AlbumId)

我可以轻松地将其修改为任何其他值,然后当我单击保存时,ASP 会更新完全不同的记录。因此,黑客可能很容易破坏您的所有数据库。有什么方法可以防止这种情况或使用不同的方法或验证它吗?

谢谢!

【问题讨论】:

  • 是的,这是一种常见的方式,即基于 Web 的应用程序可能设计不佳且充满安全漏洞。学习一些与网站设计相关的最佳实践会为您提供最好的服务。
  • 你知道 localhost 只存在于你的机器上......我们看不到它!
  • 当然,我以为你们对问题很熟悉,不需要提供实时链接
  • 通过编辑 URL 来破解它不是更容易吗?例如http://localhost:61551/StoreManager/Edit/7.
  • 这就是存在安全和 ACL 主题的原因。即使缺少标识符,您仍应在服务器端执行任何操作之前验证权限。

标签: c# asp.net entity-framework model-view-controller asp.net-mvc-5


【解决方案1】:

这里的根本问题是您的网站信任网络浏览器提供的任何输入。无论输入是通过隐藏字段(在这种情况下)还是通过 URL 或某些非隐藏字段(例如,您可以想象一个 UI 中有一个下拉选择器让您选择您要修改的数据项),或者即使该记录是在网页上的 JavaScript 发送到后端的一些 JSON 消息中标识的。

因此,您描述的问题实际上与 this 作为隐藏字段的特定细节无关,也与您使用 ASP.NET 的事实无关,也不是特殊的VS 搭建应用程序的方式。您可以更改这些细节中的任何一个,但问题仍然存在,因为恶意用户可以在请求中完全伪造任何内容。隐藏字段并不比任何其他类型的输入更难或更容易伪造。

从安全角度来看,您需要将来自客户端的所有数据视为可疑数据。确定此类输入是否有效的规则是特定于应用程序的,这就是为什么脚手架代码不会(也不能)尝试处理此问题的原因。

唯一的解决方案是使用某种机制,让您确定是否允许发送请求的用户执行请求所要求的操作。如果您实现了这一点,那么最终用户是否故意更改 ID 并不重要:如果特定用户有权编辑 id 6 的记录或 id 7 的记录,那么如果他们编辑 6 并更改它到 7,这是他们的决定——他们被允许编辑记录 7 并选择这样做;他们以一种奇怪的方式做到了,但那是他们的了望。如果用户有权编辑 6 而不是 7,并且他们尝试将 id 更改为 7,那么您的服务器应该使用 403(禁止)响应代码拒绝请求。

这意味着您需要某种方式来识别用户(或者至少有某种方式了解他们的一些事情 - 足以确定他们有权做什么;在某些情况下可能就足够了要知道用户成功地通过了某些安全权限的身份验证——对于某些操作,合理的安全策略可能只是信任所有经过身份验证的用户,或属于特定安全组的所有用户)。并且您需要通过某种方式来确定是否允许用户在识别特定实体后对其进行特定操作。

通常,这意味着让用户登录(您可以通过多种方式做到这一点 - 您的应用可能在具有某种单点登录系统的组织内运行,或者您可以遵从外部 ID 提供商,如 Google、Facebook 或 Azure Active Directory,或者您可以自己管理帐户 - 例如,ASP.NET 能够为您管理 SQL Server 中的用户帐户)。你需要决定你的安全策略实际上是如何工作的,这是一个开放式的事情,我什至不会尝试给出示例,然后你需要编写代码来执行该策略。

您从 VS 获得的基本脚手架应用程序并不能完成所有这些,因为您可以通过多种不同的方式来处理它。它可以做其中的一部分——你可以告诉它使用用户帐户支持来配置应用程序(例如,如果你愿意,它会在你创建项目时设置基于 SQL Server 的帐户管理,或者它可以将其设置为使用 AAD ,或通过集成的 Windows 身份验证进行单点登录)。但决定你想要什么样的安全策略仍然是你的工作。如果您想要一个非常基本的模型,例如“这只能由经过身份验证的用户访问”,那么您可以将 [Authorize] 自定义属性放在控制器上。但是,如果您想要实体级别的安全性(例如,确定允许谁修改任何特定实体的规则),那么您需要编写代码来实现这一点。

【讨论】:

    【解决方案2】:

    有很多方法可以解决这个问题。一种这样的方法是使用User roles 来限制谁可以访问各种方法(如编辑)。

    你可以有这样的 sn-ps:

    if (User.IsInRole("Administrators"))
    {
        // TODO
    }
    

    或者你可以像这样使用Authorize attributes

    [Authorize(Roles="Administrators")]
    public class AdminController : Controller
    {
        // TODO
    }
    

    或者,这些也可以放在控制器内的特定方法上:

    [Authorize(Roles="Administrators")]
    public ActionResult Edit(Album model)
    {
        // TODO
    }
    

    当您对谁可以访问什么具有广泛定义的角色时,这些是更好的解决方案,但假设您有一个服务,每个用户都可以登录并管理自己的项目。您还可以在模型/表格中添加一个字段来表示该项目所属的人,例如:

    if (albumModel.UserName == HttpContext.Current.User.Identity.Name)
    {
        // allow user to edit if it is his item
    }
    

    您还可以查看如何组合这些,例如如果允许管理员编辑用户的相册,可以先判断用户是否属于管理员角色,否则判断是否是该用户的相册等

    【讨论】:

    • 这 100% 解决了我的问题。感谢您的回复!
    • @Vadym 没问题。仅供参考,我认为您尝试过,但您只能检查一个答案。不过很乐意提供帮助。
    • 确实如此。两个答案都很好,但不幸的是不能同时选择:)
    猜你喜欢
    • 2012-10-31
    • 2017-06-26
    • 2016-05-30
    • 1970-01-01
    • 2013-07-29
    • 2012-08-27
    • 2021-12-10
    • 1970-01-01
    • 2013-06-02
    相关资源
    最近更新 更多