Recomendações HSTS em .htaccess

Oct 18 2020

Por favor, veja meu post anterior no hiperlink abaixo

Atualizei meu .htaccessarquivo para contabilizar um HSTS, junto com muitas das alterações recomendadas. Veja o snippet abaixo. Gostaria de enfatizar que implementar um HSTS não deve ser considerado levianamente por ninguém novo nele. Dito isso, procuro conselhos sobre o que pode ser feito de forma diferente de quem tem conhecimento .htaccess.

#IMPLEMENT HSTS
<IfModule mod_headers.c>
Header set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
</IfModule>

#CUSTOM ERROR PAGES
ErrorDocument 400 /allerror.php
ErrorDocument 401 /allerror.php
ErrorDocument 403 /allerror.php
ErrorDocument 404 /allerror.php
ErrorDocument 405 /allerror.php
ErrorDocument 408 /allerror.php
ErrorDocument 500 /allerror.php
ErrorDocument 502 /allerror.php
ErrorDocument 504 /allerror.php

RewriteEngine On

#REDIRECT TO SECURE HTTPS CONNECTION
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] #FORCE WWW TO NON-WWW RewriteCond %{HTTP_HOST} ^www.example.com [NC] RewriteRule ^(.*)$ https://example.com/$1 [L,R=301] #URL EXTENSION REMOVAL RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC] RewriteRule ^ /%1 [NC,L,R] RewriteCond %{REQUEST_FILENAME}.html -f RewriteRule ^ %{REQUEST_URI}.html [NC,L] #HOTLINKING PROTECTION RewriteCond %{HTTP_REFERER} !^https://(www\.)?example\.com(/.*)*$ [NC]
RewriteCond %{HTTP_REFERER} !^$ RewriteRule \.(css|flv|gif|ico|jpe|jpeg|jpg|js|mp3|mp4|php|png|pdf|swf|txt)$ - [F]

#CONTENT SECURITY POLICY
<FilesMatch "\.(html|php)$"> Header set Content-Security-Policy "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data: 'unsafe-inline'; media-src 'self' data: 'unsafe-inline'; connect-src 'self';" </FilesMatch> #REDIRECT FOR DATE PAGE RewriteRule ^date$ /storage/date-202010 [R=301,L]

#REDIRECT FOR HOME PAGE
RewriteRule ^home$ / [R=301,L] #PREVENT DIRECTORY BROWSING Options All -Indexes #FILE CACHING #cache html and htm files for one day <FilesMatch "\.(html|htm)$">
Header set Cache-Control "max-age=43200"
</FilesMatch>
    #cache css, javascript and text files for one week
<FilesMatch "\.(js|css|txt)$"> Header set Cache-Control "max-age=604800" </FilesMatch> #cache flash and images for one month <FilesMatch "\.(flv|swf|ico|gif|jpg|jpeg|mp4|png)$">
Header set Cache-Control "max-age=2592000"
</FilesMatch>
    #disable cache for script files
<FilesMatch "\.(pl|php|cgi|spl|scgi|fcgi)$"> Header unset Cache-Control </FilesMatch> #BLOCKS FILE TYPES FOR USERS <FilesMatch "\.(ht[ap]|ini|log|sh|inc|bak)$">
Require all denied
</FilesMatch>

Implementação HSTS

Para observar algumas coisas que aprendi enquanto pesquisava HSTS:

  1. É necessário um certificado SSL
  2. Se seus sites estiverem disponíveis via HTTP, redirecione todas as solicitações para HTTPS com um Redirecionamento permanente 301.
  3. Inclua o seguinte em seu .htaccessarquivo: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload. A idade máxima deve ser de pelo menos 10886400 segundos ou 18 semanas. Vá para o valor de dois anos.
  4. Adicione seu domínio a uma lista pré-carregada usando o primeiro link abaixo.

Recomendo a todos que leiam cada fonte abaixo para obter mais informações.

  • Envio da lista de pré-carga HSTS
  • O que é HSTS e por que devo usá-lo? | Acunetix
  • O que é HSTS e devo implementá-lo? | Dinâmica de Rede
  • Por que os sites devem usar HSTS para melhorar a segurança e o SEO

Respostas

3 MrWhite Oct 27 2020 at 23:09

Existem dois aspectos para HTTP Strict Transport Security (HSTS):

  1. Implementando HSTS em seu site.
  2. Enviando seu site já habilitado para HSTS para a lista de pré-carregamento de HSTS . É aqui que a "lista de sites HSTS" é compilada diretamente no navegador, o que evita que a primeira solicitação seja feita por HTTP (onde a solicitação é potencialmente vulnerável a ataques MITM).

