Come configurare il ASP.NET Applicazioni Web e API per richiedere HTTPS

Per qualsiasi applicazione ospitata sul Web, è essenziale che la sicurezza sia integrata fin dall’inizio.
Abilitare la tua applicazione Web per servire traffico sicuro su HTTPS e applicare questa politica è una delle prime cose che dovresti implementare e questo è altrettanto importante per le app Web quanto per le API.

Con servizi consolidati come Let’s Encrypt che forniscono certificati TLS gratuiti, non esiste più alcuna ragione tecnica o finanziaria convincente per non utilizzare HTTPS per le applicazioni web.
In questo articolo, dimostro come configurare correttamente le applicazioni Web in modo tale che richiedano HTTPS e copro esempi per entrambi ASP.NET e ASP.NET Progetti di base.

Reindirizzamento HTTPS

Per assicurarti che il tuo sito sia protetto correttamente, dopo aver ottenuto e installato un nuovo certificato SSL/TLS, ti consigliamo di assicurarti che HTTPS venga sempre utilizzato.

Per le applicazioni Web, ad esempio le applicazioni MVC, è possibile configurare il traffico da reindirizzare da HTTP a HTTPS.

Per una serie di motivi, è comunque consigliabile mantenere aperta la porta HTTP predefinita (porta 80) e reindirizzare gli utenti alla porta HTTPS predefinita (porta 443) per le applicazioni Web a cui si accede tramite un browser.

Questo fa parte dei consigli ufficiali sulle migliori pratiche all’interno della documentazione Let’s Encrypt. Top ricercatore di sicurezza, Scott Helm, ha anche un ottimo articolo che spiega perché la chiusura della porta 80 è un male per la sicurezza nel contesto delle applicazioni web.

Nelle sezioni seguenti dimostro come configurare il reindirizzamento HTTPS per ASP.NET e ASP.NET Applicazioni web di base.

ASP.NET applicazioni web

Il ASP.NET MVC framework ha convenientemente una classe RequireHttpsAttribute integrata di cui possiamo usufruire.

Quando applicato, l’attributo causerà l’invio di una risposta di reindirizzamento al client se una richiesta è stata inviata su HTTP anziché HTTPS.

L’attributo può essere applicato su base per controller o per azione. Tuttavia, consiglio vivamente di applicare l’attributo globalmente per applicare il reindirizzamento HTTPS sull’intero sito, come mostrato di seguito.

 filtri.Aggiungi (nuovo RequireHttpsAttribute());

La riga di codice di cui sopra appare in genere all’interno di un metodo statico RegisterGlobalFilters in una classe FilterConfig, come per lo snippet di codice di seguito.

/// <sommario> / / / Registra i filtri globali./// < / summary> / / / <param name= "filters" > La raccolta di filtri da registrare</param> public static void RegisterGlobalFilters (GlobalFilterCollection filters){ filters.Aggiungi (nuovo HandleErrorAttribute ()); filtri.Aggiungi (nuovo RequireHttpsAttribute ()); filtri.Aggiungi (nuovo AuthorizeAttribute());}

In un ASP.NET applicazione, il metodo RegisterGlobalFilters viene solitamente chiamato all’avvio dal metodo Application_Start all’interno del Globale.file asax.

Prima di passare, è importante notare che i filtri globali si applicheranno solo alle richieste HTTP che vengono passate ai controller. Pertanto è ancora possibile per un client accedere a file statici come fogli di stile e file di script su HTTP non sicuro.

Dovresti fare attenzione a utilizzare collegamenti relativi a qualsiasi risorsa statica a cui stai facendo riferimento dal tuo HTML o utilizzare URL assoluti con lo schema HTTPS per assicurarti che tutto il contenuto venga servito in modo sicuro.

Riscrivi le regole

Per rendere la tua applicazione web ancora più sicura puoi configurare il reindirizzamento a livello di proxy inverso, ad esempio come parte della tua configurazione IIS. Ciò assicurerà che tutte le richieste in arrivo vengano reindirizzate in modo appropriato.

