2017-09-26 7 views
0

Ich benutze BreezeJS und habe eine Frage, wie Daten gespeichert werden. Hier ist mein Code und KommentareBreezeJS SaveChanges() Sicherheitsproblem

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

Um den Zugriff auf eine Anrufer Fähigkeit zu begrenzen, um Daten abzurufen ich zum ersten Mal von den access_token des user_id extrahieren und all meine Fragen zu beschränken, umfassen diese in einer where-Klausel, so dass es etwas unmöglich für einen Benutzer um andere Benutzerdaten abzurufen.

Aber das würde einen unberechtigten Benutzer nicht stoppen, der ein gültiges access_token vom Aufrufen von SaveChanges() in einer Brute-Force-Schleife mit inkrementellen Objekt-IDs hatte.

Bin ich auf diesem einen Weg? Vielleicht vermisse ich etwas.

Danke für jede Hilfe.

Mike

+0

Nicht vertraut mit Brise, aber Sie klingen, als ob Sie richtige Zugangskontrolle implementieren. Es ist auch eine gute Methode kryptografische Zufälligkeit beim Generieren von Objekt-IDs zu verwenden, aber das ist sekundär, um eine korrekte Zugriffssteuerung zu implementieren. In Bezug auf SaveChanges() möchten Sie möglicherweise die Anzahl der Speichervorgänge einschränken, die der Benutzer ausführen kann - andernfalls kann er Ihre Datenbank mit Junk füllen. – TheGreatContini

Antwort

2

Die JObject saveBundle, die der Client geht auf den SaveChanges Verfahren opaken und hart ist, zu verwenden. Das Breeze ContextProvider konvertiert das in eine Zuordnung von Entitäten und übergibt es an die BeforeSaveEntities-Methode. BeforeSaveEntities ist eine Methode, die auf dem ContextProvider Unterklasse implementieren würde, oder in einem Delegierten, die Sie dem context anhängen, zum Beispiel:

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

In Ihrem BeforeSaveEntities oder delegierte Methode, würden Sie überprüfen, um zu sehen, ob die Entitäten gespeichert werden können vom aktuellen Benutzer. Wenn Sie ein Unternehmen finden, die nicht gespeichert werden sollen, können Sie entweder aus dem Änderungssatz entfernen, oder einen Fehler aus und brechen die sparen:

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

müssen Sie, um zu bestimmen, ob der Benutzer erlaubt sein soll, zu Speichere eine bestimmte Entität. Dies könnte auf der Rolle des Benutzers und/oder eines anderen Attributs basieren, z. Benutzer in der Sales-Rolle können nur Client-Datensätze speichern, die zu ihrer eigenen SalesRegion gehören.

+0

Vielen Dank! Genau das musste ich wissen. Ich schätze die Hilfe! – Mike