Habilitar HSTS (HTTP Strict Transport Security) no IIS 7

75

Qual é a melhor maneira de ativar o HTTP Strict Transport Security em um servidor Web IIS 7?

Posso apenas através da GUI e adicionar o cabeçalho de resposta HTTP adequado ou devo usar o appcmd e, em caso afirmativo, o que muda?

Prumo
fonte
1
Muito disso depende de como você está gerando as coisas que o IIS está exibindo (por exemplo, você pode definir o cabeçalho nas páginas PHP ou ASP.NET de dentro do seu aplicativo). Você pode nos contar mais sobre o seu caso de uso?
voretaq7

Respostas:

18

O IIS tem a capacidade de adicionar cabeçalhos personalizados às respostas . Essa seria a maneira mais fácil de fazer isso.

De acordo com a documentação no IIS.net, você pode adicionar esses cabeçalhos através do Gerenciador do IIS:

  • No painel Conexões, acesse o site, aplicativo ou diretório para o qual você deseja definir um cabeçalho HTTP personalizado.
  • No painel Inicial, clique duas vezes em Cabeçalhos de Resposta HTTP.
  • No painel Cabeçalhos de resposta HTTP, clique em Adicionar ... no painel Ações.
  • Na caixa de diálogo Adicionar cabeçalho de resposta HTTP personalizado, defina o nome e o valor do seu cabeçalho personalizado e clique em OK.
voretaq7
fonte
5
Também é possível fazer isso no Web.config, que você pode preferir. Publiquei os detalhes como uma nova resposta, pois seria muito difícil de ler sem a formatação do código-fonte que não está disponível nos comentários.
quer
3
De acordo com os fabricantes do módulo IIS de segurança estrita de transporte HTTP , apenas adicionar o cabeçalho personalizado não é compatível com a especificação preliminar (RFC 6797). Você realmente precisaria instalar este módulo IIS.
25414 Chris
@ Chris Eles estão (meio que) errados. Não sobre as especificações - elas são absolutamente corretas -, mas sobre o fato de não haver uma maneira "simples" de cumprir, exceto o módulo: basta criar 2 sites, um para SSL (com o cabeçalho) e outro para não SSL sem o cabeçalho). Certamente o módulo é um pouco mais elegante , mas não é necessário (e não é garantido se o seu site for somente https e você não fornecer respostas HTTP simples).
voretaq7
1
@ Chris Você deve adicionar uma resposta referenciando esse módulo - votos grátis! (Eu não estava ciente de sua existência, e por um monte de gente é provavelmente um mais fácil / melhor opção do que o material cabeçalho personalizado)
voretaq7
112

