Exponer las secure cookies con una extensión DIY

freishner

Capo
Se incorporó
16 Noviembre 2021
Mensajes
297
Nota:
Comprensión lectora de Inglés intermedia es requerida para los enlaces a la documentación.

1677440685902.png



¿Qué es una secure cookie?

Es una cookie que tiene el flag HttpOnly activo. La cookie está limitada a un alcance seguro, por lo que el browser limita la cookie al uso de peticiones HTTP seguras, es decir HTTPS.

¿De qué nos sirven las secure cookies?

Nos permiten el acceso a recursos. Nada fuera de lo usual, salvo que en las apps modernas, todas las cookies que son importantes para ingresar a recursos restringidos, tienden a ser secure cookies.

¿Cómo las exponemos?

Vamos a desarrollar una extensión para un navegador en concreto, en mi caso como uso chromium, vamos a darle con éste. Las extensiones tiene acceso a la instancia de javascript que tiene permisos para leer las secure cookies usando el cookies api. Cuando nuestro script detecte la url de interés, haremos lo que queramos hacer con la/s secure cookie/s.

Brief sobre las extensiones
Una extensión es un componente WEB que tiene acceso al backoffice programable del navegador (por decirlo de una forma simple). Corren sobre una instancia de Javascript mas permisiva que la instancia que se expone a una página web.

Los mercados como la chrome store, implementan verificaciones en donde se comprueba malware, servicios de pago, harvesting, etc. En el caso de usuarios mal intencionados se aplica un ban a la cuenta de Google (que hoy en día es un bien preciado).

Composición

No difieren mucho a una app web javascript. Salvo por el archivo manifest. De éste tenemos 3 versiones, siendo las 2 últimas usadas, con una advertencia de descontinuado para la 2da. Actualmente esta vigente el manifest v3.

Funcionalidades

Entre las posibilidades de las extensiones tenemos las siguientes (aquí se entienden las restricciones del store por parte de Google):
  • Acceso al DOM del sitio.
  • Manipular el navegador (redirecciones, abrir y cerrar pestañas, comunicación con otras extensiones, peticiones CORS, etc).
  • Service Workers en background.
  • Inyección de recursos varios.
  • Ejecución de código en una instancia mas permisiva a la que tiene acceso el sitio, pero con libre acceso al DOM.
Construcción

Empezamos creando un directorio como éste:
Código:
carpeta/
- manifest.json
- background.js
- script.js

Nuestro manifest debería verse así:
JSON:
{
  "manifest_version": 3,
  "name": "Nueva Extensión",
  "description": "...",
  "version": "1",
  "permissions": [
    "activeTab",
    "cookies",
    "scripting"
  ],
  "host_permissions": [
    "https://*.dominio.com/"
  ],
  "background": {
    "service_worker": "background.js",
    "type": "module"
  },
  "content_scripts": [
    {
        "js": ["script.js"],
        "matches": [
            "https://*.dominio.com/*"
        ]
    }
  ]
}

Permisos de Host: La extensión necesita ejecutarse en dominios, para el ejemplo, vamos a usar dominio.com. De ésta forma, si la intentamos ejecutar en google.com, no funcionará.
Permisos: Vamos a ocupar permisos para ejecutar content_script, leer la tab activa, y usar el cookies api.
Background: Es un service worker que se ejecutará en 2do plano.
Content Script: Es el archivo que tiene una instancia de javascript mas permisiva y acceso al DOM.

Funcionamiento
Nuestro lector de cookies se compone de dos partes fundamentales, el service worker y el content script. El primero maneja el backoffice del browser y el segundo detecta cuando nos encontramos en el sitio víctima comparando su url con la que le entregamos.

Una vez que tenemos cargado el sitio víctima, el content script se comunica con el service worker y le pide que lea para el una cookie en específico (podríamos leerlas/borrarlas todas).

Finalmente la cookie está expuesta.

La comunicación está descrita acá.

Configurar el content script
El content script tiene que accesar a un dominio o a una página en específico, eso se especifica en el parámetro matches, en el que se pueden usar comodines como lo hice yo.

El content script (script.js)

Éste archivo se ejecutará siempre que se cargue un sitio web, tendrá acceso al DOM, pero tambien podrá comunicarse con la extensión, recordar que tanto la página como la extensión se están ejecutando en instancias de javascript separadas por razones de seguridad.

JavaScript:
function leer_secure_cookie() {
    // Cuando tenemos la url requerida, pasamos a exponer la secure cookie.
    if (document.location.href == 'https://dominio.com') {
        // Le pedimos al service worker que nos lea la cookie y nos la devuelva.
        // El objeto que recibe sendMessage, es serializado y deserializado en el service worker.
        chrome.runtime.sendMessage(
            {
                exec: 'leer-cookie',
                p1: 'cookie-nombre',
                p2: document.location.href
            },
            // Éste callback es llamado cuando dentro del service worker, llamamos a sendResponse.
            // cookie llega deserializado.
            (cookie) => {
                // Secure cookie expuesta
                console.log(cookie);
            }
        );
    // Si no encontramos nada, programamos la ejecución para observar dentro de 500ms mas.
    } else {
        setTimeout(leer_secure_cookie, 500);
    }
}

leer_secure_cookie();

Luego en el service worker leemos el mensaje, leemos la cookie y respondemos con su contenido al content script.

Service Worker (background.js)

JavaScript:
// La función que lee la cookie con el cookie api.
let leer_cookie = async (name, url) => {
    try {
        return await chrome.cookies.get({ "name": name, "url": url });
    } catch(err) { return undefined; }
}

// Agregamos un listener a onMessage para recibir la comunicación del content script.
chrome.runtime.onMessage.addListener(
    // request es deserializado automáticamente para nosotros
    (request, sender, sendResponse) => {
        // Leemos el parametro exec y entramos dentro del switch.
        switch (request.exec) {
            case 'leer-cookie':
                // Una vez dentro de la acción requerida, procedemos a leer la cookie
                // usando los parametros p1 y p2 (nombre de la cookie y url respectivamente).
                ext.getCookie(request.p1, request.p2)
                // Luego, respondemos el valor de la cookie al content script.
                // El objeto es serializado y deserializado en el content script.
                    .then(cookie => sendResponse(cookie));
                break;
        }
        
        // Por último le indicamos a onMessage que vamos a ejecutar sendResponse
        // de manera asincrónica devolviendo true.
        return true;
    }
);

Instalación de la extensión desempaquetada.

Ahora tenemos que probar todo en el browser. El procedimiento está cubierto acá.

La cookie expuesta

Finalmente cuando nuestro sitio víctima es cargado, la cookie ya es nuestra.

1677444629536.png
 
Subir