FlawOpen

flawopen.com/Teardowns/cve-2026-63277-libreoffice-calc-jdbc-classpath-rce

● CVE-2026-63277 · CVSS v4 8.5 · Alta
Investigación · FlawOpen

CVE-2026-63277: ejecución Java al abrir una hoja Calc

Un documento Calc preparado podía usar un vínculo de datos externos para que LibreOffice resolviera una clase de controlador JDBC desde una ruta Java no local cuando alguien abría la hoja. LibreOffice 26.2.5 y 26.8.0 limitan estas entradas a esquemas file; hace falta que una persona abra el documento, por lo que no es un fallo de red zero-click.[1], [2], [3]

💡 Explicación en Lenguaje Sencillo (ELI5)

Una hoja de cálculo puede guardar una nota con el lugar donde debe buscarse un controlador de base de datos. Antes del arreglo, esa nota podía indicar una dirección remota y el programa podía cargar código Java desde allí cuando alguien abría el archivo. La corrección acepta únicamente direcciones con el esquema file:. Esto acota la ruta, aunque la etiqueta por sí sola no demuestra que todos los destinos estén físicamente en el equipo.[1], [4], [5]

Conceptos Clave y Términos

Vínculo de datos externos
Configuración de Calc que describe cómo se conecta la hoja a una fuente de datos externa.[1]
Controlador JDBC
Software Java que permite a una aplicación comunicarse con una base de datos.[1]
Class path
Conjunto de ubicaciones desde las que Java puede cargar clases y recursos relacionados.[4], [5]
CWE-829
Inclusión de funcionalidad de una esfera de control no confiable; aquí, la ruta admitía una URL de class path fuera del esquema de archivo local previsto.[6], [1]

Mapeos de marcos

  • Referencia CWE para la debilidad descrita en esta guía: CWE-829

Análisis de Causa Raíz

La ruta vulnerable jvmaccess::ClassPath::translateToUrls expandía cada entrada del class path Java y la entregaba al constructor de URL de Java sin restringir antes su esquema. El código de 26.2.5.2 incorpora el análisis del URI y rechaza las entradas cuyo esquema no sea file antes de construir la URL Java. El aviso del proveedor vincula esta ruta con los vínculos de datos externos de Calc y la carga de controladores JDBC. Para alcanzar el comportamiento, una persona debe abrir un documento preparado; las fuentes citadas no demuestran alcance zero-click ni explotación activa. La protección comprueba específicamente el esquema: no debe describirse como una política general de autorización ni afirmarse que rechaza todo recurso compartido remoto.[1], [4], [5]

CVE-2026-63277: cuándo un documento Calc activa la carga Java

ComprobaciónCondición afectada o comportamiento confirmadoMedida defensiva
Entrada controlada por el documentoEl vínculo de datos externos del documento puede definir la ruta del class path usado para el controlador JDBC.Trate documentos y vínculos de fuentes no confiables como entrada no confiable; actualice a una versión corregida.
Interacción de usuarioUna persona debe abrir el documento para alcanzar la ruta de carga descrita por el proveedor.No lo describa como zero-click; revise los controles para recibir y abrir documentos.
Límite del arregloLa comprobación de esquema no demuestra que todos los destinos file: estén en el disco local ni que se rechacen los recursos de red.Describa el arreglo como validación del esquema; no le atribuya una garantía más amplia de autorización o ubicación.

Flujo de Ataque Paso a Paso

Paso 1

El documento contiene un vínculo de datos externos

El documento afectado describe una fuente externa y un class path para una clase controladora JDBC de Java.[1], [4]

Paso 2

Una persona abre el documento

Se requiere interacción del usuario; abrir una hoja arbitraria no equivale a una explotación remota sin interacción.[1], [2]

Paso 3

Se traducen las rutas del class path Java

Antes del arreglo, translateToUrls pasaba una entrada expandida al constructor de URL de Java sin comprobar si el esquema era de archivo local.[4]

Paso 4

Se puede cargar el controlador indicado

