Mantente protegido

Las extensiones tienen acceso a privilegios especiales dentro del navegador, lo que las convierte en un blanco atractivo para los atacantes. Si se vulnera una extensión, todos sus usuarios se vuelven vulnerables a intrusiones maliciosas y no deseadas. Incorpora estas prácticas para proteger una extensión y a sus usuarios.

Protege las cuentas de desarrollador

El código de extensión se sube y se actualiza a través de Cuentas de Google. Si las cuentas de los desarrolladores están comprometidas, un atacante podría enviar código malicioso directamente a todos los usuarios. Para proteger estas cuentas, crea específicamente cuentas de desarrollador y habilita la autenticación de dos factores, de preferencia con una llave de seguridad .

Los grupos deben ser selectivos

Si usas la publicación de grupos, mantén el grupo restringido a desarrolladores de confianza. No aceptes solicitudes de membresía de personas desconocidas.

Nunca uses HTTP

Cuando solicites o envíes datos, evita las conexiones HTTP. Supongamos que cualquier conexión HTTP tendrá espías o contendrá modificaciones. Siempre se debe preferir HTTPS, ya que cuenta con seguridad integrada que elude la mayoría de los ataques de intermediarios.

Solicita permisos mínimos

El navegador Chrome limita el acceso de una extensión a los privilegios que se solicitaron de forma explícita en el manifiesto. Las extensiones deben minimizar sus permisos. Para ello, solo deben registrar las APIs y los sitios web de los que dependen. El código arbitrario debe reducirse al mínimo.

Limitar los privilegios de una extensión limita lo que un posible atacante puede explotar.

XMLHttpRequest de origen cruzado

Una extensión solo puede usar XMLHttpRequest para obtener recursos de sí misma y de los dominios especificados en los permisos.

{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
  "permissions": [
    "/*",
    "https://*.google.com/"
  ],
  "manifest_version": 2
}

Esta extensión solicita acceso a todo el contenido de developer.chrome.com y los subdominios de Google e indica "/*" y "https://*google.com/" en los permisos. Si se vulnerara la extensión, solo tendría permiso para interactuar con los sitios web que cumplan con el patrón de coincidencia. El atacante no podría acceder a "https://user_bank_info.com" ni interactuar con "https://malicious_website.com".

Limita los campos del manifiesto

La inclusión de registros innecesarios en el manifiesto crea vulnerabilidades y hace que una extensión sea más visible. Limita los campos de manifiesto a aquellos en los que se basa la extensión y otorga un registro de campos específicos.

Se pueden conectar de forma externa

Usa el campo externally_connectable para declarar con qué extensiones externas y páginas web la extensión intercambiará información. Restringe con quién puede conectarse la extensión de forma externa a fuentes de confianza.

{
  "name": "Super Safe Extension",
  "externally_connectable": {
    "ids": [
      "iamafriendlyextensionhereisdatas"
    ],
    "matches": [
      "/*",
      "https://*google.com/"
    ],
    "accepts_tls_channel_id": false
  },
  ...
}

Recursos accesibles desde la Web

Hacer que los recursos sean accesibles para la Web, en el web_accessible_resources, hará que los sitios web y los atacantes puedan detectar una extensión.

{
  ...
  "web_accessible_resources": [
    "images/*.png",
    "style/secure_extension.css",
    "script/secure_extension.js"
  ],
  ...
}

Cuantos más recursos accesibles desde la Web estén disponibles, más vías puede explotar un posible atacante. Mantén estos archivos al mínimo.

Incluir una política de seguridad del contenido explícita

Incluye una política de seguridad de contenido para la extensión en el manifiesto a fin de evitar ataques de secuencias de comandos entre sitios. Si la extensión solo carga recursos desde sí misma, registra lo siguiente:

{
  "name": "Very Secure Extension",
  "version": "1.0",
  "description": "Example of a Secure Extension",
  "content_security_policy": "default-src 'self'"
  "manifest_version": 2
}

