BreezeJS SaveChanges() 安全问题
BreezeJS SaveChanges() security issue
我正在使用 BreezeJS,但对如何保存数据有疑问。这是我的代码和评论
[Authorize]
/*
* I want to point out the security hole here. Any Authorized user is able to pass to this method
* a saveBundle which will be saved to the DB. This saveBundle can contain anything, for any user,
* or any table.
*
* This cannot be stopped at the client level as this method can be called from Postman, curl, or whatever.
*
* The only way I can see to subvert this attack would be to examine the saveBundle and verify
* no data is being impacted that is not owned or related directly to the calling user.
*
* Brute force could be applied here because SaveResult contains Errors and impacted Entities.
*
*/
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _efContext.SaveChanges(saveBundle);
}
为了限制访问调用者检索数据的能力,我首先从 access_token 和 user_id 中提取数据,并限制我的所有查询以将其包含在 where 子句中,这使得用户检索另一个用户的数据。
但这不会阻止拥有有效 access_token 的恶意用户在具有增量对象 ID 的强力循环中调用 SaveChanges()。
我离这个远了吗?也许我错过了什么。
感谢您的帮助。
麦克
客户端传递给 SaveChanges
方法的 JObject saveBundle
不透明且难以使用。 Breeze ContextProvider
将其转换为实体映射并将其传递给 BeforeSaveEntities 方法。 BeforeSaveEntities
是您将在 ContextProvider
子类或附加到 ContextProvider 的委托中实现的方法,例如:
var cp = new MyContextProvider();
cp.BeforeSaveEntitiesDelegate += MySaveValidator;
在您的 BeforeSaveEntities
或委托方法中,您将检查当前用户是否可以保存实体。如果您发现不应保存的实体,您可以将其从更改集中删除,或者抛出错误并中止保存:
protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(
Dictionary<Type, List<EntityInfo>> saveMap)
{
var user = GetCurrentUser();
var entityErrors = new List<EFEntityError>();
foreach (Type type in saveMap.Keys)
{
foreach (EntityInfo entityInfo in saveMap[type])
{
if (!UserCanSave(entityInfo, user))
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Forbidden)
{ ReasonPhrase = "Not authorized to make these changes" });
}
}
}
return saveMap;
}
您将需要确定是否应允许用户保存特定实体。这可能基于用户的角色 and/or 一些其他属性,例如Sales 角色的用户只能保存属于他们自己的 SalesRegion 的客户记录。
我正在使用 BreezeJS,但对如何保存数据有疑问。这是我的代码和评论
[Authorize]
/*
* I want to point out the security hole here. Any Authorized user is able to pass to this method
* a saveBundle which will be saved to the DB. This saveBundle can contain anything, for any user,
* or any table.
*
* This cannot be stopped at the client level as this method can be called from Postman, curl, or whatever.
*
* The only way I can see to subvert this attack would be to examine the saveBundle and verify
* no data is being impacted that is not owned or related directly to the calling user.
*
* Brute force could be applied here because SaveResult contains Errors and impacted Entities.
*
*/
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _efContext.SaveChanges(saveBundle);
}
为了限制访问调用者检索数据的能力,我首先从 access_token 和 user_id 中提取数据,并限制我的所有查询以将其包含在 where 子句中,这使得用户检索另一个用户的数据。
但这不会阻止拥有有效 access_token 的恶意用户在具有增量对象 ID 的强力循环中调用 SaveChanges()。
我离这个远了吗?也许我错过了什么。
感谢您的帮助。
麦克
客户端传递给 SaveChanges
方法的 JObject saveBundle
不透明且难以使用。 Breeze ContextProvider
将其转换为实体映射并将其传递给 BeforeSaveEntities 方法。 BeforeSaveEntities
是您将在 ContextProvider
子类或附加到 ContextProvider 的委托中实现的方法,例如:
var cp = new MyContextProvider();
cp.BeforeSaveEntitiesDelegate += MySaveValidator;
在您的 BeforeSaveEntities
或委托方法中,您将检查当前用户是否可以保存实体。如果您发现不应保存的实体,您可以将其从更改集中删除,或者抛出错误并中止保存:
protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(
Dictionary<Type, List<EntityInfo>> saveMap)
{
var user = GetCurrentUser();
var entityErrors = new List<EFEntityError>();
foreach (Type type in saveMap.Keys)
{
foreach (EntityInfo entityInfo in saveMap[type])
{
if (!UserCanSave(entityInfo, user))
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Forbidden)
{ ReasonPhrase = "Not authorized to make these changes" });
}
}
}
return saveMap;
}
您将需要确定是否应允许用户保存特定实体。这可能基于用户的角色 and/or 一些其他属性,例如Sales 角色的用户只能保存属于他们自己的 SalesRegion 的客户记录。