从视图回发时保护实体ID的最有效方法

时间:2013-04-25 12:50:06

标签: asp.net-mvc viewmodel code-injection

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

在编辑视图模型时,我一直在考虑如何在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,该怎么办?随机更新各种Post

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

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

2 个答案:

答案 0 :(得分:2)

这是一种直接参考攻击,根据oswap建议,您可以

  • 通过将其交换为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这样的工具或使用浏览器的控制台模式翻转隐藏字段的人的攻击。<​​/ p>

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

答案 1 :(得分:1)

你正在谈论让某人不要破解他们的形式,说当他们应该编辑记录1时他们正在更新记录2,对吧?并不一定让人们不知道用户ABC的帖子有1的身份?

使用标识列创建表格并查看模型可能会更简单一些。您可以使用标识构建所有url / GET进程,并且可以使用guid执行所有POST处理。这将使您不必构建一些内存中的映射,使用会话密钥,创建动作过滤器等​​。我喜欢你 - 我想减少你对会话的依赖程度,因为它是时间敏感的;一旦你的会话到期,你在内存中保存的映射就会过期,所以它总会返回假阴性。

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

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

您还可以尝试在POST表单中添加某种散列算法。类似的东西,哈希身份,创建帖子的用户,创建帖子的时间以及最终用户无法看到的实体上的一些随机不可更新的盐。你也可能包含一些随机的东西(比如渲染页面的时间),以确保每次页面加载时哈希都是唯一的,这样就可以防止某人使用guids / hashes(你需要在如果帐户遭到入侵,则单独的字段。您的验证过程将匹配POST的哈希值与实体上相同字段的哈希值,并仅在哈希值匹配时执行更新。但这似乎对我来说太过分了。