Abilita HTTP Strict Transport Security (HSTS) in IIS 7


76

Qual è il modo migliore per attivare HTTP Strict Transport Security su un server Web IIS 7?

Posso semplicemente usare la GUI e aggiungere l'intestazione della risposta HTTP corretta o dovrei usare appcmd e, in caso affermativo, cosa cambia?


1
Molto dipende da come stai generando i contenuti di IIS (ad esempio. Puoi impostare l'intestazione nelle pagine PHP o ASP.NET dall'interno della tua applicazione). Puoi dirci di più sul tuo caso d'uso?
voretaq7,

Risposte:


18

IIS ha la possibilità di aggiungere intestazioni personalizzate alle risposte . Questo sembrerebbe essere il modo più semplice per farlo.

Secondo la documentazione su IIS.net è possibile aggiungere queste intestazioni tramite Gestione IIS:

  • Nel riquadro Connessioni, vai al sito, all'applicazione o alla directory per cui desideri impostare un'intestazione HTTP personalizzata.
  • Nel riquadro Home, fare doppio clic su Intestazioni risposta HTTP.
  • Nel riquadro Intestazioni risposta HTTP, fai clic su Aggiungi ... nel riquadro Azioni.
  • Nella finestra di dialogo Aggiungi intestazione risposta HTTP personalizzata, impostare il nome e il valore per l'intestazione personalizzata, quindi fare clic su OK.

5
È anche possibile farlo in Web.config, che potresti preferire. Ho pubblicato i dettagli come una nuova risposta, dato che sarebbero davvero difficili da leggere senza la formattazione del codice sorgente che non è disponibile nei commenti.
Owen Blacker,

3
Secondo i produttori del modulo IIS di HTTP Strict Transport Security , la semplice aggiunta dell'intestazione personalizzata non è conforme alla bozza di specifica (RFC 6797). Dovresti effettivamente installare questo modulo IIS.
Chris,

@Chris Hanno (un po ') sbagliato. Non sulle specifiche - sono assolutamente corrette lì - ma sul fatto che non esiste un modo "semplice" per conformarsi a parte il loro modulo: basta creare 2 siti, uno per SSL (con l'intestazione) e uno per non SSL ( senza intestazione). Certamente il modulo è un po 'più elegante , ma non è necessario (e non è garantito se il tuo sito è solo https e non fornisci semplici risposte HTTP).
voretaq7,

1
@Chris Dovresti aggiungere una risposta facendo riferimento a quel modulo: voti gratuiti! (Non ero a conoscenza della sua esistenza, e per molte persone è probabilmente un'opzione più facile / migliore rispetto alla roba dell'intestazione personalizzata)
voretaq7

112

Questo ci consente di gestire sia il reindirizzamento HTTP sia di aggiungere l'intestazione Strict-Transport-Security alle risposte HTTPS con un singolo sito IIS (il modulo di riscrittura URL deve essere installato):

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="HTTP to HTTPS redirect" stopProcessing="true">
                    <match url=".*" />
                    <conditions>
                        <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}"
                        redirectType="Permanent" />
                </rule>
            </rules>
            <outboundRules>
                <rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
                    <match serverVariable="RESPONSE_Strict_Transport_Security"
                        pattern=".*" />
                    <conditions>
                        <add input="{HTTPS}" pattern="on" ignoreCase="true" />
                    </conditions>
                    <action type="Rewrite" value="max-age=31536000; includeSubDomains; preload" />
                </rule>
            </outboundRules>
        </rewrite>
    </system.webServer>
</configuration>

7
Grazie, questa è la migliore risposta! Aggiunge l'intestazione anche ai file HTML statici, a differenza dell'approccio programmatico. E non si aggiunge a HTTP, quindi conforme allo standard.
Jeow Li Huan,

4
@Mathemats Hai installato URL Rewrite in IIS?
Doug Wilson,

3
No, dopo ulteriori ricerche ho scoperto che il tag di riscrittura è fornito dall'estensione (d'oh). Tutte le risposte che ho trovato non menzionano l'estensione come una dipendenza, forse potresti inserire una sola riga nella tua risposta dicendo che ne hai bisogno.
Mathemats,

2
hstspreload.org vuole che l'utente aggiunga `; includeSubDomains; precarico` dopo il valore massimo. opzioni. La linea completa sarà: <action type="Rewrite" value="max-age=31536000 ;includeSubDomains; preload" />ottenere un passaggio su hstspreload.org
JP Hellemons,