Você parece estar indo direto para o # 2. Isso não é necessariamente recomendado. Pense na "lista de pré-carga" como uma viagem só de ida. Tecnicamente, é possível ser removido da lista de pré-carregamento; realisticamente, isso não é algo que você queira nem mesmo estar pensando. (É difícil - lento - retroceder o suficiente do HSTS apenas.)

A própria página de envio de lista de pré-carregamento não recomenda ir direto para "envio de lista de pré-carregamento". A recomendação é aumentar o max-ageparâmetro ao longo de um período de tempo (meses), antes de dar a última etapa de envio para a lista de pré-carregamento. Nesse ínterim, teste o teste de teste para garantir que os certificados SSL sejam renovados de forma confiável, sem avisos de conteúdo misto etc. etc.

Eu também desconfiaria do envio da lista de pré-carregamento do HSTS (ou até mesmo do próprio HSTS em algum grau) em um servidor compartilhado , onde você não tem controle total sobre a configuração SSL. Na verdade, você não declara se está em um servidor compartilhado ou não, mas como está fazendo toda essa configuração .htaccess, presumo que esteja. Se você tiver seu próprio servidor e acesso à configuração do servidor, a maior parte disso deve ser configurado na configuração do servidor / virtualhost (e é indiscutivelmente mais fácil e confiável de fazer).

Lembre-se de que, depois de seguir a rota HSTS (e os usuários acessarem o site HTTPS ou você estiver na "lista de pré-carregamento"), seu site poderá ser acessado por HTTPS. Isso não se aplica apenas ao seu site, mas também a quaisquer serviços de terceiros que você possa estar usando (avisos do navegador de conteúdo misto, etc.).

#IMPLEMENT HSTS
<IfModule mod_headers.c>
Header set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
</IfModule>

Isso define o cabeçalho de resposta HTTP HSTS necessário na "maioria" das respostas * 1 (mas observe o preloadparâmetro, que provavelmente deve ser omitido inicialmente).

* 1 No entanto, esta diretiva não define necessariamente o cabeçalho necessário em todas as respostas. Um requisito do HSTS é que você também defina o cabeçalho nas respostas de "redirecionamento" (por exemplo, www para não www em HTTPS). Atualmente, o acima não faz isso. Você deve usar aalways condição naHeaderdiretiva para definir o cabeçalho nas respostas diferentes de 200 OK. Por exemplo:

# Use "always" condition to set on "redirects" as well.
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"

(Eu também removi o preloadparâmetro por enquanto).

Você não precisa do <IfModule>invólucro e deve ser removido. mod_headers deve ser habilitado por padrão. Este é o seu servidor, você sabe se mod_headers está habilitado ou não. mod_headers deve ser habilitado para que isso funcione. Você não quer que isso falhe silenciosamente caso o mod_headers não esteja disponível - você precisa de uma notificação assim que isso falhar com um erro em seus logs.

Muitos artigos afirmam que você deve definir o Strict-Transport-Securitycabeçalho em respostas seguras (HTTPS). E o "envio da lista de pré-carregamento" realmente emite um "aviso" (não estritamente um "erro", creio) se você enviar o cabeçalho por HTTP também. No entanto, embora ele só precise ser definido na resposta HTTPS, os navegadores compatíveis ignoram esse cabeçalho quando enviado por uma conexão HTTP não criptografada (para evitar ataques MITM), portanto, não importa se o cabeçalho é enviado "desnecessariamente" por HTTP também. Isso seria mais fácil de gerenciar nos <VirtualHost>contêineres apropriados na configuração do servidor principal. Enviar esse cabeçalho apenas em respostas HTTPS .htaccessé mais complexo (e, portanto, mais sujeito a erros). Você precisaria empregar uma variável de ambiente adicional que pode ser usada para definir o cabeçalho de resposta HSTS condicionalmente.

Por exemplo:

# Set environment var "HSTS" if accessed over HTTPS connection
RewriteCond %{HTTPS} on
RewriteRule ^ - [E=HSTS:1]

# Conditionally set only on HTTPS connections (ie. when "HSTS" env var is set)
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains" env=HSTS

Caso contrário, acredito que suas diretivas restantes estão OK com relação ao HSTS. Mas, como sempre, teste teste teste.


Resolva vários redirecionamentos (desnecessários)

#FORCE WWW TO NON-WWW
RewriteCond %{HTTP_HOST} ^www.example.com [NC]
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]

#URL EXTENSION REMOVAL
RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC]
RewriteRule ^ /%1 [NC,L,R]