Nel caso di IIS, è possibile implementarlo tramite una regola di riscrittura aggiungendo quanto segue al Web.file di configurazione.

< riscrivere >< regole >< rule name="HTTP a HTTPS redirect" stopProcessing="true"> < match url="(.*)" /> <condizioni> <aggiungi input="{HTTPS}" pattern="off" ignoreCase="true" /> <condizioni> <azione type="Redirect" url="https://{HTTP_HOST}/{R:1}"redirectType="Permanente" /> </regola> <regole></riscrittura>

IIS rispetto al di sopra della regola di riscrittura durante la gestione del traffico in entrata, reindirizzando insicuro il traffico HTTPS prima che raggiunga il codice dell’applicazione.

Come per molti aspetti della sicurezza, credo che sia meglio avere più livelli di sicurezza in atto. Se qualcosa fallisce o viene configurato male a un livello, avere un fallback è sempre una buona cosa.

. NET Core

. NET Core ha anche una classe RequireHttpsAttribute integrata che può essere applicata su base per controller/azione o può essere registrata a livello globale.

La registrazione globale può essere impostata all’interno del metodo ConfigureServices della classe Startup, come illustrato di seguito.

/// <riepilogo> / / / Questo metodo viene chiamato dal runtime./// Utilizzare questo metodo per aggiungere servizi al contenitore./// < / riepilogo>/ / / <param name="servizi">La raccolta di servizi contenitore< / param> public void ConfigureServices(IServiceCollection services){ services.AddControllersWithViews (opzioni => opzioni.Filtro.Aggiungi (nuovo RequireHttpsAttribute()));}

Il codice di cui sopra fa la stessa cosa fondamentalmente come in un tradizionale ASP.NET progetto.

Tuttavia, in. NET Core, possiamo fare meglio di questo.

. NET Core ha anche middleware di reindirizzamento HTTPS integrato, che può essere configurato con una riga di codice, come mostrato di seguito.

app.UseHttpsRedirection();

La riga di codice sopra deve essere aggiunta al metodo Configure della classe Startup. La maggior parte dello standard ASP.NET Per MVC, configurare automaticamente il middleware di reindirizzamento HTTPS.

Di seguito è riportato un esempio dei contenuti tipici del metodo Configure come riferimento.

/// <riepilogo> / / / Questo metodo viene chiamato dal runtime./// Utilizzare questo metodo per configurare la pipeline di richiesta HTTP./// </riepilogo>/// <param name="app">Il generatore di applicazione oggetto utilizzato per configurare la pipeline di richiesta</param>/// <param name="env">L'ambiente di hosting web l'applicazione è in esecuzione in</param>public void Configurare(IApplicationBuilder app, IWebHostEnvironment env){ if (env.IsDevelopment ()) {app.UseDeveloperExceptionPage ();} else {app.UseExceptionHandler ("/Home / Errore"); app.UseHsts ();} app.UseHttpsRedirection (); app.UseStaticFiles (); app.UseRouting (); app.UseAuthorization (); app.UseEndpoints (endpoints = > {endpoints.MapControllerRoute( nome: "default", pattern: "{controller = Home} / {action = Index} / {id?}"); });}

Quindi, perché il middleware di reindirizzamento HTTPS è migliore del filtro RequireHttpsAttribute?

Bene, grazie al modo in cui ASP.NET Le applicazioni Web di base sono ospitate, i reindirizzamenti HTTPS del middleware vengono applicati a un livello superiore e quindi le richieste di file statici come fogli di stile e script verranno reindirizzati oltre alle richieste associate al controller.

HSTS

Un altro utile pezzo di ASP.NET Core middleware è il middleware HSTS ed è configurato nell’esempio sopra tramite la seguente riga di codice.

app.UseHsts();

Si noti che, come con molti dei componenti middleware incorporati, molti aspetti più avanzati di ASP.NET Il middleware di base può essere configurato all’interno del metodo ConfigureServices della classe di avvio.

