Habilite HTTP Strict Transport Security (HSTS) en IIS 7

76

¿Cuál es la mejor manera de activar HTTP Strict Transport Security en un servidor web IIS 7?

¿Puedo simplemente a través de la GUI y agregar el encabezado de respuesta HTTP adecuado o debería usar appcmd y, de ser así, qué cambia?

Mover
fuente
1
Mucho de esto depende de cómo esté generando el material que IIS está sirviendo (por ejemplo, puede configurar el encabezado en páginas PHP o ASP.NET desde su aplicación). ¿Puede contarnos más sobre su caso de uso?
voretaq7

Respuestas:

18

IIS tiene la capacidad de agregar encabezados personalizados a las respuestas . Esta parece ser la forma más fácil de hacerlo.

De acuerdo con la documentación en IIS.net , puede agregar estos encabezados a través del Administrador de IIS:

  • En el panel Conexiones, vaya al sitio, la aplicación o el directorio para el que desea establecer un encabezado HTTP personalizado.
  • En el panel de inicio, haga doble clic en Encabezados de respuesta HTTP.
  • En el panel Encabezados de respuesta HTTP, haga clic en Agregar ... en el panel Acciones.
  • En el cuadro de diálogo Agregar encabezado de respuesta HTTP personalizado, establezca el nombre y el valor de su encabezado personalizado y luego haga clic en Aceptar.
voretaq7
fuente
55
También es posible hacer esto en Web.config, que puede preferir. He publicado los detalles como una nueva respuesta, ya que sería muy difícil de leer sin el formato del código fuente que no está disponible en los comentarios.
Owen Blacker
3
De acuerdo con los creadores del módulo HTTP Strict Transport Security IIS , solo agregar el encabezado personalizado no cumple con el borrador de especificación (RFC 6797). En realidad, necesitaría instalar este módulo IIS.
Chris
@ Chris Están (un poco) equivocados. No se trata de la especificación, son absolutamente correctas allí, sino del hecho de que no hay una forma "simple" de cumplir aparte de su módulo: solo cree 2 sitios, uno para SSL (con el encabezado) y otro para no SSL ( sin el encabezado). Ciertamente, el módulo es un poco más elegante , pero no es necesario (y no está garantizado en absoluto si su sitio es solo https y no sirve respuestas HTTP simples).
voretaq7
1
@Chris Sin embargo, debe agregar una respuesta que haga referencia a ese módulo: ¡votaciones libres! (No estaba al tanto de su existencia, y para muchas personas es probablemente una opción más fácil / mejor que el encabezado personalizado)
voretaq7
112

Esto nos permite manejar la redirección HTTP y agregar el encabezado Strict-Transport-Security a las respuestas HTTPS con un solo sitio IIS (el módulo URL Rewrite debe estar instalado):

<?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>
Doug Wilson
fuente
77
Gracias, esta es la mejor respuesta! Agrega el encabezado a los archivos HTML estáticos también, a diferencia del enfoque programático. Y no se agrega a HTTP, por lo que se ajusta al estándar.
Jeow Li Huan
44
@Mathemats ¿Tienes instalado URL Rewrite en IIS?
Doug Wilson
3
No, después de más investigaciones descubrí que la extensión (d'oh) proporciona la etiqueta de reescritura. Todas las respuestas que pude encontrar no mencionan la extensión como una dependencia, quizás podría arrojar un solo trazo en su respuesta diciendo que lo necesita.
Mathemats
2
hstspreload.org quiere que el usuario agregue `; includeSubDomains; preload` después del valor de edad máxima. opciones. La línea completa será: <action type="Rewrite" value="max-age=31536000 ;includeSubDomains; preload" />para obtener un pase en hstspreload.org
JP Hellemons
2
El grupo de captura R: 1 con el patrón (. *) Coincide con la URL completa, el protocolo y todo, e intentar concatenar {HTTP_HOST} / {R: 1} significa que obtienes https://somedomain.com/https://somedomain.com/relatedpathy el resultado es que la ruta se descartó.
AaronLS
38

Para complementar la respuesta de voretaq7 , también puede hacerlo utilizando el archivo Web.config (NB: para ser utilizado solo en sitios SSL, ya que agregará el encabezado para las respuestas HTTP y HTTPS, lo que va en contra de la especificación RFC 6797, consulte la explicación a continuación): agregue un bloque de la siguiente manera:

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

Obviamente, es posible que ya tenga un system.webServerbloqueo en su Web.config, así que agregue esto a eso, si es así. Preferimos manejar cosas en Web.config en lugar de la GUI, porque significa que los cambios de configuración pueden confirmarse en nuestro repositorio Git.

Si desea manejar la redirección de HTTP a SSL, como mencionó Greg Askew , puede que le resulte más fácil hacerlo con un sitio web separado en IIS. Así es como manejamos la necesidad de SSL para algunos sitios de clientes. Ese sitio contiene solo un redireccionamiento HTTP y algunas correcciones de divulgación de información , todo en la 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>

Esta es nuestra solución preferida por un par de razones: podemos registrar fácilmente el tráfico redirigido por separado (ya que está en un registro IIS diferente), no involucra más código en Global.asax.cs (no tenemos ningún código allí, que es un poco más conveniente para un sitio de Umbraco) y, lo que es más importante, significa que toda la configuración todavía se mantiene en nuestro repositorio de GIT.

Editado para agregar: Para ser claros, para cumplir con RFC 6797 , el Strict-Transport-Securityencabezado personalizado NO DEBE agregarse a las solicitudes realizadas por HTTP no encriptado. Para cumplir con RFC6797, DEBE tener dos sitios en IIS, como lo describí después del primer bloque de código. Como Chris señala, RFC 6797 incluye:

Un host HSTS NO DEBE incluir el campo de encabezado STS en las respuestas HTTP transmitidas a través del transporte no seguro.

por lo que enviar el Strict-Transport-Securityencabezado del cliente en respuesta a una solicitud que no sea SSL no cumpliría con la especificación

Owen Blacker
fuente
1
Para agregar a la respuesta de Owen Blacker, para IIS utilizo URLScan 3.1 y hago que elimine globalmente el SERVIDOR de la respuesta configurando RemoveServerHeader = 1, el resto de las configuraciones han ordenado estar en cada archivo web.config del sitio. Prefiero esto a borrar el valor.
KeyOfJ
URLScan es una solución muy común y, sugeriría, una mejor que la que estoy sugiriendo. Pero no siempre es la solución más conveniente: o)
Owen Blacker
Es importante tener en cuenta que agregar esto a un sitio con HTTPS y HTTP habilitados (para que pueda redirigir) ¡ROMPERÁ el sitio! Obtendrá 500 sin información, incluso con CustomErrors Mode = "Off", sin errores en los registros.
Chris Moschini
@ChrisMoschini Debería haber sido más claro que la primera línea Web.config debería ser para un sitio solo SSL.
Owen Blacker
1
@Lenne Scott Hanselman escribió una descripción más buena de por qué STS no pertenece al encabezado mientras usa HTTP. Lea más aquí
David Yates
8

