保护服务器上的Breeze安全,以防止对外键进行恶意更新 [英] Securing Breeze on the server to prevent malicious updates to foreign keys

查看:77
本文介绍了保护服务器上的Breeze安全,以防止对外键进行恶意更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题



我只是想弄清楚在保存Breeze更改时我需要在服务器端实现多少安全措施。特别是,我正在考虑恶意用户如何手动修改SaveChanges请求或修改客户端中的javascript,从而绕过我的常规业务规则-例如,恶意更改实体上的外键ID。



我想确切地了解我需要集中精力进行安全工作的地方;我不想浪费时间实施不需要的安全层。



我在服务器端使用带有.net和Entity Framework的Breeze。

p>

示例



这是一个简单的示例。 ObjectA 引用了 ObjectB ,而 ObjectA 是由特定的用户拥有。因此,我的数据库如下所示:

  ObjectA:

Id ObjectB_Id SomeField User_Id
1 1爱丽丝的对象A 1
2 2鲍勃的对象A 2

对象B:

Id SomeOtherField
1 Foo
2 Bar

用户:

ID名称
1爱丽丝
2鲍勃

从此模型中,我遇到的安全问题是:


  1. 我不希望未经身份验证的用户发生变化任何数据

  2. 我不希望Bob能够对Alice的 ObjectA

  3. 进行任何更改
  4. 我不希望爱丽丝将她的 ObjectA 指向鲍勃的 ObjectB

  5. 我不希望Bob尝试将其 ObjectA 上的 User_Id 更改为Alice

(1)的解决方案很简单;我将确保SaveChanges方法具有 [Authorize] 属性。



我可以轻松地使用Fiddler进行构建一个SaveChanges请求以重现问题2至4-例如,我可以构建一个将 Alice 的ObjectA更改为指向Bob的 ObjectB 的请求code>。消息内容可能如下所示:

 实体:
[
{
Id:1,
ObjectB_Id:2,
SomeField:爱丽丝的ObjectA,
User_Id:1,
entityAspect:
{
entityTypeName: ObjectA:#MyNamespace,
defaultResourceName: ObjectAs,
entityState: Modified,
originalValuesMap :
{
ObjectB_Id: 1
},
autoGeneratedKey:
{
propertyName: Id,
autoGeneratedKeyType:身份
}
}
}
],

正如我期望的那样,当服务器端未实现安全性时,这会将 ObjectB_Id 的更新值保留到数据库中。 / p>

但是,我也已经确认,如果没有 originalValuesMap 中的 ObjectB_Id ,即使我更改了 ObjectB_Id 在消息主体中,不会在数据库中更新。



一般规则?



所以,我认为这意味着我需要在服务器是:



[2013年7月4日编辑-为了清楚起见,已重写]



通常:




  • 邮件中的任何内容均不可信任:既不是originalValuesMap中的值,也不是所谓的不变值

    • 唯一的例外是实体的身份,我们可以认为是正确的。

    • 据说不变的属性可能已被篡改,即使它们不在originalValuesMap中。




对于未更改属性(该属性也不在originalValuesMap上):




  • 当使用任何不变的属性时,我们一定不能使用消息中的值;我们必须从数据库中检索对象并使用其中的值。

    • 例如,在检查对象的电量以确保允许用户更改它,我们将无法信任消息上的UserId;我们必须从数据库中检索实体,并使用该实体中的UserId值


  • 对于任何其他不变属性,我们不会以任何方式使用它,我们不必担心它是否已被篡改,因为即使被篡改,该篡改的值也不会持久化到数据库中



用于更改的属性(属性也位于originalValuesMap上):




  • 业务规则可能会阻止更改特定属性。在这种情况下,我们应该对每个这样的规则进行检查。


  • 如果允许更改值,并且它是外键,我们可能应该执行安全检查,以确保会话标识允许新值使用


  • 我们不得在originalValuesMap中使用任何原始值,因为这些原始值可能已被篡改






实施规则



假设这些规则正确无误,我想有两种选择可以实现更改后的外键周围的安全性:




  • 如果业务规则不允许对特定字段进行更改,我将拒绝SaveChanges请求

  • 如果业务规则允许对特定字段进行更改,我将检查允许新值。为此,不能使用 originalValuesMap ;我需要进入数据库(或其他受信任的来源,例如会话Cookie)



