Comprensione della falsificazione delle richieste tra siti in .NET

Puoi solo produrre applicazioni web sicure tenendo conto della sicurezza, sin dall'inizio. Ciò richiede di pensare ai potenziali modi in cui qualcuno potrebbe attaccare il tuo sito mentre crei ogni pagina, modulo e azione. Richiede anche la comprensione dei tipi più comuni di problemi di sicurezza e di come affrontarli.

Il tipo più comune di falla di sicurezza in una pagina Web consente a un utente malintenzionato di eseguire comandi per conto di un utente, ma sconosciuto all'utente. L'attacco di contraffazione di richiesta cross-site sfrutta la fiducia che un sito Web ha già stabilito con il browser web di un utente.

In questo tutorial, discuteremo su cosa sia un attacco contraffatto di una richiesta cross-site e su come viene eseguito. Quindi costruiremo una semplice applicazione ASP.NET MVC vulnerabile a questo attacco e correggeremo l'applicazione per evitare che si ripeta.


Che cosa è un falso per richieste di cross-site?

L'attacco di contraffazione richiesta cross-site presuppone innanzitutto che la vittima si sia già autenticata su un sito Web di destinazione, ad esempio un sito bancario, Paypal o altro sito da attaccare. Questa autenticazione deve essere archiviata in modo tale che se l'utente lascia il sito e ritorni, vengono comunque visti come registrati dal sito Web di destinazione. L'utente malintenzionato deve quindi convincere la vittima ad accedere a una pagina oa un link che eseguirà una richiesta o pubblicherà sul sito web di destinazione. Se l'attacco funziona, il sito Web di destinazione vedrà una richiesta proveniente dalla vittima ed eseguirà la richiesta come tale utente. Questo, in effetti, consente all'aggressore di eseguire qualsiasi azione desiderata sul sito web di destinazione come vittima. Il risultato potenziale potrebbe trasferire denaro, reimpostare una password o cambiare un indirizzo e-mail sul sito web di destinazione.

Come funziona l'attacco

L'atto di convincere la vittima a utilizzare un link non richiede che facciano clic su un link. Un semplice collegamento di immagine potrebbe essere sufficiente:

Includere un link come questo su un post del forum apparentemente innocuo, un commento sul blog o un sito di social media potrebbe attirare l'attenzione di un utente. Esempi più complessi utilizzano JavaScript per creare una richiesta di post HTTP completa e inviarla al sito Web di destinazione.


Creazione di un'applicazione Web vulnerabile in ASP.NET MVC

Creiamo una semplice applicazione ASP.NET MVC e lasciala vulnerabile a questo attacco. Userò Visual Studio 2012 per questi esempi, ma funzionerà anche in Visual Studio 2010 o Visual Web Developer 2010 funzionerà se hai installato il supporto per MVC 4 che può essere scaricato e installato da Microsoft.


Inizia creando un nuovo progetto e scegli di utilizzare il Progetto Internet modello. O View Engine funzionerà, ma qui userò il motore di visualizzazione ASPX.

Aggiungeremo un campo alla tabella UserProfile per memorizzare un indirizzo email. Sotto Server Explorer espandere Connessioni dati. Dovresti vedere il Connessione predefinita creato con le informazioni per gli accessi e le iscrizioni. Fare clic destro sul Profilo utente tabella e fare clic Open Table Definition. Sulla riga vuota sotto Nome utente tabella, aggiungeremo una nuova colonna per l'email. Assegna un nome alla colonna indirizzo email, dagli il tipo nvarchar (MAX), e controllare il Consenti i null opzione. Ora fai clic Aggiornare per salvare la nuova versione del tavolo.

Questo ci fornisce un modello base di un'applicazione web, con supporto per l'accesso, molto simile a quello che molti scrittori avrebbero iniziato a provare a creare un'applicazione. Se esegui l'app ora, la vedrai visualizzata ed è funzionale. stampa F5 o usare DEBUG -> Avvia il debugging dal menu per visualizzare il sito Web.