Si la extensión necesita incluir secuencias de comandos de hosts específicos, se pueden incluir:

{
  "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
}

Evita las APIs ejecutables

Las APIs que ejecutan código deben reemplazarse por alternativas más seguras.

interiorHTML y document.write()

Si bien puede ser más sencillo crear elementos HTML de forma dinámica con document.write() y innerHTML, la extensión y las páginas web de las que depende quedan abiertas a los atacantes que insertan secuencias de comandos maliciosas. En su lugar, crea manualmente nodos del DOM y usa innerText para insertar contenido dinámico.

function constructDOM() {
  let newTitle = document.createElement('h1');
  newTitle.innerText = host;
  document.appendChild(newTitle);
}

eval()

Siempre que sea posible, evita usar eval() para evitar ataques, ya que eval() ejecutará cualquier código que se le pase, que puede 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();

En cambio, elige métodos más seguros y 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();

Usa las secuencias de comandos del contenido con cuidado

Si bien las secuencias de comandos de contenido viven en un mundo aislado, no están inmunes a los ataques:

  • Las secuencias de comandos de contenido son la única parte de una extensión que interactúa directamente con la página web. Debido a esto, las páginas web hostiles pueden manipular partes del DOM del que depende la secuencia de comandos del contenido o explotar comportamientos estándares sorprendentes, como los elementos con nombre.
  • Para interactuar con el DOM de las páginas web, las secuencias de comandos de contenido deben ejecutarse en el mismo proceso del renderizador que la página web. Esto hace que las secuencias de comandos de contenido sean vulnerables a la filtración de datos a través de ataques de canales secundarios (p.ej., Spectre), y que se tome el control de un atacante si una página web maliciosa pone en riesgo el proceso del procesador.

El trabajo sensible debe realizarse en un proceso dedicado, como la secuencia de comandos en segundo plano de la extensión. Evita exponer por accidente los privilegios de extensión a las secuencias de comandos del contenido:

  • Supongamos que un atacante podría haber creado mensajes de una secuencia de comandos de contenido (p.ej., valida y limpia todas las entradas y protege tus secuencias de comandos de secuencias de comandos entre sitios).
  • Supongamos que cualquier dato enviado a la secuencia de comandos del contenido se pueda filtrar a la página web. No envíes datos sensibles (p.ej., secretos de la extensión, datos de otros orígenes web o historiales de navegación) a secuencias de comandos de contenido.
  • Limita el alcance de las acciones con privilegios que pueden activar las secuencias de comandos de contenido. No permitas que las secuencias de comandos de contenido activen solicitudes a URLs arbitrarias ni pasen argumentos arbitrarios a las APIs de extensión (p.ej., no permites pasar URLs arbitrarias a la API de fetch o chrome.tabs.create).

Registra y limpia las entradas

Para proteger una extensión de secuencias de comandos maliciosas, limita los objetos de escucha solo a lo que la extensión espera, valida los remitentes de datos entrantes y limpia todas las entradas.

Una extensión solo debe registrarse para runtime.onRequestExternal si espera la comunicación desde un sitio web o una extensión externos. Verifica siempre que el remitente coincida con una fuente de confianza.

// The ID of an external extension
const kFriendlyExtensionId = "iamafriendlyextensionhereisdatas";

chrome.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) {
    if (sender.id === kFriendlyExtensionId)
      doSomething();
});

Incluso los mensajes a través del evento runtime.onMessage desde la propia extensión deben analizarse para garantizar que MessageSender no sea de una secuencia de comandos de contenido comprometida.

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.allowedAction)
    console.log("This is an allowed action.");
});

Evita que una extensión ejecute la secuencia de comandos de un atacante depurando las entradas del usuario y los datos entrantes, incluso de la extensión en sí y de las fuentes aprobadas. Evita las APIs ejecutables.

function sanitizeInput(input) {
    return input.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
}