Che cos’è HSTS e perché dovremmo usarlo?

Il problema con il reindirizzamento HTTPS da solo è con la prima richiesta non sicura che arriva nell’applicazione da un client.

Se la prima richiesta HTTP in arrivo viene intercettata da un ‘man in the middle’ l’integrità della richiesta andrà persa. Ad esempio, il client potrebbe essere reindirizzato da qualche altra parte senza che se ne accorga, ad esempio, a una falsa pagina di accesso.

HSTS sta per HTTP Strict Transport Security e aiuta a risolvere il problema sopra descritto informando il browser che un’applicazione Web dovrebbe essere accessibile solo tramite HTTPS.

Lo fa restituendo un’intestazione Strict-Transport-Security nella risposta in modo che le richieste successive utilizzino HTTPS senza ulteriori reindirizzamenti. Il browser memorizza nella cache questa istruzione per garantire che ulteriori visite al sito saranno su HTTPS senza ulteriori reindirizzamenti.

La prima richiesta

Sì, tutto sembra fantastico, ma per quanto riguarda la prima richiesta?

Abbiamo risolto la maggior parte del problema, ma non abbiamo ancora affrontato la prima richiesta ricevuta da un cliente che non ha mai visitato il nostro sito prima.

Per essere super-sicuro e chiudere il ciclo su questo, possiamo registrare il nostro sito per essere ‘precaricato’. I browser mantengono un elenco di siti che si trovano in un elenco di “precarico” e se il tuo sito è in questo elenco, non riceverai mai una richiesta non sicura da un client poiché il browser onorerà lo stato di precarico.

Puoi registrare il tuo sito per essere precaricato andando sul sito web HSTS Precaricato e inviando una richiesta per averlo precaricato.

Di seguito è riportato un esempio di intestazione HSTS con la direttiva precarico specificata.

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload

Si noti che è estremamente importante testare accuratamente il sito prima di abilitare HSTS in un ambiente di produzione per assicurarsi che funzioni correttamente su HTTPS. Questo è particolarmente importante se si sceglie di precaricare il tuo sito come questo non può essere facilmente annullata e potrebbe richiedere mesi per ottenere il vostro sito rimosso dalla lista di precaricamento.

Consiglio vivamente di configurare HSTS per le tue applicazioni web. Se si sceglie o meno di avere il vostro sito precaricato dipenderà dai vostri requisiti di sicurezza specifici.

Regole in uscita

Come indicato nella sezione Rewrite rules di questo articolo, è anche possibile abilitare HSTS a livello di proxy inverso.

Di seguito è riportato un esempio di come configurare questo all’interno di un Web.file di configurazione se stai ospitando la tua applicazione in IIS.

<riscrivi ><outboundRules ><rule name="Add Strict-Transport-Security when HTTPS" enabled="true"> <match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" /> <condizioni> <aggiungi input="{HTTPS}" pattern="on" ignoreCase="true" /> <condizioni> <azione type="Riscrivere" value="max-age=31536000" /> </regola> </outboundRules></riscrittura>

Ora il HSTS intestazione verrà impostata per tutte HTTPS traffico sul tuo sito.

Si noti che l’approccio di cui sopra funzionerà sia per i tradizionali ASP.NET e ASP.NET Applicazioni principali. Hai solo bisogno di aggiungere un Web.file di configurazione al progetto e assicurarsi che la proprietà’ Copia nella directory di output ‘sia impostata su’Copia se più recente’.

API

Le API differiscono un po ‘ dalle normali applicazioni Web a cui si accede dagli umani, sia nella loro progettazione, nei casi d’uso previsti e nelle considerazioni sulla sicurezza.

Tratteremo le best practice per richiedere HTTPS per le API nelle sezioni seguenti.

Richiedere HTTPS?

Tradizionale ASP.NET I progetti API Web non hanno accesso a un attributo incorporato per richiedere HTTPS.

Tuttavia, questo non ci impedisce di creare il nostro.

