Las extensiones tienen acceso a privilegios especiales dentro del navegador, lo que las convierte en un objetivo atractivo para los atacantes. Si se vulnera una extensión, todos los usuarios de esa extensión se vuelven vulnerables a intrusiones maliciosas y no deseadas. Incorpora estas prácticas para mantener una extensión segura y proteger a sus usuarios.
Protege las cuentas de desarrollador
El código de extensión se sube y se actualiza mediante Cuentas de Google. Si las cuentas de los desarrolladores se vulneran, un atacante podría enviar código malicioso directamente a todos los usuarios. Para proteger estas cuentas, habilita la autenticación de dos factores, preferiblemente con una llave de seguridad.
Cómo mantener la selectividad de los grupos
Si usas la publicación de grupos, mantén el grupo limitado a desarrolladores de confianza. No aceptes solicitudes de membresía de personas desconocidas.
Nunca uses HTTP
Cuando solicites o envíes datos, evita una conexión HTTP. Supongamos que cualquier conexión HTTP tendrá escuchas o contendrá modificaciones. Siempre se debe preferir HTTPS, ya que tiene seguridad integrada que evita 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 manifest. Las extensiones deben minimizar sus permisos y solo registrar las APIs y los sitios web de los que dependen.
Limitar los privilegios de una extensión limita lo que un posible atacante puede aprovechar.
Recuperación() de origen cruzado
Una extensión solo puede usar fetch()
y XMLHttpRequest()
para obtener recursos de la extensión y de los dominios especificados en los permisos. Ten en cuenta que el controlador de recuperación en el trabajador de servicio intercepta las llamadas a ambos.
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"host_permissions": [
"https://developer.chrome.com/*",
"https://*.google.com/*"
],
"manifest_version": 3
}
Esta extensión del ejemplo anterior solicita acceso a todo lo que se encuentra en developer.chrome.com y los subdominios de Google, ya que enumera "https://developer.chrome.com/*"
y "https://*.google.com/*"
en los permisos. Si la extensión se viera comprometida, solo tendría permiso para interactuar con sitios web que cumplan con el patrón de coincidencia. El atacante solo tendría una capacidad limitada para acceder a "https://user_bank_info.com"
o interactuar con "https://malicious_website.com"
.
Limita los campos del manifiesto
Si incluyes claves y permisos innecesarios en el manifiesto, se crean vulnerabilidades y se hace que una extensión sea más visible. Limita los campos del manifiesto a los que la extensión utiliza.
Se puede conectar de forma externa
Usa el campo "externally_connectable"
para declarar con qué extensiones y páginas web externas
la extensión intercambiará información. Restringir 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://developer.chrome.com/*",
"https://*.google.com/*"
],
"accepts_tls_channel_id": false
},
...
}
Recursos accesibles a través de la Web
Si permites que la Web acceda a los recursos, en "web_accessible_resources"
, los sitios web y los atacantes podrán detectar la extensión.
{
...
"web_accessible_resources": [
{
"resources": [ "test1.png", "test2.png" ],
"matches": [ "https://web-accessible-resources-1.glitch.me/*" ]
}
]
...
}
Cuantos más recursos accesibles a la Web haya disponibles, más posibilidades tendrá un posible atacante de aprovecharse de ellos. Mantén estos archivos al mínimo.
Incluye una política de seguridad de contenido explícito
Incluye una política de seguridad de contenido para la extensión en el manifiesto para evitar ataques de secuencias de comandos entre sitios. Si la extensión solo carga recursos de sí misma, registra lo siguiente:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": {
"extension_pages": "default-src 'self'"
},
"manifest_version": 3
}
Si la extensión necesita usar el ensamblado web o aumentar las restricciones en las páginas en zona de pruebas, se pueden agregar los siguientes elementos:
{
"name": "Very Secure Extension",
"version": "1.0",
"description": "Example of a Secure Extension",
"content_security_policy": {
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';",
"sandboxed_pages":"script-src 'self' 'wasm-unsafe-eval'; object-src 'self';"
},
"manifest_version": 3
}
Evita document.write() y innerHTML
Si bien puede ser más sencillo crear elementos HTML de forma dinámica con document.write()
y innerHTML
, deja la extensión y las páginas web de las que depende la extensión abiertas a los atacantes que insertan secuencias de comandos maliciosas. En su lugar, crea nodos del DOM manualmente y usa innerText
para insertar contenido dinámico.
function constructDOM() {
let newTitle = document.createElement('h1');
newTitle.innerText = host;
document.appendChild(newTitle);
}
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 exentas de 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 de las que depende la secuencia de comandos del contenido o explotar comportamientos estándar de la Web 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 canal lateral (p.ej., Spectre) y a que un atacante se apodere de él si una página web maliciosa vulnera el proceso de renderización.
Las operaciones que usan datos sensibles (como la información privada de un usuario) o las APIs de Chrome con acceso a las funciones del navegador deben realizarse en el trabajador del servicio de las extensiones. Evita exponer accidentalmente los privilegios de la extensión a las secuencias de comandos de contenido:
- Supongamos que un atacante pudo 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 la secuencia de comandos entre sitios).
- Supongamos que los datos que se envían a la secuencia de comandos de contenido podrían filtrarse a la página web. No envíes datos sensibles (p.ej., secretos de la extensión, datos de otros orígenes web, historial de navegación) a las 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 permitas pasar URLs arbitrarias a los métodos
fetch()
ochrome.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 espera la extensión, valida a los remitentes de los datos entrantes y limpia todas las entradas.
Una extensión solo debe registrarse en runtime.onMessageExternal
si espera una comunicación de un sitio web o una extensión externos. Siempre verifica 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 de la extensión deben analizarse para garantizar que MessageSender no provenga 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.");
});