Quando in ASP.NET MVC realizziamo una action per gestire il post di una form, ad esempio per modificare una entità Person su database, possiamo scrivere un metodo il cui argomento è il vero e proprio model, che il framework provvede a popolare in base ai dati pervenuti dal browser.
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(Person person) { // qui salvataggio su DB return this.RedirectToAction("Index"); }
Si tratta di una funzionalità molto comoda, perché ci consente di ragionare a oggetti e di lavorare quindi ad un alto livello di astrazione: ciò che accade dietro alle quinte è che ASP.NET MVC associa i dati ricevuti dal post alle relativa proprietà basandosi sul nome del campo nella form. Eppure un'implementazione della action di Edit come quella precedente nasconde in realtà una pericolosa falla di sicurezza.
Immaginiamo infatti che Person abbia una proprietà Role che non vogliamo rendere accessibile all'utente, tanto da farci decidere, ad esempio, di non includere alcun editor per questo dato nelle view di creazione o di modifica. In queste condizioni, però, un hacker potrebbe modificare il contenuto del form postato (tampering dei dati), includendo artificiosamente un campo di nome Role; ASP.NET MVC avrebbe tutte le ragioni per ritenere perfettamente valido anche questo dato, aggiornando di fatto la relativa proprietà dell'oggetto sul server!
Si tratta di problema potenzialmente serio, che però possiamo evitare in vari modi. Se utilizziamo i metodi UpdateModel o TryUpdateModel per aggiornare il model, è possibile specificare una whitelist con l'elenco delle sole proprietà che si vogliono valorizzare:
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(Person person) { var p = new Person(); // non aggiorniamo Role, anche se inviato in POST this.UpdateModel(p, new string[] { "FirstName", "LastName"}); // qui salvataggio su DB return this.RedirectToAction("Index"); }
Il medesimo elenco può essere utilizzato per gestire la creazione, tramite l'attributo Bind e la proprietà Include; in questo modo le proprietà del model non presenti in whitelist non verranno valorizzate:
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Create( [Bind(Include = "FirstName, LastName")]Person person) { // qui salvataggio su DB return this.RedirectToAction("Index"); }
Entrambi questi metodi prevedono, eventualmente, anche la possibilità di fornire una blacklist, ossia un elenco di proprietà il cui aggiornamento è vietato. Attenzione al fatto che l'attributo Bind utilizzato come nell'esempio precedente, viene ignorato da UpdateModel/TryUpdateModel. Questo limite non sussiste nel caso in cui sia applicato direttamente sul model:
[Bind(Include = "FirstName, LastName")] public class Person { public string FirstName { get; set; } public string LastName { get; set; } public string Role { get; set; } }
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Migrare una service connection a workload identity federation in Azure DevOps
Garantire la provenienza e l'integrità degli artefatti prodotti su GitHub
Usare un KeyedService di default in ASP.NET Core 8
Generare HTML a runtime a partire da un componente Razor in ASP.NET Core
Escludere alcuni file da GitHub Secret Scanning
Evitare (o ridurre) il repo-jacking sulle GitHub Actions