El aviso del proveedor describe esta ruta de carga Java. El impacto depende del documento, la configuración y la integración Java; no se debe afirmar que todo documento o instalación de Calc sea explotable.[1], [2]

Paso 5

La versión corregida rechaza otros esquemas

LibreOffice 26.2.5.2 analiza el URI y genera una excepción antes de crear la URL salvo que el esquema sea file. Instale una compilación corregida por el proveedor o la distribución.[5], [1]

Código Fuente: Vulnerable vs. Seguro

Estos fragmentos concisos proceden de la implementación ascendente fijada de translateToUrls. La versión 26.2.4.2 expande la entrada y pasa directamente a crear una URL Java. La versión 26.2.5.2 añade el análisis URI y rechaza los esquemas distintos de file antes de crearla. El diff prueba la comprobación del esquema; el aviso del proveedor acredita la ruta de documento Calc/JDBC. Es un análisis de código fuente, no una prueba de concepto ejecutable.[4], [5], [1]

Fragmento de origen: jvmaccess/source/classpath.cxx — función translateToUrls

IMPLEMENTACIÓN VULNERABLE
// LibreOffice 26.2.4.2 — jvmaccess/source/classpath.cxx (versión vulnerable)
if (!url.isEmpty()) {
    css::uno::Reference< css::uri::XVndSunStarExpandUrlReference >
        expUrl(
            css::uri::UriReferenceFactory::create(context)->parse(url),
            css::uno::UNO_QUERY);
    if (expUrl.is()) {
        css::uno::Reference< css::util::XMacroExpander > expander =
            css::util::theMacroExpander::get(context);
        try {
            url = expUrl->expand( expander );
        } catch (const css::lang::IllegalArgumentException & e) {
            css::uno::Any anyEx = cppu::getCaughtException();
            throw css::lang::WrappedTargetRuntimeException(
                "com.sun.star.lang.IllegalArgumentException: "
                 + e.Message,
                 nullptr, anyEx );
        }
    }
    jvalue arg;
    arg.l = environment->NewString(
        reinterpret_cast< jchar const * >(url.getStr()),
        static_cast< jsize >(url.getLength()));
    if (arg.l == nullptr) {
        return nullptr;
    }
    jobject o(environment->NewObjectA(classUrl, ctorUrl, &arg));
    if (o == nullptr) {
        return nullptr;
    }
    urls.push_back(o);
}
PARCHE SEGURO Y ROBUSTO
// LibreOffice 26.2.5.2 — jvmaccess/source/classpath.cxx (versión corregida)
if (!url.isEmpty()) {
    css::uno::Reference< css::uri::XVndSunStarExpandUrlReference >
        expUrl(
            css::uri::UriReferenceFactory::create(context)->parse(url),
            css::uno::UNO_QUERY);
    if (expUrl.is()) {
        css::uno::Reference< css::util::XMacroExpander > expander =
            css::util::theMacroExpander::get(context);
        try {
            url = expUrl->expand( expander );
        } catch (const css::lang::IllegalArgumentException & e) {
            css::uno::Any anyEx = cppu::getCaughtException();
            throw css::lang::WrappedTargetRuntimeException(
                "com.sun.star.lang.IllegalArgumentException: "
                 + e.Message,
                 nullptr, anyEx );
        }
    }
    css::uno::Reference< css::uri::XUriReference > uriRef(
        css::uri::UriReferenceFactory::create(context)->parse(url));
    if (!uriRef.is() || !uriRef->getScheme().equalsIgnoreAsciiCase("file"))
    {
        throw css::lang::IllegalArgumentException(
            "non-local Java class path entry: " + url,
            css::uno::Reference< css::uno::XInterface >(), 0);
    }
    jvalue arg;
    arg.l = environment->NewString(
        reinterpret_cast< jchar const * >(url.getStr()),
        static_cast< jsize >(url.getLength()));
    if (arg.l == nullptr) {
        return nullptr;
    }
    jobject o(environment->NewObjectA(classUrl, ctorUrl, &arg));
    if (o == nullptr) {
        return nullptr;
    }
    urls.push_back(o);
}

Lista de Verificación de Seguridad para Ingeniería

Fuentes