BreezeJS SaveChanges() проблема безопасности
Я использую 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, от вызова SaveChanges() в цикле грубой силы с инкрементными идентификаторами объектов.
Я в этом отстранен? Может быть, я что-то упустил.
Спасибо за любую помощь.
Майк
1 ответ
JObject saveBundle
что клиент переходит к SaveChanges
метод непрозрачен и сложен в использовании. Бриз 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;
}
Вам нужно будет определить, разрешено ли пользователю сохранять конкретную сущность. Это может быть основано на роли пользователя и / или некотором другом атрибуте, например, пользователи в роли Sales могут сохранять только те записи клиента, которые принадлежат их собственному SalesRegion.