将这些规则应用于对安全性的关注我在上面给出了




  • 安全问题(2)。我需要根据数据库中当前在 ObjectA 上的 User_ID 检查会话上的用户身份。这是因为我不能信任请求中的User_ID,即使它不在 originalValuesMap 中。


  • 安全问题(3)。如果业务规则允许更改 ObjectB ,我将需要检查谁拥有 ObjectB_Id 新值;我将从数据库中检索指定的ObjectB来完成此操作。如果此 ObjectB 不是 ObjectA 的所有者所有,我可能想拒绝更改。


  • 安全问题(4)。如果业务规则允许更改 User ,则该问题已包含在(2)中。




问题



所以,实际上,我正在寻找确认自己在考虑正确路线的问题。


  1. 我的一般规则是否正确?

  2. 我是否执行规则听起来合理吗?

  3. 我错过了什么吗?

  4. 我是不是在使事情复杂化?


解决方案

菲尔...您在这里绝对正确。您在解决问题和威胁以及缓解这些威胁的一般方法方面做得很好。几乎就像您写了Breeze安全性章节的介绍……我们还没有了解。



我不认为您是



读过这篇文章的人可能会认为哇……这是很多工作……微风的东西一定不安全。



很多工作。但是,并不是让微风变得困难。这是存在的每个Web应用程序的必要思考。身份验证只是保护应用程序安全的第一步,也是最简单的步骤。



即使客户端已通过身份验证,您也不应该信任任何客户端请求。这意味着要确保客户端被授权发出请求,并且确保进入和退出服务器的内容与客户端声称要执行的操作和允许执行的操作一致。这些是适用于所有Web应用程序的通用原则,而不仅仅是Breeze应用程序。坚持这些原则在Breeze中并不比在任何其他技术中困难。



您可能会忽略的一种Breeze技术。 EFContextProvider.Context 应该只保存要保存的实体。不要使用它来检索原始实体。您将需要一个单独的 DbContext 来检索原始实体,以便与客户端中的变更集实体进行比较。



我们正在研究一些示例,这些示例演示了如何处理您所描述的问题。例如,我们建议(并演示)一个插入到 BeforeSaveEntitiesDelegate 的验证规则引擎;这种引擎方法使编写服务器端规则束并使它们自动应用变得更加容易。



我们的样本和指南尚未准备好发布。但是,它们也会随之而来。



同时,请按照您在此处描述的直觉进行操作。有关您的进度的博客。告诉我们... ...我们很高兴能突出显示您的帖子。


The Problem

I'm just trying to figure out exactly how much of my own security I need to implement on the server side when saving changes in Breeze. In particular, I'm thinking about how a malicious user could manually hack the SaveChanges request, or hack the javascript in the client, to bypass my normal business rules - for example, to maliciously alter foreign key IDs on my entities.

I want to understand exactly where I need to focus my security efforts; I don't want to waste time implementing layers of security that are not required.

I'm using Breeze with .net and Entity Framework on the server side.

Example

Here's a trivial example. ObjectA has a reference to an ObjectB, and ObjectA is owned by a particular User. So, my database looks like this:

ObjectA:

Id    ObjectB_Id    SomeField          User_Id
1     1             Alice's ObjectA    1
2     2             Bob's ObjectA      2

ObjectB:

Id    SomeOtherField
1     Foo
2     Bar

User:

Id    Name
1     Alice
2     Bob

From this model, the security concerns I have are:

  1. I don't want unauthenticated users to be changing any data
  2. I don't want Bob to be able to make any changes to Alice's ObjectA
  3. I don't want Alice to try to point her ObjectA at Bob's ObjectB.
  4. I don't want Bob to try to change the User_Id on his ObjectA to be Alice.

The solution for (1) is trivial; I'll ensure that my SaveChanges method has an [Authorize] attribute.

I can easily use Fiddler to build a SaveChanges request to reproduce issues 2 to 4 - for example, I can build a request which changes Alice's ObjectA to point to Bob's ObjectB. This is what the message content might look like:

"entities":
[
    {
        "Id":1,
        "ObjectB_Id":2,
        "SomeField":"Alice's ObjectA",
        "User_Id":1,
        "entityAspect":
        {
            "entityTypeName":"ObjectA:#MyNamespace",
            "defaultResourceName":"ObjectAs",
            "entityState":"Modified",
            "originalValuesMap":
            {
                "ObjectB_Id":"1"
            },
            "autoGeneratedKey":
            {
                "propertyName":"Id",
                "autoGeneratedKeyType":"Identity"
            }
        }
    }
],

