Integridade de sub-recursos (SRI)
Tags: frontend, security, sri, braziliandevs
Published: 2021-07-02 14:44:20

## O que é integridade de sub-recursos?
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.

### Qual a diferença entre SRI e HTTPS?
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.

### Por que incluir `crossorigin=”anonymous”`?
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.

## O Atributo de `integrity`
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.

## Ferramentas para gerar hashes SRI
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 hexadecimal `shasum `e a converte em binária
> - A etapa `awk` do pipe é necessária porque o `shasum` vai passar o nome do arquivo hasheado em sua saída `xxd`. Isso pode ter consequências desastrosas se o nome do arquivo tiver caracteres hexadecimais válidos, porque o `xxd` também decodificará isso e passará para `base64`.

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:
1. Salve esse código como sri-hash.bat na pasta SendTo do Windows em seu ambiente (C:\Users\USER\AppData\Roaming\Microsoft\Windows\SendTo).
2. 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.
3. Selecione o valor de `integrity` e clique com o botão direito para copiá-lo para a área de transferência.
4. 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`.

### Atributo `crossorigin`
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.

## Como os navegadores lidam com o SRI

Os navegadores lidam com SRI fazendo o seguinte:
1. Quando um navegador encontra um elemento `<script>` ou `<link>` com o atribuito `integrity`, 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 pelo `integrity`;
> 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.

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

### Navegadores compatíveis

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.