Di seguito è riportato un esempio di come farlo.

/// <summary>/// Called when a process requests authorization./// </summary>/// <param name="actionContext">The action context</param>public override void OnAuthorization(HttpActionContext actionContext){ HttpRequestMessage request = actionContext.Request; if (request.RequestUri.Scheme != Uri.UriSchemeHttps) { if (request.Method.Equals(HttpMethod.Get)) { actionContext.Response = request.CreateResponse(HttpStatusCode.Found, "SSL is required"); // Provide the correct URL to the user via the Location header. var uriBuilder = nuovo UriBuilder(richiesta.RequestUri) {Scheme = Uri.UriSchemeHttps, Port = 443}; actionContext.Risposta.Intestazione.Posizione = uriBuilder.Uri;} else actionContext.Risposta = richiesta.CreateResponse (HttpStatusCode.NotFound, "SSL è richiesto"); }}

Nell’esempio precedente, ho creato una classe chiamata RequireHttpsAttribute che deriva dalla classe AuthorizationFilterAttribute e sto sovrascrivendo il metodo virtuale OnAuthorization.

Per le richieste GET, il metodo precedente informa i client dell’URL corretto utilizzando lo schema HTTPS restituendolo nell’intestazione della posizione. Per tutte le altre richieste, viene semplicemente restituito il messaggio ‘SSL is required’.

Sebbene ciò abbia senso quando si chiama un’API da un browser, uno dei problemi con il codice sopra è che sta restituendo un codice di stato di reindirizzamento che la maggior parte dei client API non capirà.

A seconda del punto di vista, il codice di cui sopra potrebbe invece essere modificato per impostare il codice di stato HTTP su qualcos’altro, come una richiesta errata, piuttosto che cercare di reindirizzare il client.

Possiamo implementare qualcosa di simile in .NET Core creando la nostra classe come ApiRequireHttpsAttribute che deriva dalla classe RequireHttpsAttribute incorporata. Possiamo quindi sovrascrivere il metodo virtual HandleNonHttpsRequest e impostare il codice di risposta di conseguenza, come da codice di esempio riportato di seguito.

/// <riepilogo>/// Chiamato se la richiesta non viene ricevuta tramite HTTPS.///</ summary >///<param name="filterContext">Il contesto del filtro< / param >override protetto HandleNonHttpsRequest vuoto(AuthorizationFilterContext filterContext){ filterContext.Risultato = nuovo StatusCodeResult(400);} 

Il codice precedente imposta il codice di stato HTTP per la risposta alla richiesta errata (400). Potrebbe essere modificato per includere un messaggio nella risposta o qualsiasi altra logica personalizzata richiesta.

Non ascolto?

Ok, quindi abbiamo esaminato come forzare i client API a utilizzare HTTPS ogni volta che tentano di utilizzare HTTP.

Tuttavia, questa è l’opzione migliore?

La best practice impone che dovremmo avere più livelli di sicurezza, ma impone anche che dovremmo implementare la sicurezza il prima possibile.

In realtà, la cosa più sicura che possiamo fare nel contesto delle API è impedire loro di ascoltare su una porta non sicura, in primo luogo. Questo consiglio è rispecchiato nei documenti di Microsoft per ASP.NET Nucleo.

Naturalmente, non possiamo impedire a un client API di cercare di raggiungere la nostra API in modo insicuro. Tuttavia, in questo caso, è colpa dell’integratore di API e non qualcosa per cui possiamo fare qualcosa di significativo per prevenire.

Sommario

In questo articolo, ho coperto come applicare HTTPS attraverso le applicazioni web e le API e ho discusso le soluzioni più appropriate e sicure per entrambi gli scenari.

La cosa fondamentale da rimuovere è che è necessario implementare più livelli di sicurezza per la propria applicazione e, ove possibile, applicare la sicurezza il prima possibile.

Utilizzare HSTS e sfruttare la potenza della configurazione reverse proxy per gestire le richieste in modo sicuro.

Leave a Reply