Creiamo un account di prova che possiamo usare per questo esempio. Clicca sul Registrare collega e crea un account con qualsiasi nome utente e password che desideri. Qui ho intenzione di utilizzare un account chiamato testuser. Dopo la creazione, vedrai che ora sono loggato come testuser. Dopo averlo fatto, esci e aggiungiamo una pagina a questa applicazione per consentire all'utente di cambiare la propria email.


Prima di creare quella pagina per modificare l'indirizzo email, dobbiamo prima apportare una modifica all'applicazione in modo che il codice sia a conoscenza della nuova colonna che abbiamo appena aggiunto. Apri il AccountModels.cs file sotto il Modelli cartella e aggiornare il Profilo utente classe per abbinare il seguente. Questo dice alla classe sulla nostra nuova colonna in cui memorizzeremo l'indirizzo email per l'account.

[Tabella ("UserProfile")] classe pubblica UserProfile [Chiave] [DatabaseGeneratedAttribute (DatabaseGeneratedOption.Identity)] public int UserId get; impostato;  public string UserName get; impostato;  public string EmailAddress get; impostato; 

Apri il AccountController.cs file. Dopo il RemoveExternalLogins funzione aggiungere il seguente codice per creare una nuova azione. Ciò otterrà l'e-mail corrente per l'utente che ha effettuato l'accesso e la passerà alla vista per l'azione.

public ActionResult ChangeEmail () // Ottieni la stringa utente login registrata = WebSecurity.CurrentUserName; string currentEmail; using (UsersContext db = new UsersContext ()) UserProfile user = db.UserProfiles.FirstOrDefault (u => u.UserName.ToLower () == username); currentEmail = user.EmailAddress;  return View (currentEmail); 

Abbiamo anche bisogno di aggiungere la vista corrispondente per questa azione. Questo dovrebbe essere un file chiamato ChangeEmail.aspx sotto il Vista \ Account cartella:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage"%>  Cambia indirizzo email   

Cambia indirizzo email

Indirizzo email attuale: <%= Model ?? "Nessuna email corrente"%>

<% using(Html.BeginForm()) %> <% %>

Questo ci dà una nuova pagina che possiamo usare per cambiare l'indirizzo email per l'utente attualmente connesso.


Se eseguiamo questa pagina e andiamo al / Account / ChangeEmail azione, ora vediamo che al momento non abbiamo un'e-mail. Ma abbiamo una casella di testo e un pulsante che possiamo usare per correggerlo. Prima però, dobbiamo creare l'azione che verrà eseguita, quando il modulo in questa pagina viene inviato.

[HttpPost] public ActionResult ChangeEmail (modello ChangeEmailModel) string username = WebSecurity.CurrentUserName; using (UsersContext db = new UsersContext ()) UserProfile user = db.UserProfiles.FirstOrDefault (u => u.UserName.ToLower () == username); user.EmailAddress = model.NewEmail; db.SaveChanges ();  // E per verificare la modifica, ottenere l'e-mail dal profilo ChangeEmailModel newModel = new ChangeEmailModel (); using (UsersContext db = new UsersContext ()) UserProfile user = db.UserProfiles.FirstOrDefault (u => u.UserName.ToLower () == username); newModel.CurrentEmail = user.EmailAddress;  return View (newModel); 

Dopo aver apportato questa modifica, eseguire il sito Web e di nuovo andare al / Account / ChangeEmail azione che abbiamo appena creato. Ora puoi inserire un nuovo indirizzo email e fare clic su Cambia email pulsante e vedere che l'indirizzo email verrà aggiornato.


Attaccare il sito

Come scritto, la nostra applicazione è vulnerabile a un attacco di contraffazione di una richiesta incrociata. Aggiungiamo una pagina web per vedere questo attacco in azione. Stiamo andando ad aggiungere una pagina all'interno del sito web che cambierà l'e-mail con un valore diverso. Nel HomeController.cs file aggiungeremo una nuova azione chiamata AttackForm.

public ActionResult AttackForm () return View (); 

Aggiungeremo anche una vista per questo nome AttackForm.aspx sotto il / Vista / Casa cartella. Dovrebbe sembrare come questo:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage"%>  Forma di attacco   

Forma di attacco

Questa pagina ha un modulo nascosto, per attaccarti, cambiando la tua email:

