18
Integridade de sub-recursos (SRI)
SRI é uma especificação da W3C que permite aos desenvolvedores web garantir que os recursos hospedados em servidores de terceiros não foram adulterados. Seu uso é recomendado como boa prática, sempre que as bibliotecas são carregadas de uma fonte de terceiro.
O HTTPS garante que a conexão entre o navegador e o servidor seja segura. O próprio recurso ainda pode ser modificado no lado do servidor por um invasor para incluir conteúdo malicioso, mas ainda pode ser servido com um certificado válido. O SRI, por outro lado, garante que um recurso não mudou desde que o hash foi criado.
Quando a solicitação não está na mesma origem, o atributo crossorigin
deve estar presente para a verificação da integridade do arquivo. Sem este atributo, o navegador informará fail-open
, o que significa que carregará o recurso como se o atributo de integridade não tivesse sido definido, perdendo efetivamente toda a segurança que o SRI traz em primeiro lugar.
O crossorigin="anonymous"
resulta que nenhuma credencial é enviada ao site de origem que hospeda o conteúdo. No entanto, ele enviará um cabeçalho HTTP Origin
.Se o servidor negar a inclusão do recurso (por não definir o cabeçalho HTTP Access-Control-Allow-Origin
), o recurso não será usado pelo navegador.
Podemos instruir o navegador a verificar a integridade do conteúdo carregado externamente, incluindo o atributo integrity
nas tags <script>
ou <link>
. Este atributo conterá as versões codificadas em base64 dos hashes criptográficos que esperamos para esse ativo específico.
Exemplos:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js" integrity="sha256-ivk71nXhz9nsyFDoYoGf2sbjrR9ddh+XDkCcfZxjvcM=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" integrity="sha256-8EtRe6XWoFEEhWiaPkLawAD1FkD9cbmGgEy6F46uQqU=" crossorigin="anonymous">
Pode ser utilizado mais de um tipo de hashes, como por exemplo o hash SHA256 junto com o SHA512, deixando para o navegador selecionar qual algoritmo de hash é mais forte e compatível com a verificação de integridade.
Exemplos:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js" integrity="sha256-ivk71nXhz9nsyFDoYoGf2sbjrR9ddh+XDkCcfZxjvcM= sha512-7aMbXH03HUs6zO1R+pLyekF1FTF89Deq4JpHw6zIo2vbtaXnDw+/2C03Je30WFDd6MpSwg+aLW4Di46qzu488Q==" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" integrity="sha256-8EtRe6XWoFEEhWiaPkLawAD1FkD9cbmGgEy6F46uQqU= sha512-/5KWJw2mvMO2ZM5fndVxUQmpVPqaxZyYRTMrXtrprsyQ2zM0o0NMjU02I8ZJXeBP trmrPO4IAyCCRsydG0BJoQ==" crossorigin="anonymous">
Além disso, também é importante notar que podem ser especificados vários hashes do mesmo tipo, caso você precise que um conteúdo diferente seja servido para a solicitação.
Existem duas formas fáceis de criar os hashes dos seus objetos.
O SRI Hash Generator é uma ferramenta online que você pode usar para gerar hashes SRI.
Caso prefira gerar manualmente via linha de comando, é necessário utilizar o OpenSSL, com o seguinte comando:
cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A
Pode ser utilizado também com shasum usando o comando:
shasum -b -a 384 FILENAME.js | awk '{ print $1 }' | xxd -r -p | base64
- O pipe
xxd
pega a saída hexadecimalshasum
e a converte em binária- A etapa
awk
do pipe é necessária porque oshasum
vai passar o nome do arquivo hasheado em sua saídaxxd
. Isso pode ter consequências desastrosas se o nome do arquivo tiver caracteres hexadecimais válidos, porque oxxd
também decodificará isso e passará parabase64
.
No Windows, é possível criar uma ferramenta para geração dos hashes SRI com o seguinte código:
@echo off
set bits=384
openssl dgst -sha%bits% -binary %1% | openssl base64 -A > tmp
set /p a= < tmp
del tmp
echo sha%bits%-%a%
pause
Para usar o código:
- Salve esse código como sri-hash.bat na pasta SendTo do Windows em seu ambiente (C:\Users\USER\AppData\Roaming\Microsoft\Windows\SendTo).
- Clique com o botão direito em um arquivo no Explorer, selecione ‘Enviar Para’ e selecione
sri-hash
. Você verá o valor do integrity em uma caixa de comando. - Selecione o valor de
integrity
e clique com o botão direito para copiá-lo para a área de transferência. - Pressione qualquer tecla para fechar a caixa de comando.
O comando wget faz download do arquivo. A partir daí, o comando car produz o arquivo que é canalizado para o OpenSSL que irá executá-lo por meio do hash SHA256 e fornecer o resumo na forma binária. Isso é então canalizado para o OpenSSL novamente para codificar a saída em base64. A string resultante é o valor do atributo integrity
.
O 'crossorigin' instrui o navegador a fazer uma solicitação habilitada para CORS de forma ativa. O compartilhamento de recursos crossorigin
. Podem ser passador 2 valores para este atributo que são anonymous
e use-credentials
, a diferença entre eles é que o primeiro é usado porque é feito através de uma solicitação HTTP simples, sem envio de credenciais, ou seja, sem cookies, sem certificados e sem a autenticação básica do HTTP.
Os navegadores lidam com SRI fazendo o seguinte:
-
Quando um navegador encontra um elemento
<script>
ou<link>
com o atribuitointegrity
, antes de executar o script ou baixar a folha de estilos especificada, o navegador primeiro compara o script ou a folha de estilos ao valor do hash esperado fornecido pelointegrity
;Observação: para verificação de SRI de um recurso servido de uma origem diferente do documento no qual está incorporado, os navegadores também verificam o recurso usando CORS, para garantir que a origem que atende o recurso permite que ele seja compartilhado com a origem solicitante.
Se o script ou folha de estilo não corresponder ao valor associado de
integrity
o navegador deve se recusar a executar o script ou aplicar a folha de estilo e, em vez disso, deve retornar um erro de rede indicando que a busca desse script ou folha de estilo falhou.
Os seguintes navegadores desktop são compatíveis a partir das seguintes versões:
Chrome 45+, Edge, 17+, Firefox 43+, Opera, Safari 11.1+.
Os seguintes navegadores mobile são compatíveis a partir das seguintes versões:
WebView Android 45+, Chrome Android 45+, Firefox for Android 43+, Safari IOS 11.3+, Samsung Internet 5.0+.
O Internet Explorer não tem compatibilidade, e o Opera Android não se sabe se possui compatibilidade.
18