Um problema potencial aqui (com o segundo e terceiro redirecionamentos canônicos acima, após o redirecionamento de HTTP para HTTPS) é que isso pode resultar em dois redirecionamentos adicionais se www+ .htmlfor solicitado. Isso pode ser resolvido simplesmente revertendo os dois redirecionamentos e incluindo o nome do host canônico no redirecionamento "REMOÇÃO DE EXTENSÃO DE URL" (conforme mencionado em minha resposta à sua pergunta anterior ).

Por exemplo:

#URL EXTENSION REMOVAL
RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC]
RewriteRule ^ https://example.com/%1 [R=301,L]

#FORCE WWW TO NON-WWW
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule (.*) https://example.com/$1 [R=301,L]

Veja minha resposta anterior para uma abordagem alternativa para o redirecionamento "REMOÇÃO DE EXTENSÃO DE URL" que aborda alguns problemas potenciais.

Se você não estiver usando o wwwsubdomínio em outros nomes de host (por exemplo. www.subdomain.example.com), Poderá simplificar o CondPattern no redirecionamento www para não-www para simplesmente ^www\., ie. qualquer nome de host solicitado que simplesmente inicia www., em vez de verificar o nome de host inteiro.


Correções Adicionais

Loop de remoção / reescrita de extensão de URL (500 erro interno do servidor)

Há alguns outros problemas que não resolvi abordar em sua pergunta anterior , não relacionados ao HSTS, que abordarei a seguir ...

#URL EXTENSION REMOVAL
:
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [NC,L]

Este (e similar) é um daqueles trechos de código que são copiados / colados "cegamente" em todos os lugares (e quero dizer em todos os lugares ) como a maneira "padrão" de anexar (reescrever URL) a extensão de arquivo ao usar URLs sem extensão. No entanto, embora provavelmente "funcione" para os seus URLs válidos, tem uma falha grave ao solicitar URLs inválidos ...

Se /about.htmlfor um arquivo válido que você deseja veicular ao solicitar o URL sem extensão /about, ele funciona bem. No entanto, se eu (maliciosamente) solicitar /about/ou /about/<anything>ele enviará seu servidor em um loop de reescrita em espiral, resultando em uma resposta de 500 Erro interno do servidor. O usuário final não deve ser capaz de invocar tal resposta (potencialmente mais vulnerável a ataques DDOS e outros comportamentos hostis).

Isso ocorre porque REQUEST_FILENAME(o caminho do sistema de arquivos mapeado) não se refere necessariamente ao mesmo caminho de URL público que a REQUEST_URIvariável (caminho de URL solicitado).

Para resolver isso, use REQUEST_URItodo. Por exemplo:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.html -f
RewriteRule ^ %{REQUEST_URI}.html [L]

(O NCsinalizador é supérfluo na RewriteRulediretiva aqui.)

Veja minha resposta à seguinte pergunta sobre ServerFault para obter mais detalhes sobre isso.

Proteção Hotlink - Simplifique a Condição

#HOTLINKING PROTECTION
RewriteCond %{HTTP_REFERER} !^https://(www\.)?example\.com(/.*)*$ [NC]

Isso é relativamente pequeno. A regex na condição acima pode ser simplificada. Neste ponto do .htaccessarquivo, o nome do host já foi canonizado para remover o www do subdomínio, portanto, o (www\.)?subpadrão acima é supérfluo. Assim como o (/.*)*$subpadrão final , que simplesmente corresponde a todo o resto. Você não precisa realmente corresponder a nada aqui, você só precisa afirmar que o Referercabeçalho começa com o nome de host apropriado (esquema +).

Por exemplo:

RewriteCond %{HTTP_REFERER} !^https://example\.com

A NCbandeira também é supérflua aqui. Forçar uma correspondência que não diferencia maiúsculas de minúsculas quando não é necessária apenas cria (um pouquinho) mais trabalho para o seu servidor e, em alguns casos, pode abrir você para vulnerabilidades ("conteúdo duplicado" é comum - embora isso não seja um problema aqui) .

Ativando desnecessário Options

#PREVENT DIRECTORY BROWSING
Options All -Indexes

Isso não impede apenas a "navegação no diretório". O Allargumento habilita um monte de outras coisas que você provavelmente não precisa, como server-side includes ( Includes) e a habilidade de executar scripts CGI ( ExecCGI). (A propósito, este é o único momento em que você pode misturar argumentos com um +ou -sem.) Para evitar apenas a navegação no diretório (ou seja, a geração automática de índices de diretório por mod_autoindex), remova o Allargumento.

No entanto, você provavelmente só precisa FollowSymLinks (o que já pode estar definido na configuração do servidor), então você pode definir o seguinte:

Options FollowSymLinks

Observe a ausência de +ou -. Isso define FollowSymLinks, portanto, desabilitando Indexes("navegação no diretório") se já estiver definido.