La nostra pagina annuncia utilmente il suo cattivo intento, che ovviamente non sarebbe un vero attacco. Questa pagina contiene un modulo nascosto che non sarà visibile all'utente. Utilizza quindi Javascript per inviare automaticamente questo modulo quando la pagina viene caricata.


Se si esegue nuovamente il sito e andare al / Home / AttackForm pagina, vedrai che si carica bene, ma senza alcuna indicazione esteriore che qualcosa è successo. Se ora vai al / Account / ChangeEmail pagina però, vedrai che la tua email è stata cambiata [email protected]. Qui, ovviamente, stiamo intenzionalmente rendendo ovvio, ma in un attacco reale, potresti non notare che la tua email è stata modificata.


Attenuazione dei falsi falsi delle richieste tra siti

Esistono due modi principali per mitigare questo tipo di attacco. Innanzitutto, possiamo controllare il rinvio da cui arriva la richiesta web. Questo dovrebbe dire all'applicazione quando l'invio di un modulo non proviene dal nostro server. Questo ha due problemi però. Molti server proxy rimuovono queste informazioni di riferimento, intenzionalmente per proteggere la privacy o come effetto collaterale, il che significa che una richiesta legittima non può contenere queste informazioni. È anche possibile che un attaccante simuli il referral, sebbene aumenti la complessità dell'attacco.

Il metodo più efficace è richiedere che esista un token specifico dell'utente per ogni invio di modulo. Il valore di questo token dovrebbe essere generato casualmente ogni volta che viene creato il modulo e il modulo viene accettato solo se il token è incluso. Se il token è mancante o è incluso un valore diverso, non è consentita l'invio del modulo. Questo valore può essere memorizzato nello stato di sessione dell'utente o in un cookie per consentirci di verificare il valore quando il modulo viene inviato.

ASP.NET semplifica questo processo, poiché il supporto CSRF è integrato. Per utilizzarlo, è necessario apportare due modifiche al nostro sito Web.


Risolvere il problema

Innanzitutto, è necessario aggiungere il token univoco al modulo per modificare l'e-mail dell'utente quando viene visualizzato. Aggiorna il modulo in ChangeEmail.aspx guarda sotto / Account / ChangeForm:

<% using(Html.BeginForm())  %> <%: Html.AntiForgeryToken() %> <%: Html.TextBoxFor(t=>t.NewEmail)%>  <%  %>

Questa nuova linea: <%: Html.AntiForgeryToken() %> indica a ASP.NET di generare un token e posizionarlo come campo nascosto nel modulo. Inoltre, il framework gestisce la sua collocazione in un'altra posizione in cui l'applicazione può accedervi in ​​seguito per verificarlo.

Se cariciamo la pagina adesso e guardiamo all'origine, vedremo questa nuova riga, nel modulo, visualizzata nel browser. Questo è il nostro token:

Dobbiamo anche apportare una modifica alla nostra azione per far sapere che abbiamo aggiunto questo token e che deve verificare il token prima di accettare il modulo inviato.

Anche in questo caso è semplice in ASP.NET MVC. All'inizio dell'azione che abbiamo creato per gestire il modulo pubblicato, quello con il [HttpPost] attributo aggiunto, aggiungeremo un altro attributo chiamato [ValidateAntiForgeryToken]. Questo fa sì che l'inizio della nostra azione ora assomigli al seguente:

 [HttpPost] [ValidateAntiForgeryToken] public ActionResult ChangeEmail (modello ChangeEmailModel) string username = WebSecurity.CurrentUserName; * resto della funzione omessa *

Proviamo questo. Prima vai al / Account / ChangeEmail pagina e ripristinare l'e-mail per il tuo account a un valore noto. Quindi possiamo tornare al / Home / AttackForm pagina e ancora il codice di attacco tenta di cambiare la nostra e-mail. Se si ritorna al / Account / ChangeEmail pagina di nuovo, questa volta vedrai che l'email inserita in precedenza è ancora al sicuro e intatta. Le modifiche apportate alla nostra forma e azione hanno protetto questa pagina dall'attacco.

Se dovessi esaminare direttamente il modulo di attacco (facilmente fatto rimuovendo il