2009-10-01 8 views
5

Ich habe eine ASP.NET MVC-Anwendung, die Kalender-ähnlich ist. Wie im NerdDinner Beispiel, aktualisiere ich die Ergebnisse meiner Bearbeitungsseite mit UpdateMethod()ASP.NET MVC UpdateModel anfällig für Hacker?

In meiner App sind bestimmte Ereignisse vollständig anpassbar und bestimmte sind nur teilweise anpassbar. Auch wenn das Editierformular zum Bearbeiten der teilweise anpassbaren Ereignisse nur diese Felder zur Verfügung stellt, könnte jemand natürlich sein eigenes Formular mit den fehlenden Daten erstellen und auf meiner Site veröffentlichen. Wenn sie dies tun, was soll jemanden davon abhalten, alle Felder zu ändern? Schlimmer noch, was ist, wenn sie versuchen, die ID (Primärschlüssel) zu ändern?

Es fühlt sich an wie UpdateModel() ist anfällig für sehr grundlegende Hacking. Sind meine Ängste berechtigt oder fehlt etwas?

// POST: /MyEvents/Edit/2 
[AcceptVerbs(HttpVerbs.Post), Authorize] 
public ActionResult Edit(int id, FormCollection formValues) 
{ 
    MyEvent myevent = eventRepository.GetMyEvent(id); 

    try 
    { 
     UpdateModel(myevent); 
     eventRepository.Save(); 
     return RedirectToAction("Details", new { id = myevent.MyEventId }); 
    } 
    catch 
    { 
     ModelState.AddRuleViolations(myevent.GetRuleViolations()); 
     return View(new MyEventFormViewModel(myevent)); 
    } 
} 
+0

easy/safe mode = Erstellen Sie Formular (in) -Modelle, und ordnen Sie diese dann Ihren Entitäten über den Automapper zu. – mxmissile

Antwort

9

Sie vermissen den Abschnitt über "Model Binding Security". Sie sollten immer eine Whitelist mit Eigenschaften einschließen, die von Ihren Benutzereingabemethoden aktualisiert werden können.

Zum Beispiel von NerdDinner:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create([Bind(Include="Title, Address")] Dinner dinner) 
{ 

} 

oder wenn Sie Update anrufen, können Sie ein String-Array von erlaubten Eigenschaften erstellen, und tun

UpdateModel(myObject, allowedProperties); 

Sie können die Klassen sperren selbst, so dass nur bestimmte Eigenschaften auch aktualisierbar sind.

[Bind(Include="MyProp1,MyProp2,MyProp3")] 
public partial class MyEntity { } 
+0

Großartig, bis Sie 20 oder 30 Elemente auf einem Dateneingabe-Bildschirm haben, dann wird es ein Schmerz =) –

+2

Sie können auch eine Blacklist verwenden :) – womp

7

Ihre Ängste sind richtig. Dies wird als Massenzuweisung bezeichnet. Sie können Ihren Code schützen, indem Sie Ihre Klasse mit BindAttribute markieren und Exclude/Include Eigenschaften festlegen.

1

Es gibt Überladungen von UpdateModel, die ein Array von Strings zur Benennung der zu aktualisierenden Eigenschaften enthalten. Diese Überladungen werden nur die benannten Eigenschaften aktualisieren.

Es kann andere einfachere/deklarative Möglichkeiten geben, dies zu erreichen, ich bin kein Experte für MVC-Datenbindung.

1

Sie können Felder in Ihrem Modell markieren, die von der Aktualisierung ignoriert werden sollen, oder eine Liste der enthaltenen/ausgeschlossenen Felder mit einer der anderen Überladungen UpdateModel übergeben.

4

Es ist durchaus möglich für jemanden unternehmungslustig/böswillig, die Felder auf eine der Eigenschaften in Ihrem Modell abzubilden. Es gibt ein paar Möglichkeiten, um dies zu umgehen

Am einfachsten ist es, die Exclude/include Eigenschaften Überladungen von UpdateModel zu verwenden, wie bereits erwähnt wurde. Der Nachteil davon ist, dass die Methode nur ein String-Array akzeptiert, was manchmal bedeuten kann, dass Ihr Code nicht mehr synchron ist, wenn Sie umbenennen. Eine andere Möglichkeit besteht darin, ein einfaches DTO zu verwenden, das die gebundenen Felder enthält, Sie können dann das DTO nehmen und tun, was Sie wollen mit Ihrem Ereignisobjekt, das fügt offensichtlich eine andere Klasse hinzu und ist viel manueller, gibt Ihnen aber viel mehr Steuer

public ActionResult(int id, EditForm form) { 
    MyEvent event = _eventRepository.GetMyEvent(id); 
    event.Name = form.Name; //etc; 
    if (User.IsInRole("Organiser")) { 
     event.Date = form.Date; 
    } 
    return ... 
} 

eine weitere Möglichkeit, über ein Kundenmodell Mappe für Ihre MyEvent Klasse sein könnte, die nur Ihr gewünschtes Feld aber wahrscheinlich übertrieben binden.