Indice dei contenuti
Quando si ha a che fare con un sito web ASP.NET in modalità HTTPS capita frequentemente di avere problemi a gestire correttamente i secure cookies, ovvero i cookie configurati per essere impostati solo se la richiesta al server da parte del client - la cosiddetta request - avviene in modalità sicura (SSL). Nella maggior parte dei casi questi problemi producono tutti il seguente messaggio di errore:
System.Web.HttpException (0x80004005): The application is configured to issue secure cookies. These cookies require the browser to issue the request over SSL (https protocol). However, the current request is not over SSL.
Che comunica, in poche parole, l'impossibilità da parte del server di effettuare un cookie-set (ovvero di impostare uno o più cookie) sul client che effettua la request poiché quest'ultima non viene effettuata in SSL. Nella maggior parte dei casi questo può accadere per tre motivi:
- Il certificato SSL non è configurato direttamente sul Web Server ma è installato "a monte" su un reverse proxy o load-balancer (Nginx o simile), il quale si occupa di gestire l'end-point SSL per poi passare il risultato al Web Server tramite un canale non protetto. Questa implementazione HTTPS, nota come SSL Termination, è generalmente sicura ma ha l'effetto collaterale che il Web Server non ha alcun modo di accorgersi che la connessione è avvenuta - a monte - tramite SSL: di conseguenza, il parametro HttpContext.Current.Request.IsSecureConnection sarà valorizzato a false e il parametro HttpContext.Current.Request.Url.Scheme darà come risultato http anziché https.
- Configurazione errata del Web.Config, che si verifica generalmente quando le impostazioni dei cookie di autenticazione non corrispondono a quelle dei cookie di sessione (e di tutti gli altri cookie).
- Problemi legati a Windows XP o versioni precedenti, il cui sistema di decodifica SSL (libreria Crypt32.dll) presenta una anomalia, riconosciuta da Microsoft, che impedisce al sistema di determinare correttamente l'esistenza e/o la validità del certificato.
Vediamo quali sono le azioni che possiamo intraprendere e le risorse a nostra disposizione per affrontare ciascuna di queste problematiche.
Certificato configurato a monte del Web Server (SSL Termination)
La prima cosa da comprendere è che l'errore non è dovuto a una falla di sicurezza del nostro sistema, ma all'impossibilità oggettiva di IIS (e quindi della nostra applicazione) di comprendere che la richiesta, pur non essendo SSL, è già stata opportunamente verificata "a monte" dal load balancer/reverse proxy: di conseguenza, per risolvere il problema dobbiamo trovare il modo di comunicare ad ASP.NET questa informazione.
Per controllare se la richiesta arriva o meno in SSL ASP.NET controlla se la variabile server HTTPS esiste ed ha un valore pari a "on". Una soluzione potrebbe essere quella di impostarla noi, ma prima di fare una cosa del genere dobbiamo assicurarci che la richiesta arrivi effettivamente da un endpoint SSL. Per questo ci viene in aiuto l'header HTTP_X_FORWARDED_PROTO , generalmente impostato (con valore https) dal load-balancer/reverse proxy subito dopo aver verificato la connessione protetta e immediatamente prima di passare la chiamata al web server retrostante.
Abbiamo quindi tutti gli strumenti per impostare la seguente regola di rewrite:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<rewrite> <rules> <rule name="HTTPS_On" patternSyntax="Wildcard"> <match url="*" /> <serverVariables> <set name="HTTPS" value="on" /> </serverVariables> <action type="None" /> <conditions> <add input="{HTTP_X_FORWARDED_PROTO}" pattern="https" /> </conditions> </rule> </rules> </rewrite> |
La regola di cui sopra aggiunge una variabile server HTTPS, impostandola ad On, in tutti i casi in cui l'header HTTP_X_FORWARDED_PROTO corrisponde a una connessione https.
NOTA: Se non sapete cos'è una regola di rewrite o come impostarla, leggete qui.
In alternativa potete sempre disabilitare l'impostazione che impone al sito di creare soltanto cookie in modalità sicura. Per far questo localizzate la seguente riga del Web.Config:
1 |
<httpCookies httpOnlyCookies="true" requireSSL="true" /> |
E sostituite il valore dell'attributo requireSSL impostandolo a false. Questa pratica è generalmente sconsigliata, in quanto apre il vostro sito a potenziali falle di sicurezza: anche se nel vostro caso specifico - a patto che accettiate unicamente connessioni HTTPS e che l'SSL Termination sia opportunamente configurato - l'impatto in termini di sicurezza è praticamente nullo, resta il fatto che i cookie generati sul browser dell'utente saranno visualizzati come "non sicuri": la cosa potrà essere visualizzata da qualsiasi utente mediamente esperto in vari modi, ad esempio dando un'occhiata alla finestra resources del pannello Strumenti per sviluppatori di Google Chrome:
Per questo motivo consigliamo di evitare di ricorrere a questo workaround salvo quando assolutamente necessario: vedere i cookie di autenticazione impostati in modalità non sicura potrebbe far storcere il naso ai vostri clienti, nonché stuzzicare la curiosità di qualche aspirante hacker nei riguardi delle procedure di autenticazione del vostro sito.
Configurazione errata del Web.Config
Questa problematica si verifica frequentemente quando il sito web utilizza la form authentication di ASP.NET, che prevede per impostazione predefinita la creazione di un cookie contenente le credenziali dell'utente, impostandola in modo contraddittorio rispetto alle impostazioni generali dei cookie. Questo può accadere per via del fatto che le due impostazioni sono, sfortunatamente, situate in due punti diversi del Web.Config. In dettaglio:
- La configurazione della form authentication si trova in <system.web><forms>
- La configurazione generale dei cookie (che influenza anche il cookie di sessione ASPNET_SessionId) si trova in <system.web><httpCookies>
Sia l'elemento <forms> che l'elemento <httpCookies> hanno un attributo requireSSL che è opportuno impostare allo stesso modo: true nel caso in cui si vogliano creare unicamente cookie in modalità sicura, false in caso contrario.
Questo è un esempio di una porzione di Web.Config per impostare correttamente la creazione di cookie in modalità sicura:
1 2 3 4 5 6 7 8 9 |
<system.web> <!-- ... --> <!-- all your other options go here --> <!-- ... --> <authentication> <forms name="Login" loginUrl="login.aspx" protection="All" timeout="60" requireSSL="true" /> </authentication> <httpCookies httpOnlyCookies="true" requireSSL="true" /> </system.web> |
Problemi legati a Windows XP
Questa tipologia di problemi è la più insidiosa, in quanto il sito sembra funzionare correttamente se provato con macchine dotate di Sistemi Operativi recenti (Windows 7 e successivi). Inoltre, trattandosi di una anomalia della libreria di decrypting interna al sistema (Crypt32.dll), il problema si manifesta indipendentemente dal browser utilizzato: si crea spesso quindi quindi la situazione altamente controintuitiva per cui lo stesso sito potrebbe funzionare in modo molto diverso sulla stessa versione del medesimo browser, installato però su macchine diverse.
Si tratta di un problema noto e riconosciuto da Microsoft, per il quale sono stati pubblicati alcuni articoli sulla KB (e rilasciati altrettanti hotfix):
- SSL connection does not work on Windows XP
- Windows Server 2003 and Windows XP clients cannot obtain certificates from a Windows Server 2008-based certification authority (CA) if the CA is configured to use SHA2 256 or higher encryption
Se pensate di essere vittime di questo tipo di problema potete provare ad aggiornare il vostro sistema installando gli hotfix disponibili per il download nelle pagine sopra elencate: in alternativa - o se non avete la possibilità di far installare questo aggiornamento a tutti i vostri utenti - non vi resta che impostare l'attributo requireSSL del Web.Config su false (cfr. paragrafo precedente) e rinunciare, almeno per il momento, alla creazione di cookie in modalità sicura.
Per il momento è tutto: felice connessione!