- Para impedir ataques XSS, uma das principais vulnerabilidades da web, o Firefox passa a oferecer pela primeira vez suporte à Sanitizer API padronizada
- Ao usar o método
setHTML() no lugar do innerHTML tradicional, HTML não confiável é sanitizado automaticamente antes de ser inserido no DOM, removendo scripts maliciosos
- Se a configuração padrão for excessiva ou insuficiente, desenvolvedores podem controlar quais elementos e atributos serão permitidos por meio de configurações personalizadas
- Em combinação com Trusted Types, esse recurso do Firefox eleva o nível geral de segurança da web e permite que desenvolvedores previnam XSS mesmo sem uma equipe de segurança dedicada
Vulnerabilidade XSS e a resposta do Firefox
- Cross-site scripting (XSS) ocorre quando um invasor insere HTML ou JavaScript arbitrário por meio de conteúdo fornecido pelo usuário
- Com isso, o atacante pode monitorar interações do usuário ou roubar dados
- O XSS é classificado há quase 10 anos entre as três principais vulnerabilidades da web (CWE-79)
- Desde 2009, o Firefox vem fortalecendo a defesa contra XSS ao liderar o padrão Content-Security-Policy (CSP)
- O CSP restringe quais recursos um site pode carregar e executar
- No entanto, ele exige mudanças na estrutura de sites existentes e revisões contínuas de segurança, o que limitou sua adoção em larga escala
O papel da Sanitizer API e do setHTML()
- A Sanitizer API fornece uma forma padronizada de transformar HTML malicioso em conteúdo inofensivo
- No código de exemplo, o elemento
<img src="x" onclick="alert('XSS')"> é removido e apenas <h1>Hello my name is</h1> permanece
- O método
setHTML() executa automaticamente o processo de sanitização durante a inserção de HTML, garantindo um comportamento seguro por padrão
- Basta substituir atribuições com
innerHTML por setHTML() para obter uma forte proteção contra XSS
- Se a configuração padrão for rígida demais ou permissiva demais, desenvolvedores podem definir elementos e atributos HTML permitidos por meio de configuração personalizada
- Também é possível usar a ferramenta Sanitizer API playground para experimentação
Integração com Trusted Types
- A Trusted Types API fornece uma camada adicional de segurança ao centralizar o controle da análise e inserção de HTML
- Ao usar
setHTML(), é fácil aplicar políticas de Trusted Types
- Políticas mais rígidas podem permitir apenas
setHTML() e bloquear outras formas arriscadas de inserção, ajudando a evitar regressões futuras de XSS
Efeitos de segurança no Firefox 148
- O Firefox 148 oferece suporte tanto à Sanitizer API quanto a Trusted Types, elevando significativamente o nível básico de segurança
- Desenvolvedores podem prevenir XSS com mudanças simples no código, sem depender de políticas complexas ou de uma equipe de segurança separada
- Espera-se que a adoção desse padrão contribua para expandir uma web mais segura em todos os navegadores
Resumo
- O Firefox 148 ajuda desenvolvedores web a bloquear ataques XSS com facilidade por meio do método
setHTML() e da Sanitizer API
- Esse recurso complementa as limitações do CSP e marca um passo importante para consolidar um modo seguro de inserção de HTML como padrão da web
- Em combinação com Trusted Types, ele permite manutenção de segurança de longo prazo e prevenção de regressões de XSS
- Como resultado, o Firefox está liderando a transição para uma web em que segurança é o padrão
2 comentários
Ah, com certeza algo assim é necessário. Vai ser muito bom se todos os navegadores passarem a oferecer suporte.
Comentários do Hacker News
Esse tipo de recurso sempre parece um pouco inquietante
porque existem métodos que lidam com entrada do usuário com segurança e outros que não, mas é difícil distinguir só pelo nome
Idealmente, funções perigosas deveriam deixar isso claro no nome desde o início
Além disso, a própria ideia de “sanitizar” HTML é ambígua, e é difícil saber se isso é realmente seguro
remove elementos e atributos capazes de executar scripts, e essa lógica roda dentro do engine do navegador, então trata isso com mais precisão do que sanitizadores baseados em string
Veja mais na documentação do MDN sobre setHTML
elementNode.textContenté seguro mesmo com entrada não confiável, enquantoelementNode.innerHTMLnão éo primeiro escapa todos os caracteres, e o segundo não escapa nada
Também há quem diga que “sanitização de HTML” é um problema fundamentalmente insolúvel
Veja este comentário para a discussão relacionada
APIs assim nem deveriam ter passado da fase de proposta
innerHTMLesetHTML, o projeto deveria ter removidoinnerHTMLpor completo e, para o comportamento antigo, usar algo comosetHTMLUnsafeinnerHTMLpor configuração globalembora isso possa fazer o site deixar de funcionar em navegadores antigos
Content-Security-Policy: require-trusted-types-for 'script', dá para bloquear a passagem de strings normais para métodos sem sanitizaçãoSe, como no exemplo, for possível inserir tags como
<h1>ou<br>no nome do usuário, então mesmo bloqueando a execução de scripts ainda é possível fazer injeção arbitrária de markupTambém seria possível alterar o CSS com uma tag
<style>, então, por exemplo, daria para mudar o visual de uma página de perfil do PayPalFica a dúvida de quem realmente desejaria isso
Dá para adicionar uma camada extra de defesa restringindo com um sanitizador o HTML gerado pelo Markdown, permitindo apenas certas tags
innerTextoutextContent, e nãoinnerHTMLsetHTMLé um substituto parainnerHTMLsetHTML()for rígida ou permissiva demais, o desenvolvedor pode fornecer uma configuração personalizada definindo quais elementos e atributos HTML serão permitidosVeja esta thread para a discussão relacionada
No fim, o backend ainda precisa sanitizar nomes de usuário da forma padrão, e na saída ainda é preciso aplicar escape de HTML
Segundo a RFC 2119, isso é um requisito de nível “SHOULD”
Fico feliz em ver esse recurso surgir, mas provavelmente vai levar tempo até que o suporte dos navegadores se espalhe o suficiente
Dá para verificar o suporte em Can I use
nesse meio-tempo, dá para usar um polyfill
O título foi um pouco chamativo demais
Na prática, também daria para implementar a sanitização com uma função que valida a entrada antes de passá-la para
innerHTMLSó que esse tipo de tentativa acaba parecendo reinvenção da roda
Além disso, em versões antigas do Firefox, o hacks.mozilla.org nem abre, e no Pale Moon ou SeaMonkey o MDN aparece quebrado
Parece até que um “cartel dos navegadores” quer estragar a web
É um argumento que nem considera o problema de diferenças entre parsers (parser differential)
Se a API Sanitizer for usada incorretamente, ela pode virar uma armadilha
Principalmente ao usar o modo “remove”
Eu preferiria usar só
setTexte não permitir que usuários adicionem HTML de forma algumasetHTML, não haverá XSSolhando para a frequência com que
innerHTMLé usado na prática, é difícil excluí-lo por completoÉ impressionante ver que todos os aspectos do acesso à rede agora são controlados corretamente, e que a cadeia de segurança passou de confiar no código para confiar na configuração do host
Os padrões também foram definidos com segurança
O que eu realmente quero é um elemento
<sandbox>que permita executar código perigoso com segurançaNão para corrigir código perigoso, mas para poder rodá-lo em um ambiente isolado
iframes têm a limitação de não fluir junto com o DOM, e numa era de IA e conteúdo dinâmico crescente, precisamos de encapsulamento componível
Gostei muito do nome
setHTMLUnsafeRecursos de segurança falham quando dependem de o desenvolvedor optar por usá-los
Em vez disso, é mais eficaz fazer com que “o caminho perigoso pareça perigoso”
O nome
set_html()parece bem mais intuitivo do queinner_htmlAs APIs de JavaScript são realmente uma bagunça e precisam ser organizadas algum dia
Aqui a discussão está centrada em segurança, mas ao lançar novas APIs o próprio design também deveria ser limpo
As APIs do DOM sempre deram, e ainda dão, a impressão de terem sido feitas por “pessoas que nunca criaram uma API”
Desenvolvedores dos anos 90:
Desenvolvedores dos anos 2020:
Não aprendemos nada com os anos 90