2
Il gruppo di acquisizione R: 1 con il modello (. *) Corrisponde all'intero URL, protocollo e tutti, e provare a concatenare {HTTP_HOST} / {R: 1} significa che ottieni https://somedomain.com/https://somedomain.com/relatedpathe il risultato è che il percorso viene abbandonato.
AaronLS,

38

Per integrare la risposta di voretaq7 , puoi anche farlo usando il file Web.config (NB: da usare solo per siti SSL, poiché aggiungerà l'intestazione per le risposte HTTP e HTTPS, che è contro la specifica RFC 6797, si prega di consultare la spiegazione di seguito) - aggiungere un blocco come segue:

<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name="Strict-Transport-Security" value="max-age=31536000"/>
        </customHeaders>
    </httpProtocol>
</system.webServer>

Ovviamente, potresti già avere un system.webServerblocco nel tuo Web.config, quindi aggiungi questo, se è così. Preferiamo gestire le cose nel Web.config piuttosto che nella GUI, perché significa che le modifiche alla configurazione possono essere impegnate nel nostro repository Git.

Se si desidera gestire il reindirizzamento da HTTP a SSL, come menzionato da Greg Askew , potrebbe essere più semplice farlo con un sito Web separato in IIS. Ecco come gestiamo la richiesta di SSL per alcuni siti client. Quel sito contiene solo un reindirizzamento HTTP e alcune correzioni per la divulgazione di informazioni , tutto in Web.config:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <httpRuntime requestValidationMode="2.0" enableVersionHeader="false" />
  </system.web>
  <system.webServer>
    <httpRedirect enabled="true" destination="https://www.domain.co.uk/"
      httpResponseStatus="Permanent" />
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
    <rewrite>
      <outboundRules>
        <rule name="Remove RESPONSE_Server">
          <match serverVariable="RESPONSE_Server" pattern=".+" />
          <action type="Rewrite" value="" />
        </rule>
      </outboundRules>
    </rewrite>
  </system.webServer>
</configuration>

Questa è la nostra soluzione preferita per un paio di motivi: possiamo facilmente registrare separatamente il traffico reindirizzato (poiché si trova in un diverso registro IIS), non comporta più codice in Global.asax.cs (non abbiamo alcun codice lì dentro, che è un po 'più conveniente per un sito Umbraco) e, soprattutto, significa che tutta la configurazione è ancora presente nel nostro repository GIT.

Modificato per aggiungere: per essere chiari, al fine di ottemperare a RFC 6797 , l' Strict-Transport-Securityintestazione personalizzata NON DEVE essere aggiunta alle richieste fatte da HTTP non crittografato. Per essere conforme a RFC6797, DEVI avere due siti in IIS, come ho descritto dopo il primo blocco di codice. Come sottolinea Chris , RFC 6797 include:

Un host HSTS NON DEVE includere il campo di intestazione STS nelle risposte HTTP trasmesse su trasporto non sicuro.

pertanto l'invio Strict-Transport-Securitydell'intestazione del cliente in risposta a una richiesta non SSL non sarebbe conforme alle specifiche.


1
Per aggiungere alla risposta Owen Blacker, per IIS utilizzo URLScan 3.1 e rimuovo globalmente il SERVER dalla risposta impostando RemoveServerHeader = 1, il resto delle impostazioni ha richiesto di essere in ogni file web.config del sito. Preferisco questo a sopprimere il valore.
KeyOfJ

URLScan è una soluzione molto comune e, suggerirei, una migliore di quella che sto suggerendo. Ma non è sempre la soluzione più conveniente: o)
Owen Blacker,

È importante notare che l'aggiunta di questo a un sito con HTTPS e HTTP abilitati (in modo che possa reindirizzare) interromperà il sito! Otterrai un 500 senza informazioni, anche con la modalità CustomErrors = "Off", senza errori nei registri.
Chris Moschini,

@ChrisMoschini Avrei dovuto essere più chiaro che la prima riga Web.config dovrebbe essere per un sito solo SSL.
Owen Blacker,

1
@Lenne Scott Hanselman ha scritto una descrizione molto più valida del perché STS non appartiene all'intestazione durante l'utilizzo di HTTP. Maggiori informazioni qui
David Yates,

8

Vorrei usare l'esempio dal link Wikipedia a cui hai fatto riferimento ed eseguire l'attività in global.asax per il sito. Ciò consente di reindirizzare la richiesta a un URL https, quindi inserire l'intestazione nella risposta.

Ciò è dovuto al fatto che l'intestazione HSTS deve essere ignorata se non è in una risposta https.

protected void Application_BeginRequest()
{
    switch (Request.Url.Scheme)
    {
        case "https":
            Response.AddHeader("Strict-Transport-Security", "max-age=31536000");
            break;
        case "http":
            var path = "https://" + Request.Url.Host + Request.Url.PathAndQuery;
            Response.Status = "301 Moved Permanently";
            Response.AddHeader("Location", path);
            break;
    }
}

3

Questo sembra essere un modo abbastanza sicuro per farlo. Aggiungi questo codice in Global.asax: l'evento Application_BeginRequest viene generato per primo nel ciclo di vita della richiesta Asp.net: http://msdn.microsoft.com/en-us/library/system.web.httpapplication.beginrequest(v=vs. 110) aspx

Secondo le specifiche, le richieste http non devono rispondere con l'intestazione, quindi questo codice lo aggiunge solo per le richieste https. Max-age è in numero di secondi ed è generalmente una buona idea inserire un valore elevato qui (IE - 31536000 indica che il sito eseguirà SSL solo per i prossimi 365 giorni)

protected void Application_BeginRequest(Object sender, EventArgs e)
{
  switch (Request.Url.Scheme)
  {
    case "https":
      Response.AddHeader("Strict-Transport-Security", "max-age=31536000");
      break;
    case "http":
      var path = "https://" + Request.Url.Host + Request.Url.PathAndQuery;
      Response.Status = "301 Moved Permanently";
      Response.AddHeader("Location", path);
      break;
  }
}

2

Utilizzando l'esempio fornito da Doug Wilson, ho creato le seguenti due funzioni di PowerShell per aggiungere regole di riscrittura degli URL per il reindirizzamento a HTTPS e per l'aggiunta di intestazioni HSTS.

Questi sono stati testati su Windows 2012 e Windows 2012 R2.

Tutto quello che devi fare è fornire il nome del sito web. Opzionalmente puoi assegnare un nome diverso alle regole se non ti piacciono le impostazioni predefinite.

Una cosa da notare è che dal mio test, le variabili del server devono essere aggiunte all'elenco di autorizzazioni prima di essere nelle intestazioni di risposta. Le funzioni fanno questo per te.

EDIT: vedi riferimento su Url Rewrite per le intestazioni HTTP qui: http://www.iis.net/learn/extensions/url-rewrite-module/setting-http-request-headers-and-iis-server-variables

Function Add-HTTPSRedirectRewriteRule()
{
    <#
        .SYNOPSIS
        This function is used to create a URL Rewrite Rule that redirects HTTP requests to HTTPS using a 301
        RuleName is optional and will default to "Redirect to HTTPS"

        .SYNTAX
        Add-HTTPSRedirectRewriteRule -WebsiteName "www.mywebsite.com"

        .EXAMPLES
        Add-HTTPSRedirectRewriteRule -WebsiteName "www.mywebsite.com"

        Add-HTTPSRedirectRewriteRule -WebsiteName "www.mywebsite.com" -RuleName "my rule name"

    #>


    [cmdletbinding(positionalbinding=$false)]
    Param
    (
        [parameter(mandatory=$true)][String] [ValidateNotNullOrEmpty()] $WebsiteName,
        [parameter(mandatory=$false)][String] $RuleName="Redirect to HTTPS"
    )

        Write-Verbose -Message "Creating the Url Rewrite rule ""$RuleName"" in website ""$WebsiteName"""
        Remove-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/rules" -name "." -AtElement @{name="$RuleName"}  -ErrorAction SilentlyContinue
        Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules" -name "." -value @{name="$RuleName";stopProcessing='True'}
        Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/match" -name "url" -value "(.*)"
        Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/conditions" -name "." -value @{input='{HTTPS}';pattern='off'}
        Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/action" -name "type" -value "Redirect"
        Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/action" -name "url" -value "https://{HTTP_HOST}/{R:1}"
}

Function Add-HSTSHeaderRewriteRule()
{
    <#
        .SYNOPSIS
        This function is used to create a URL Rewrite Rule that sets an HTTP Response Header for Strict-Transport-Security
        when the protocol requested is HTTPS

        RuleName is optional and will default to "Add Strict-Transport-Security header when request is HTTPS"

        .SYNTAX
        Add-HSTSHeaderRewriteRule -WebsiteName "www.mywebsite.com"

        .EXAMPLES
        Add-HSTSHeaderRewriteRule -WebsiteName "www.mywebsite.com"

        Add-HSTSHeaderRewriteRule -WebsiteName "www.mywebsite.com" -RuleName "my rule name"

    #>

    [cmdletbinding(positionalbinding=$false)]
    Param
    (
        [parameter(mandatory=$true)][String] [ValidateNotNullOrEmpty()] $WebsiteName,
        [parameter(mandatory=$false)][String]$RuleName="Add Strict-Transport-Security header when request is HTTPS"
    )

    $serverVariable = "RESPONSE_Strict_Transport_Security"

    Write-Verbose -Message "Creating the HSTS Header rule ""$RuleName"" in website ""$WebsiteName"""

    Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/allowedServerVariables" -name "." -AtElement @{name="$serverVariable"} -ErrorAction SilentlyContinue
    Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName"  -filter "system.webServer/rewrite/allowedServerVariables" -name "." -value @{name="$serverVariable"}

    Remove-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -name "." -filter "system.webServer/rewrite/outboundRules" -AtElement @{name="$RuleName"} -ErrorAction SilentlyContinue

    Add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules" -name "." -value @{name="$RuleName"}
    Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/match" -name "serverVariable" -value $serverVariable
    Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/match" -name "pattern" -value ".*"
    Add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/conditions" -name "." -value @{input='{HTTPS}';pattern='on'}
    Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/action" -name "type" -value "Rewrite"
    Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/action" -name "value" -value "max-age=31536000"

}

1

Secondo i produttori del modulo IIS di HTTP Strict Transport Security, la semplice aggiunta dell'intestazione personalizzata non è conforme alla bozza di specifica (RFC 6797).

Dovresti effettivamente installare questo modulo IIS per attivare HSTS su IIS 7.

Aggiornamento 26 ottobre 2014 : grazie al commentatore di seguito, ho letto di nuovo la pagina del modulo e in particolare la parte che giustifica l'uso del modulo rispetto all'aggiunta di intestazioni personalizzate.

Un host HSTS NON DEVE includere il campo di intestazione STS nelle risposte HTTP trasmesse su trasporto non sicuro.

Se ti assicuri di aggiungere le intestazioni solo in HTTPS e NON in HTTP, non hai bisogno di questo modulo e puoi usare la risposta di Doug Wilson. Non usare la risposta di Owen Blacker perché non ha la condizione https.


1
Quindi alcune delle altre risposte che inviano solo l'intestazione alle richieste HTTPS risolvono anche questo problema? O il tuo modulo fa qualcosa di diverso / extra rispetto alle altre soluzioni?
slolife,

@slolife Ho aggiornato la mia risposta. Puoi usare il codice nella risposta di Doug Wilson. Non hai bisogno di questo modulo. Vedo ora che questo è discusso anche nei commenti della risposta accettata. Non sono a conoscenza del fatto che questo modulo stia facendo qualcosa di diverso / extra rispetto alle altre soluzioni. Ma non ho nemmeno fatto un controllo esauriente del codice sorgente .
Chris,

Avrei dovuto essere più chiaro che il primo Web.config doveva essere implementato in un sito solo SSL. Modificherò la mia risposta per chiarirlo.
Owen Blacker,

1

Questo può essere fatto aggiungendo il seguente blocco in Web.Config:

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name ="CustomName" value="MyCustomValue"/>
      </customHeaders>
    </httpProtocol>
</system.webServer>

Dobbiamo configurare su IIS che ha la capacità di rispondere alle intestazioni personalizzate:

  • Vai a Gestione Internet Information Services (IIS).
  • Configurare le intestazioni di risposta aggiunte alla risposta dal server.
  • Ora aggiungi il nome dell'intestazione personalizzata e il valore personalizzato (il nome e il valore dell'intestazione personalizzati devono essere uguali a quelli in Web.Config). Puoi trovarlo sul blog

0

Solo per aggiungere, vedo nei commenti 2 persone che parlano di 500 errori quando lo fai. Ho avuto questo

Se viene visualizzato un errore 500 in IIS, è possibile che sia stata aggiunta la regola sia al livello principale, impostato su ereditato, sia a livello di sito.

per esempio

Default Web Site <- here
  Some Web Site <- here

IIS / Il browser non sembra fornire alcuna informazione in merito, indipendentemente dalle impostazioni di gestione degli errori

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.