Isso nos permite manipular o redirecionamento HTTP e adicionar o cabeçalho Strict-Transport-Security às respostas HTTPS com um único site IIS (o módulo URL Rewrite deve ser 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
fonte
7
Obrigado, esta é a melhor resposta! Também adiciona o cabeçalho aos arquivos HTML estáticos, ao contrário da abordagem programática. E não adiciona ao HTTP, em conformidade com o padrão.
Jeow Li Huan 7/11
4
@ Mathemats Você tem o URL Rewrite instalado no IIS?
Doug Wilson
3
Não, depois de mais pesquisas, descobri que a tag reescrita é fornecida pela extensão (d'oh). Todas as respostas que pude encontrar não mencionam a extensão como uma dependência, talvez você possa colocar uma linha na sua resposta dizendo que precisa.
Mathemats
2
O hstspreload.org deseja que o usuário adicione `; includeSubDomains; preload` após o valor da idade máxima. opções A linha completa será: <action type="Rewrite" value="max-age=31536000 ;includeSubDomains; preload" />para obter um passe em hstspreload.org
JP Hellemons
2
O grupo de captura R: 1 com o padrão (. *) Corresponde a toda a URL, protocolo e tudo, e tentar concatenar {HTTP_HOST} / {R: 1} significa que você obtém https://somedomain.com/https://somedomain.com/relatedpathe o resultado é que o caminho foi interrompido.
AaronLS
38

Para complementar a resposta do voretaq7 , você também pode fazer isso usando o arquivo Web.config (NB: Para ser usado apenas em sites SSL, pois ele adicionará o cabeçalho das respostas HTTP e HTTPS, que é contra a especificação RFC 6797, veja a explicação abaixo) - adicione um bloco da seguinte maneira:

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

Obviamente, você já pode ter um system.webServerbloco no seu Web.config, então adicione isso a isso, se houver. Preferimos manipular as coisas no Web.config do que na GUI, porque isso significa que as alterações na configuração podem ser confirmadas em nosso repositório Git.

Se você deseja lidar com o redirecionamento HTTP para SSL, como Greg Askew mencionou, talvez seja mais fácil fazer isso com um site separado no IIS. É assim que lidamos com a exigência de SSL para alguns sites clientes. Esse site contém apenas um redirecionamento HTTP e algumas correções de divulgação de informações , todas no 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 é a nossa solução preferida por alguns motivos - podemos registrar facilmente o tráfego redirecionado separadamente (como em um log do IIS diferente), não envolve mais código no Global.asax.cs (não temos nenhum código lá, o que é um pouco mais conveniente para um site da Umbraco) e, o que é mais importante, significa que toda a configuração ainda é realizada em nosso repositório GIT.

Editado para adicionar: Para ficar claro, para cumprir a RFC 6797 , o Strict-Transport-Securitycabeçalho personalizado NÃO DEVE ser adicionado a solicitações feitas por HTTP não criptografado. Para ser compatível com RFC6797, você DEVE ter dois sites no IIS, como descrevi após o primeiro bloco de código. Como Chris aponta, o RFC 6797 inclui:

Um host HSTS NÃO DEVE incluir o campo de cabeçalho STS nas respostas HTTP transmitidas por transporte não seguro.

portanto, o envio do Strict-Transport-Securitycabeçalho do cliente em resposta a uma solicitação não SSL não estaria em conformidade com a especificação.

Owen Blacker
fonte
1
Para adicionar à resposta Owen Blacker, no IIS, uso o URLScan 3.1 e o remova globalmente do SERVER da resposta, definindo RemoveServerHeader = 1, o restante das configurações exigidas para estar em cada arquivo web.config do site. Eu prefiro isso a apenas apagar o valor.
KeyOfJ
O URLScan é uma solução muito comum e, eu sugiro, uma solução melhor do que a que estou sugerindo. Mas nem sempre é a solução mais conveniente: o)
Owen Blacker
Importante observar que adicionar isso a um site com HTTPS e HTTP ativado (para que ele possa redirecionar) quebrará o site! Você receberá um 500 sem informações, mesmo com o Modo CustomErrors = "Off", sem erros nos logs.
Chris Moschini
@ChrisMoschini Eu deveria ter deixado mais claro que a primeira linha Web.config deve ser para um site somente SSL.
quer
1
@Lenne Scott Hanselman escreveu uma descrição muito boa de por que o STS não pertence ao cabeçalho enquanto usa HTTP. Leia mais aqui
David Yates
8

Eu usaria o exemplo do link da Wikipedia que você referenciou e executaria a atividade em global.asax para o site. Isso permite redirecionar a solicitação para uma URL https e, em seguida, insira o cabeçalho na resposta.

Isso ocorre porque o cabeçalho do HSTS deve ser ignorado se não estiver em uma resposta 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
fonte
3

Esta parece ser uma maneira bastante segura de fazer isso. Adicione esse código ao Global.asax - o evento Application_BeginRequest é acionado primeiro no ciclo de vida da solicitação do Asp.net: http://msdn.microsoft.com/en-us/library/system.web.httpapplication.beginrequest(v=vs. 110) .aspx

De acordo com a especificação, as solicitações HTTP não devem responder com o cabeçalho - portanto, esse código o adiciona apenas para solicitações https. A idade máxima é de alguns segundos e geralmente é uma boa ideia colocar um valor grande aqui (IE - 31536000 indica que o site executará SSL apenas pelos próximos 365 dias)

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
fonte
2

Usando o exemplo fornecido por Doug Wilson, criei as duas funções do PowerShell a seguir para adicionar regras de reescrita de URL para redirecionamento para HTTPS e para adicionar cabeçalhos HSTS.

Estes foram testados no Windows 2012 e Windows 2012 R2.

Tudo que você precisa fazer é fornecer o nome do site. Você pode opcionalmente dar um nome diferente às regras se não gostar dos padrões.

Um ponto a ser observado é que, nos meus testes, as variáveis ​​de servidor precisam ser adicionadas à lista de permissões antes de estar nos cabeçalhos de resposta. As funções fazem isso por você.

EDIT: Consulte a referência na reescrita de URL para cabeçalhos HTTP aqui: 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
fonte
1

De acordo com os fabricantes do módulo IIS de segurança estrita de transporte HTTP, apenas adicionar o cabeçalho personalizado não é compatível com a especificação preliminar (RFC 6797).

Você realmente precisaria instalar este módulo IIS para ativar o HSTS no IIS 7.

Atualização 26 de outubro de 2014 : Graças ao comentarista abaixo, li a página do módulo novamente e, especificamente, a parte que justifica o uso do módulo ao adicionar cabeçalhos personalizados.

Um host HSTS NÃO DEVE incluir o campo de cabeçalho STS nas respostas HTTP transmitidas por transporte não seguro.

Se você adicionar os cabeçalhos apenas em HTTPS e NÃO em HTTP, não precisará deste módulo e poderá usar a resposta de Doug Wilson. Não use a resposta de Owen Blacker, pois ela não possui a condição https.

Chris
fonte
1
Então, algumas das outras respostas que enviam apenas o cabeçalho para solicitações HTTPS também resolvem esse problema? Ou o seu módulo faz algo diferente / extra que as outras soluções não?
slolife
@slolife Atualizei minha resposta. Você pode usar o código na resposta de Doug Wilson. Você não precisa deste módulo. Vejo agora que isso também é discutido nos comentários da resposta aceita. Não conheço este módulo fazendo algo diferente / extra que as outras soluções não. Mas também não fiz uma verificação exaustiva do código-fonte .
26414 Chris
Eu deveria ter deixado mais claro que o primeiro Web.config deve ser implementado em um site somente SSL. Vou editar minha resposta para esclarecer isso.
quer
1

Isso pode ser feito adicionando o seguinte bloco no Web.Config:

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

Temos que configurar no IIS que tem a capacidade de personalizar cabeçalhos de resposta:

  • Vá para o Gerenciador do Internet Information Services (IIS).
  • Configure os cabeçalhos de resposta adicionados à resposta do servidor.
  • Agora adicione o nome do cabeçalho personalizado e o valor personalizado (o nome e o valor personalizados do cabeçalho devem ser os mesmos do Web.Config). Você pode encontrar no blog
Vinit
fonte
0

Só para adicionar, vejo nos comentários 2 pessoas falando sobre 500 erros quando você faz isso. Eu tive isso.

Se você receber um erro 500 no IIS, talvez seja porque você adicionou a regra no nível superior, definido como herdado e no nível do site.

por exemplo

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

IIS / O Navegador não parece fornecer nenhuma informação que você tenha feito, independentemente das suas configurações de tratamento de erros

Tony
fonte