Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Herramientas/GitHubGitHub/novaek/cve-2026-0073-research
Análisis de VulnerabilidadesExplotaciónIngeniería InversaSeguridad WebAnálisis de Binarios
GitHubnovaek/cve-2026-0073-research

CVE-2026-0073-Research

CVE-2026-0073 es una RCE con una puntuación de severidad CVSS de 8.3, y aquí explicaremos cómo funciona.

Ver Repositorio
51hace 3 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-0073-Research

CVE-2026-0073 es un RCE con una puntuación de severidad CVSS de 8.3, y aquí explicaremos cómo funciona.

Primera parte: Análisis del código:

Al principio, lo único que podría ser interesante es aprender más sobre el propio fallo.

Mi primera fuente es: https://www.tenable.com/cve/CVE-2026-0073

Esta fuente nos dice que el archivo auth.cpp muestra una función llamada adbd_tls_verify_cert que tiene un flujo que permite un RCE no autenticado.

El objetivo principal ahora es obtener el código fuente de auth.cpp.

Como no pude encontrarlo en ningún repositorio oficial, encontré este repositorio creado por Project-Awaken en: https://github.com/Project-Awaken/android_packages_modules_adb/blob/12/daemon/auth.cpp

¡y ahí está! nuestra misteriosa función:

root@kitploit:~
int adbd_tls_verify_cert(X509_STORE_CTX* ctx, std::string* auth_key) {
    if (!auth_required) {
        // Any key will do.
        LOG(INFO) << __func__ << ": auth not required";
        return 1;
    }

    bool authorized = false;
    X509* cert = X509_STORE_CTX_get0_cert(ctx);
    if (cert == nullptr) {
        LOG(INFO) << "got null x509 certificate";
        return 0;
    }
    bssl::UniquePtr<EVP_PKEY> evp_pkey(X509_get_pubkey(cert));
    if (evp_pkey == nullptr) {
        LOG(INFO) << "got null evp_pkey from x509 certificate";
        return 0;
    }

    IteratePublicKeys([&](std::string_view public_key) {
        // TODO: do we really have to support both ' ' and '\t'?
        std::vector<std::string> split = android::base::Split(std::string(public_key), " \t");
        uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
        const std::string& pubkey = split[0];
        if (b64_pton(pubkey.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) {
            LOG(ERROR) << "Invalid base64 key " << pubkey;
            return true;
        }

        RSA* key = nullptr;
        if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) {
            LOG(ERROR) << "Failed to parse key " << pubkey;
            return true;
        }

        bool verified = false;
        bssl::UniquePtr<EVP_PKEY> known_evp(EVP_PKEY_new());
        EVP_PKEY_set1_RSA(known_evp.get(), key);
        if (EVP_PKEY_cmp(known_evp.get(), evp_pkey.get())) {
            LOG(INFO) << "Matched auth_key=" << public_key;
            verified = true;
        } else {
            LOG(INFO) << "auth_key doesn't match [" << public_key << "]";
        }
        RSA_free(key);
        if (verified) {
            *auth_key = public_key;
            authorized = true;
            return false;
        }

        return true;
    });

    return authorized ? 1 : 0;
}

Pero la parte interesante de la función es la siguiente:

root@kitploit:~
bool verified = false;
bssl::UniquePtr<EVP_PKEY> known_evp(EVP_PKEY_new());
EVP_PKEY_set1_RSA(known_evp.get(), key);
if (EVP_PKEY_cmp(known_evp.get(), evp_pkey.get())) {
  LOG(INFO) << "Matched auth_key=" << public_key;
  verified = true;
} else {
  LOG(INFO) << "auth_key doesn't match [" << public_key << "]";
}

¿Por qué? porque verified se establece como un booleano que permite o no la conexión, y solo se modifica con la declaración "if". ¿El problema? EVP_PKEY_cmp(known_evp.get(), evp_pkey.get()) no siempre devuelve 1 o 0, sino también -1 y -2 porque EVP_PKEY_cmp() devuelve 1 si las claves coinciden, 0 si no coinciden, -1 si los tipos de clave son diferentes y -2 si la operación no es compatible.

Por lo tanto, valida los certificados de claves diferentes o si la operación no es compatible, incluso cuando la clave no coincide.

Para validar nuestra sesión tendremos que forzar una de estas dos opciones.

Segunda parte: Producción del POC e ingeniería inversa del protocolo de conexión ADB

Para intentar explotar esta falla, necesitaremos establecer una sesión TLS.

Esto solo funciona si tanto el atacante como el dispositivo objetivo pueden usar TLS. Sin embargo, la decisión de usar TLS solo la toma el dispositivo objetivo.

Si el dispositivo objetivo permite TLS, puedes establecer una sesión TLS.

Todo ocurre aquí:

  • Primero: paquetes CNXN (paquetes de conexión)
  • Segundo: paquetes STLS (paquetes de actualización a TLS)
  • Tercero: handshake TLS (con clave EC en lugar de RSA)

Intentemos hacer que funcione

Descargar herramienta