2017-09-26 4 views
0

J'utilise BreezeJS et j'ai une question concernant la façon dont les données sont sauvegardées. Voici mon code et les commentairesBreezeJS SaveChanges() problème de sécurité

[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); 
    } 

Pour limiter l'accès à une capacité d'appelants pour récupérer des données I premier extrait du access_token le user_id et limiter toutes mes questions à inclure dans une clause where, ce qui rend un peu impossible pour un utilisateur pour récupérer les données d'un autre utilisateur. Mais cela n'empêcherait pas un utilisateur non autorisé qui avait un access_token valide d'appeler SaveChanges() dans une boucle de force brute avec des identifiants d'objets incrémentiels.

Suis-je loin de celui-ci? Peut-être qu'il me manque quelque chose.

Merci pour toute aide.

Mike

+0

Vous ne connaissez pas Breeze, mais vous semblez avoir mis en place un contrôle d'accès approprié. C'est également une bonne pratique d'utiliser l'aléatoire cryptographique pour générer vos identifiants d'objet, mais cela est en fait secondaire à la mise en œuvre d'un contrôle d'accès approprié. En termes de SaveChanges(), vous pouvez vouloir limiter le nombre d'opérations de sauvegarde que l'utilisateur peut faire - sinon il peut remplir votre db avec des indésirables. – TheGreatContini

Répondre

2

Le JObject saveBundle que le client passe à la méthode SaveChanges est opaque et difficile à utiliser. Le Breeze ContextProvider convertit cela en une carte d'entités et le passe à la méthode BeforeSaveEntities. BeforeSaveEntities est une méthode que vous mettre en œuvre sur votre ContextProvider sous-classe, ou dans un délégué que vous attachez à la ContextProvider, par exemple:

var cp = new MyContextProvider(); 
    cp.BeforeSaveEntitiesDelegate += MySaveValidator; 

Dans votre BeforeSaveEntities ou méthode déléguée, vous vérifiez si les entités peuvent être sauvegardées par l'utilisateur actuel. Si vous trouvez une entité qui ne doit pas être enregistré, vous pouvez le retirer de l'ensemble de changement, ou lancer une erreur et abandonner l'enregistrement:

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; 
} 

Vous devrez déterminer si l'utilisateur doit être autorisé à enregistrer une entité particulière. Cela pourrait être basé sur le rôle de l'utilisateur et/ou sur un autre attribut, par ex. Les utilisateurs du rôle Ventes ne peuvent enregistrer que les enregistrements Client appartenant à leur propre SalesRegion.

+0

Merci beaucoup! C'est exactement ce que j'avais besoin de savoir. J'apprécie l'aide! – Mike