As I'd expect, when no security is implemented on the server side, this persists the updated value for ObjectB_Id into the database.

However, I've also confirmed that if there is no entry for ObjectB_Id in the originalValuesMap, then even if I change the value for ObjectB_Id in the main body of the message it is NOT updated in the database.

General Rules?

So, I think this means that the general security rules I need to follow on the server are:

[Edited 4 July 2013 - rewritten for clarity]

In general:

  • Nothing in the message can be trusted: neither values in the originalValuesMap nor supposedly "unchanged" values
    • The only exception is the identity of the entity, which we can assume is correct.
    • Supposedly "unchanged" properties may have been tampered with even if they are not in the originalValuesMap

For "Unchanged" properties (properties which are not also on the originalValuesMap):

  • When "using" any "unchanged" property, we must NOT use the value from the message; we must retrieve the object from the database and use the value from that.
    • for example, when checking owenership of an object to ensure that the user is allowed to change it, we cannot trust a UserId on the message; we must retrieve the entity from the database and use the UserId value from that
  • For any other "unchanged" property, which we are not using in any way, we don't need to worry if it has been tampered with because, even if it has, the tampered value will not be persisted to the database

For changed properties (properties which are also on the originalValuesMap):

  • Business rules may prevent particular properties being changed. If this is the case, we should implement a check for each such rule.

  • If a value is allowed to be changed, and it is a foreign key, we should probably perform a security check to ensure that the new value is allowed to be used by the session identity

  • We must not use any of the original values in the originalValuesMap, as these may have been tampered with

[End of edit]

Implementing the Rules

Assuming that these rules are correct, I guess there are a couple of options to implement security around the changed foreign keys:

  • If the business rules do not allow changes to a particular field, I will reject the SaveChanges request
  • If the business rules DO allow changes to a particular field, I will check that the new value is allowed. In doing this, CANNOT use the originalValuesMap; I'll need to go to the database (or other trusted source, eg session Cookie)

Applying these rules to the security concerns that I gave above,

  • security concern (2). I'll need to check the user identity on the session against the User_ID on the ObjectA that is currently in the database. This is because I cannot trust the User_ID on the request, even if it is not in the originalValuesMap.

  • security concern (3). If the business rules allow a change of ObjectB, I will need to check who owns the new value of ObjectB_Id; I'll do this by retrieving the specified ObjectB from the database. If this ObjectB is not owned by ObjectA's owner, I probably want to reject the changes.

  • security concern (4). If the business rules allow a change of User, this is already covered by (2).

Questions

So, really, I'm looking for confirmation that I'm thinking along the right lines.

  1. Are my general rules correct?
  2. Does my implementation of the rules sound reasonable?
  3. Am I missing anything?
  4. Am I over complicating things?

解决方案

Phil ... you are absolutely on the right track here. You've done a nice job of laying out the issues and the threats and the general approach to mitigating those threats. It is almost as if you had written the introduction to the Breeze security chapter ... which we haven't gotten to yet.

I do not think that you are "over complicating things"

Someone reading this might think "wow ... that's a lot of work ... that Breeze stuff must be insecure".

Well it is a lot of work. But it isn't Breeze that is making it difficult. This is the necessary thinking for every web application in existence. Authentication is only the first step ... the easiest step ... in securing an application.

You shouldn't trust any client request ... even if the client is authenticated. That means making sure the client is authorized to make the request and that the content entering and exiting the server is consistent with what the client is both claiming to do and is allowed to do. These are general principles that apply to all web applications, not just Breeze applications. Adhering to these principles is no more difficult in Breeze than in any other technology.

One Breeze technicality you may have overlooked. The EFContextProvider.Context should only hold the entities to save; don't use it to retrieve original entities.You'll need a separate DbContext to retrieve the original entities to compare with the change-set entities from the client.

We are working on samples that demonstrate ways to handle the issues you described. For example, we're recommending (and demo'ing) a "validation rules engine" that plugs into the BeforeSaveEntitiesDelegate; this "engine" approach makes it easier to write bunches of server-side rules and have them applied automatically.

Our samples and guidance aren't quite ready for publication. But they are coming along.

Meanwhile, follow your instincts as you've described them here. Blog about your progress. Tell us about it ... and we'll be thrilled to highlight your posts.

这篇关于保护服务器上的Breeze安全,以防止对外键进行恶意更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