1

编辑- 只是一个快速的编辑,从一个明确的问题开始!我实质上要问的是,从视图发回时保护我的实体标识符的最有效方法是什么?

我一直在考虑在编辑视图模型时保护 POST 上的 ID 的方法。让我们以一个示例实体为例

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
}

及其对应的视图模型:

public class PostViewModel
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
}

现在,当我将此视图模型传递给允许用户编辑它的视图时,我将执行以下操作:

public ActionResult EditPost(PostViewModel viewModel)
{
    Post post = database.Posts.Single(p => p.Id.Equals(viewModel.Id));
    post.Title = viewModel.Title;
    post.Content = viewModel.Content;
    database.Entry(post).State = System.Data.EntityState.Modified;
    database.SaveChanges();

    return View(viewModel);
}

或者也许通过参数列表传递 ID,如下所示:

public ActionResult EditPost(int postId, PostViewModel viewModel)
{
    Post post = database.Posts.Single(p => p.Id.Equals(postId));
    // and the rest
}

无论哪种方式,我们都需要返回我们正在更新的实体的标识符以及 POST 数据。我们如何确保更新的实体是预期的?

我想我们可以验证用户是否有足够的访问权限来更新这个实体......但是如果用户的帐户被盗用,并且一些随机黑客开始使用他们的帐户注入随机 ID 怎么办?随机更新各种Posts。

可能建议实体使用复杂的(如 GUID)标识符,这会使猜测变得更加困难,但这会使您的漂亮友好的 URL 看起来对普通用户来说有点吓人,在查看Postfor时不得不传递它例子。

我们如何在这里两全其美?保持干净的 URL,但保护我们的实体免受注入攻击?

4

2 回答 2

2

这是直接引用攻击,根据 oswap 的建议,您可以

  • 通过将 id 交换为 guid 来混淆 id,然后将映射保存在内存/会话中
  • 在会话中保留对项目的引用并确保它与返回的相同

我解决这个问题的方法是使用属性,我手头没有任何代码,所以你需要类似的东西

Decorate get action with attribute
on gets, attribute clears item list from session
Pull Item from db
store items id in session for item

decorate post action with attribute    
attribute makes sure modelstate is valid first (saves double validating)
attribute looks in session for id
attribute checks the id against the stored value
if id matches, action can continue
if id doesn't match, an entry is made in modelstate

使用这种方法,您可以保护自己免受有人在 burpsuite 等工具中摆弄您的 id 或使用浏览器的控制台模式来翻转隐藏字段。

此外,作为此过程的开始,始终确保您的获取项目不会盲目地从数据库中获取,而是首先确保该人实际上可以获取该项目,即。属于他们的数据集等

于 2013-04-25T14:48:03.903 回答
1

您是在谈论阻止某人在他们应该编辑记录 1 时入侵他们的表单以说他们正在更新记录 2,对吗?并且不一定阻止人们发现用户 ABC 的帖子的身份为 1?

也许使用标识列guid 创建表和视图模型会更简单一些。您的所有 urls / GET 过程都可以使用身份构建,并且您可以使用 guid 进行所有 POST 处理。这将使您不必构建一些内存映射、使用会话键、创建操作过滤器等​​。我和您一样 - 我想减少您对会话的依赖量,因为它是时间敏感的;一旦你的会话过期,你保存在内存中的映射就会过期,所以它总是会返回一个假阴性。

不过,这可能会消除数据层中的一些可重用性。

编辑:但我认为最好的保护就像你说的那样 - 验证编辑记录的帐户有权编辑记录。如果将其与 guid(或表单上加密的内容)结合使用,将很难随机猜测记录。

您还可以尝试在 POST 表单中添加某种散列算法。例如,对身份、创建帖子的用户、创建帖子的时间以及最终用户看不到的实体上的一些随机不可更新的盐进行哈希处理。您还可能包含一些随机的内容(例如呈现页面时的刻度时间),以确保每次页面加载时哈希都是唯一的,这将防止有人耕种 guid / 哈希(您需要将刻度张贴在单独的字段)如果帐户被盗用。您的验证过程会将 POST 的哈希与实体上相同字段的哈希匹配,并且仅在哈希匹配时执行更新。但这对我来说似乎有点矫枉过正。

于 2013-04-25T16:06:14.423 回答