FlawOpen

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

● CVE-2026-63277 · CVSS v4 8.5 · Alta
Pesquisa · FlawOpen

CVE-2026-63277: execução Java ao abrir planilha Calc

Um documento Calc preparado para isso podia usar um vínculo de dados externos para fazer o LibreOffice resolver uma classe de driver JDBC em um caminho Java não local quando alguém abria a planilha. O LibreOffice 26.2.5 e 26.8.0 passaram a aceitar apenas entradas de class path com esquema file; é necessária a interação de quem abre o documento, portanto não é uma falha de rede zero-click.[1], [2], [3]

💡 Explicação em Linguagem Simples (ELI5)

Uma planilha pode guardar uma indicação de onde o programa deve buscar um driver de banco de dados. Antes da correção, essa indicação podia apontar para um endereço remoto, e o programa podia carregar código Java dali quando alguém abrisse o arquivo. A correção aceita somente endereços com o esquema file:. Isso restringe o caminho, mas o rótulo por si só não prova que todo destino seja fisicamente local.[1], [4], [5]

Conceitos Centrais e Termos

Vínculo de dados externos
Configuração do Calc que descreve como a planilha se conecta a uma fonte de dados externa.[1]
Driver JDBC
Software Java que permite que um aplicativo se comunique com um banco de dados.[1]
Class path
Conjunto de locais dos quais Java pode carregar classes e recursos relacionados.[4], [5]
CWE-829
Inclusão de funcionalidade de uma esfera de controle não confiável; neste caso, o caminho aceitava um URL de class path fora do esquema de arquivo local esperado.[6], [1]

Mapeamentos de frameworks

  • Referência CWE para a fraqueza descrita neste guia: CWE-829

Análise de Causa Raiz

O caminho vulnerável jvmaccess::ClassPath::translateToUrls expandia cada entrada de class path Java e a passava ao construtor de URL do Java sem restringir primeiro o esquema. O código 26.2.5.2 acrescenta a análise do URI e rejeita entradas cujo esquema não seja file antes de construir o URL Java. O aviso do fornecedor relaciona esse caminho aos vínculos de dados externos do Calc e ao carregamento de drivers JDBC. A exploração exige que alguém abra um documento preparado; as fontes citadas não comprovam alcance zero-click nem exploração ativa. A proteção verifica especificamente o esquema: não a descreva como política geral de autorização nem afirme que ela rejeita todo compartilhamento remoto de arquivos.[1], [4], [5]

CVE-2026-63277: quando um documento Calc aciona o carregamento Java

VerificaçãoCondição afetada ou comportamento confirmadoAção defensiva
Entrada controlada pelo documentoO vínculo de dados externo do documento pode definir o caminho de class path usado para o driver JDBC.Trate documentos e vínculos de origem não confiável como entrada não confiável; atualize para uma versão corrigida.
Interação do usuárioUma pessoa precisa abrir o documento para alcançar o caminho de carregamento descrito pelo fornecedor.Não apresente como zero-click; avalie controles de recebimento e abertura de documentos.
Limite da correçãoA checagem de esquema não demonstra que cada destino file: esteja no disco local nem que compartilhamentos de rede sejam recusados.Descreva a correção como validação do esquema; não atribua a ela uma garantia mais ampla de autorização ou localidade.

Fluxo de Ataque Passo a Paso

Passo 1

O documento contém um vínculo de dados externos

O documento afetado descreve uma fonte externa e um class path para uma classe de driver de banco de dados Java.[1], [4]

Passo 2

Uma pessoa abre o documento

A interação do usuário é necessária; abrir uma planilha arbitrária não equivale a uma exploração remota sem interação.[1], [2]

Passo 3

O class path Java é convertido em URLs

Antes da correção, translateToUrls passava uma entrada expandida ao construtor de URL do Java sem verificar se o esquema era de arquivo local.[4]

Passo 4

O driver referenciado pode ser carregado

O aviso do fornecedor descreve esse caminho de carregamento Java. O impacto depende do documento, da configuração e da integração Java; nem todo documento ou instalação Calc deve ser considerado vulnerável em condições idênticas.[1], [2]

Passo 5

A versão corrigida rejeita esquemas diferentes

No LibreOffice 26.2.5.2, o URI é analisado e ocorre uma exceção antes de criar o URL, a menos que o esquema seja file. Instale uma versão corrigida pelo fornecedor ou pela distribuição.[5], [1]

Código-Fonte: Vulnerável vs. Seguro

Estes trechos concisos vêm da implementação upstream de translateToUrls nas versões fixadas. A versão 26.2.4.2 expande a entrada e segue diretamente para criar um URL Java. A versão 26.2.5.2 insere a análise do URI e rejeita esquemas diferentes de file antes dessa criação. O diff demonstra a validação do esquema; o aviso do fornecedor confirma o caminho por documentos Calc/JDBC. É uma análise do código-fonte, não uma prova de conceito executável.[4], [5], [1]

Trecho de origem: jvmaccess/source/classpath.cxx — função translateToUrls

IMPLEMENTAÇÃO VULNERÁVEL
// LibreOffice 26.2.4.2 — jvmaccess/source/classpath.cxx (versão vulnerável)
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);
}
PATCH SEGURO E ROBUSTO
// LibreOffice 26.2.5.2 — jvmaccess/source/classpath.cxx (versão corrigida)
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 Verificação de Segurança para Engenharia

Fontes