保护服务器上的Breeze安全,以防止对外键进行恶意更新 [英] Securing Breeze on the server to prevent malicious updates to foreign keys
问题描述
问题
我只是想弄清楚在保存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鲍勃
从此模型中,我遇到的安全问题是:
- 我不希望未经身份验证的用户发生变化任何数据
- 我不希望Bob能够对Alice的
ObjectA
- 我不希望爱丽丝将她的
ObjectA
指向鲍勃的ObjectB
。 - 我不希望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 $ c的值, $ c>在消息主体中,不会在数据库中更新。
一般规则?
所以,我认为这意味着我需要在服务器是:
[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)中。
问题
所以,实际上,我正在寻找确认自己在考虑正确路线的问题。
- 我的一般规则是否正确?
- 我是否执行规则听起来合理吗?
- 我错过了什么吗?
- 我是不是在使事情复杂化?
菲尔...您在这里绝对正确。您在解决问题和威胁以及缓解这些威胁的一般方法方面做得很好。几乎就像您写了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:
- I don't want unauthenticated users to be changing any data
- I don't want Bob to be able to make any changes to Alice's
ObjectA
- I don't want Alice to try to point her
ObjectA
at Bob'sObjectB
. - I don't want Bob to try to change the
User_Id
on hisObjectA
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 theObjectA
that is currently in the database. This is because I cannot trust the User_ID on the request, even if it is not in theoriginalValuesMap
.security concern (3). If the business rules allow a change of
ObjectB
, I will need to check who owns the new value ofObjectB_Id
; I'll do this by retrieving the specified ObjectB from the database. If thisObjectB
is not owned byObjectA
'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.
- Are my general rules correct?
- Does my implementation of the rules sound reasonable?
- Am I missing anything?
- 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屋!