As extensões têm acesso a privilégios especiais no navegador, o que as torna um alvo atraente para invasores. Se uma extensão for comprometida, todos os usuários dela ficarão vulneráveis a intrusões maliciosas e indesejadas. Mantenha uma extensão segura e os usuários protegidos incorporando estas práticas.
Proteger contas de desenvolvedor
O código da extensão é enviado e atualizado pelas Contas do Google. Se as contas dos desenvolvedores forem comprometidas, um invasor poderá enviar código malicioso diretamente a todos os usuários. Proteja essas contas by criando contas de desenvolvedor específicas e ativando a autenticação de dois fatores , de preferência com uma chave de segurança .
Manter grupos seletivos
Se você estiver usando a publicação em grupos, mantenha o grupo confinado a desenvolvedores confiáveis. Não aceite solicitações de participação de pessoas desconhecidas.
Nunca usar HTTP
Ao solicitar ou enviar dados, evite uma conexão HTTP. Suponha que todas as conexões HTTP tenham ouvintes ou contenham modificações. O HTTPS sempre deve ser preferido, porque tem segurança integrada que evita a maioria dos ataques "man-in-the-middle".
Solicitar permissões mínimas
O navegador Chrome limita o acesso de uma extensão a privilégios que foram explicitamente solicitados em o manifesto. As extensões precisam minimizar as permissões registrando apenas as APIs e os sites de que dependem. O código arbitrário precisa ser mantido no mínimo.
Limitar os privilégios de uma extensão limita o que um possível invasor pode explorar.
XMLHttpRequest de origem cruzada
Uma extensão só pode usar XMLHttpRequest para receber recursos dela mesma e de domínios especificados nas permissões.
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"permissions": [
"/*",
"https://*.google.com/"
],
"manifest_version": 2
}
Essa extensão solicita acesso a tudo em developer.chrome.com e subdomínios do Google listando "/*" e "https://*google.com/" nas permissões. Se a
extensão fosse comprometida, ela ainda teria permissão para interagir apenas com sites que atendam
ao padrão de correspondência. O invasor não conseguiria acessar "https://user_bank_info.com" ou
interagir com "https://malicious_website.com".
Limitar campos de manifesto
Incluir registros desnecessários no manifesto cria vulnerabilidades e torna uma extensão mais visível. Limite os campos de manifesto àqueles em que a extensão se baseia e forneça um registro de campo específico.
Conectável externamente
Use o campo externally_connectable para declarar quais extensões e páginas da Web externas a
extensão vai trocar informações. Restrinja quem a extensão pode se conectar externamente a fontes confiáveis.
{
"name": "Super Safe Extension",
"externally_connectable": {
"ids": [
"iamafriendlyextensionhereisdatas"
],
"matches": [
"/*",
"https://*google.com/"
],
"accepts_tls_channel_id": false
},
...
}
Recursos acessíveis pela Web
Tornar os recursos acessíveis pela Web, em web_accessible_resources, fará com que uma
extensão seja detectável por sites e invasores.
{
...
"web_accessible_resources": [
"images/*.png",
"style/secure_extension.css",
"script/secure_extension.js"
],
...
}
Quanto mais recursos acessíveis pela Web estiverem disponíveis, mais caminhos um possível invasor poderá explorar. Mantenha esses arquivos no mínimo.
Incluir uma política de segurança de conteúdo explícita
Inclua uma política de segurança de conteúdo para a extensão no manifesto para evitar ataques de script entre sites. Se a extensão carregar apenas recursos dela mesma, registre o seguinte:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": "default-src 'self'"
"manifest_version": 2
}
Se a extensão precisar incluir scripts de hosts específicos, eles poderão ser incluídos:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": "default-src 'self' https://extension.resource.com"
"manifest_version": 2
}
Evitar APIs executáveis
As APIs que executam código precisam ser substituídas por alternativas mais seguras.
document.write() e innerHTML
Embora seja mais simples criar elementos HTML dinamicamente com document.write() e innerHTML, isso deixa a extensão e as páginas da Web de que ela depende abertas para invasores que inserem scripts maliciosos. Em vez disso, crie nós DOM manualmente e use innerText para inserir conteúdo dinâmico.
function constructDOM() {
let newTitle = document.createElement('h1');
newTitle.innerText = host;
document.appendChild(newTitle);
}
eval()
Evite usar eval() sempre que possível para evitar ataques, já que eval() vai executar qualquer código transmitido a ele, que pode ser malicioso.
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// WARNING! Might be evaluating an evil script!
var resp = eval("(" + xhr.responseText + ")");
...
}
}
xhr.send();
Em vez disso, prefira métodos mais seguros e rápidos, como JSON.parse().
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.example.com/data.json", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// JSON.parse does not evaluate the attacker's scripts.
var resp = JSON.parse(xhr.responseText);
}
}
xhr.send();
Usar scripts de conteúdo com cuidado
Embora os scripts de conteúdo vivam em um mundo isolado, eles não estão imunes a ataques:
- Os scripts de conteúdo são a única parte de uma extensão que interage diretamente com a página da Web. Por isso, páginas da Web hostis podem manipular partes do DOM de que o script de conteúdo depende, ou explorar um comportamento surpreendente do padrão da Web, como itens nomeados.
- Para interagir com o DOM de páginas da Web, os scripts de conteúdo precisam ser executados no mesmo processo de renderização da página da Web. Isso torna os scripts de conteúdo vulneráveis ao vazamento de dados por ataques de canal lateral (por exemplo, Spectre) e a serem acessados indevidamente por um invasor se uma página da Web mal-intencionada comprometer o processo de renderização.
O trabalho sensível precisa ser realizado em um processo dedicado, como o script de segundo plano da extensão. Evite expor acidentalmente privilégios de extensão a scripts de conteúdo:
- Suponha que as mensagens de um script de conteúdo possam ter sido criadas por um invasor (por exemplo, valide e limpe todas as entradas e proteja seus scripts contra scripting em vários sites).
- Suponha que todos os dados enviados ao script de conteúdo possam vazar para a página da Web. Não envie dados sensíveis (por exemplo, segredos da extensão, dados de outras origens da Web, histórico de navegação) para scripts de conteúdo.
- Limite o escopo das ações privilegiadas que podem ser acionadas por scripts de conteúdo. Não permita que
scripts de conteúdo acionem solicitações para URLs arbitrários ou transmitam argumentos arbitrários para
APIs de extensão (por exemplo, não permita a transmissão de URLs arbitrários para
fetchouchrome.tabs.createAPI).
Registrar e limpar entradas
Proteja uma extensão contra scripts maliciosos limitando os listeners apenas ao que a extensão espera, validando os remetentes de dados recebidos e limpando todas as entradas.
Uma extensão só precisa se registrar para runtime.onRequestExternal se estiver esperando
comunicação de um site ou extensão externa. Sempre valide se o remetente corresponde a uma fonte confiável.
// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (sender.id === kFriendlyExtensionId)
doSomething();
});
Mesmo as mensagens pelo evento runtime.onMessage da própria extensão precisam ser analisadas para garantir que o MessageSender não seja de um script de conteúdo comprometido.
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.allowedAction)
console.log("This is an allowed action.");
});
Evite que uma extensão execute o script de um invasor limpando as entradas do usuário e os dados recebidos, mesmo da própria extensão e de fontes aprovadas. Evitar APIs executáveis.
function sanitizeInput(input) {
return input.replace(/&/g, '&').replace(/</g, '<').replace(/"/g, '"');
}