Usaría el ejemplo del enlace de Wikipedia al que hizo referencia y realizaría la actividad en global.asax para el sitio. Esto permite redirigir la solicitud a una URL https y luego insertar el encabezado en la respuesta.

Esto se debe a que el encabezado HSTS debe ignorarse si no está en una respuesta 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;
    }
}
Greg Askew
fuente
3

Esto parece ser una manera bastante segura de hacer esto. Agregue este código en Global.asax: el evento Application_BeginRequest se dispara primero en el ciclo de vida de la solicitud Asp.net: http://msdn.microsoft.com/en-us/library/system.web.httpapplication.beginrequest(v=vs. 110) .aspx

Según la especificación, las solicitudes http no deben responder con el encabezado, por lo que este código solo lo agrega para las solicitudes https. La edad máxima es en número de segundos, y generalmente es una buena idea poner un valor grande aquí (IE - 31536000 indica que el sitio ejecutará SSL solo durante los próximos 365 días)

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;
  }
}
erbz
fuente
2

Utilizando el ejemplo proporcionado por Doug Wilson, he creado las siguientes dos funciones de PowerShell para agregar reglas de reescritura de URL para redireccionar a HTTPS y para agregar encabezados HSTS.

Estos han sido probados en Windows 2012 y Windows 2012 R2.

Todo lo que necesita hacer es proporcionar el nombre del sitio web. Opcionalmente, puede asignar un nombre diferente a las reglas si no le gustan los valores predeterminados.

Una cosa a tener en cuenta es que, a partir de mis pruebas, las variables del servidor deben agregarse a la lista de permisos antes de estar en los encabezados de respuesta. Las funciones hacen esto por ti.

EDITAR: consulte la referencia sobre Reescritura de URL para encabezados HTTP aquí: 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"

}
CarlR
fuente
1

De acuerdo con los creadores del módulo HTTP Strict Transport Security IIS, solo agregar el encabezado personalizado no cumple con el borrador de la especificación (RFC 6797).

En realidad, necesitaría instalar este módulo IIS para activar HSTS en IIS 7.

Actualización 26 de octubre de 2014 : Gracias al comentarista a continuación, leí la página del módulo nuevamente y específicamente la parte que justifica el uso del módulo sobre la adición de encabezados personalizados.

Un host HSTS NO DEBE incluir el campo de encabezado STS en las respuestas HTTP transmitidas a través del transporte no seguro.

Si se asegura de agregar los encabezados solo en HTTPS y NO en HTTP, no necesita este módulo y puede usar la respuesta de Doug Wilson. No use la respuesta de Owen Blacker porque no tiene la condición https.

Chris
fuente
1
Entonces, ¿algunas de las otras respuestas que solo envían el encabezado a las solicitudes HTTPS también resuelven este problema? ¿O su módulo hace algo diferente / extra que las otras soluciones no hacen?
slolife
@slolife Actualicé mi respuesta. Puede usar el código en la respuesta de Doug Wilson. No necesitas este módulo. Ahora veo que esto también se discute en los comentarios de la respuesta aceptada. No estoy al tanto de que este módulo haga algo diferente / extra que las otras soluciones no. Pero tampoco he hecho una verificación exhaustiva del código fuente .
Chris
Debería haber sido más claro que el primer Web.config debería implementarse en un sitio solo SSL. Editaré mi respuesta para aclarar eso.
Owen Blacker
1

Esto se puede hacer agregando el siguiente bloque en Web.Config:

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

Tenemos que configurar en IIS que tenga la capacidad de personalizar los encabezados para responder:

  • Vaya al Administrador de Internet Information Services (IIS).
  • Configure los encabezados de respuesta que se agregan a la respuesta del servidor.
  • Ahora agregue su Nombre de encabezado personalizado y su Valor personalizado (el nombre y el valor del encabezado personalizado deben ser los mismos que en Web.Config). Puedes encontrar en el blog
Vinit
fuente
0

Solo para agregar, veo en los comentarios a 2 personas hablando de 500 errores cuando haces esto. Tuve esto

Si obtiene un error 500 en IIS puede ser porque ha agregado la regla tanto en el nivel superior, configurado como heredado y en el nivel del sitio.

p.ej

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

IIS / The Browser no parece darle ninguna información de que haya hecho esto, independientemente de la configuración de manejo de errores

Tony
fuente