FlawOpen

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

● CVE-2026-63277 · CVSS v4 8.5 · Haute
Recherche · FlawOpen

CVE-2026-63277 : exécution Java à l’ouverture d’un classeur Calc

Un document Calc conçu à cet effet pouvait utiliser un lien de données externe pour faire résoudre par LibreOffice une classe de pilote JDBC depuis un chemin Java non local à l’ouverture du classeur. LibreOffice 26.2.5 et 26.8.0 limitent ces entrées au schéma file ; l’ouverture par une personne est nécessaire, il ne s’agit donc pas d’une faille réseau zero-click.[1], [2], [3]

💡 Explication en Langage Simple (ELI5)

Un tableur peut mémoriser l’endroit où le programme doit chercher un pilote de base de données. Avant le correctif, cette indication pouvait viser une adresse distante et le programme pouvait y charger du code Java quand une personne ouvrait le fichier. Le correctif n’accepte que les adresses portant le schéma file:. Cela resserre le chemin, mais cette étiquette ne garantit pas à elle seule que chaque cible soit physiquement locale.[1], [4], [5]

Concepts Clés et Termes

Lien de données externe
Paramètre de Calc qui décrit la connexion entre la feuille et une source de données externe.[1]
Pilote JDBC
Logiciel Java qui permet à une application de communiquer avec une base de données.[1]
Class path
Ensemble d’emplacements depuis lesquels Java peut charger des classes et ressources associées.[4], [5]
CWE-829
Inclusion de fonctionnalités provenant d’un domaine de contrôle non fiable ; ici, le chemin acceptait une URL de class path hors du schéma local attendu.[6], [1]

Correspondances de référentiels

  • Référence CWE pour la faiblesse décrite dans ce guide : CWE-829

Analyse de Cause Racine

Le chemin vulnérable jvmaccess::ClassPath::translateToUrls développait chaque entrée du class path Java puis la transmettait au constructeur d’URL de Java sans en restreindre le schéma au préalable. Le code 26.2.5.2 ajoute l’analyse de l’URI et rejette les entrées dont le schéma n’est pas file avant de construire l’URL Java. L’avis du fournisseur relie ce chemin aux liens de données externes Calc et au chargement des pilotes JDBC. Une personne doit ouvrir un document préparé pour atteindre ce comportement ; les sources citées n’établissent ni un déclenchement zero-click ni une exploitation observée. La protection vérifie précisément le schéma : ne la présentez pas comme une politique générale d’autorisation et n’affirmez pas qu’elle rejette tout partage de fichiers distant.[1], [4], [5]

CVE-2026-63277 : conditions du chargement Java depuis Calc

VérificationCondition concernée ou comportement confirméAction défensive
Entrée contrôlée par le documentLe lien de données externe du document peut définir le chemin du class path utilisé pour le pilote JDBC.Traitez les documents et liens d’origine non fiable comme des entrées non fiables ; installez une version corrigée.
Interaction utilisateurUne personne doit ouvrir le document pour atteindre le chemin de chargement décrit par le fournisseur.Ne le qualifiez pas de zero-click ; examinez les contrôles de réception et d’ouverture des documents.
Limite du correctifCette vérification ne démontre pas que chaque cible file: se trouve sur un disque local ni que les partages réseau sont refusés.Décrivez-la comme validation du schéma ; ne lui attribuez pas une garantie plus large d’autorisation ou de localité.

Déroulement de l'Attaque Étape par Étape

Étape 1

Le document contient un lien de données externe

Le document concerné décrit une source externe et un class path pour une classe de pilote de base de données Java.[1], [4]

Étape 2

Une personne ouvre le document

Une interaction utilisateur est nécessaire ; ouvrir un tableur quelconque n’équivaut pas à une exploitation distante sans interaction.[1], [2]

Étape 3

Le class path Java est converti en URL

Avant le correctif, translateToUrls transmettait une entrée développée au constructeur d’URL Java sans vérifier que son schéma était un fichier local.[4]

Étape 4

Le pilote indiqué peut être chargé

L’avis du fournisseur décrit ce chemin de chargement Java. L’impact dépend du document, de la configuration et de l’intégration Java ; ne prétendez pas que tout document ou toute installation Calc est exploitable.[1], [2]

Étape 5

La version corrigée refuse les autres schémas

LibreOffice 26.2.5.2 analyse l’URI et lève une exception avant la création de l’URL, sauf si le schéma vaut file. Installez une version corrigée par le fournisseur ou la distribution.[5], [1]

Code Source : Vulnérable vs Sécurisé

Ces extraits ciblés proviennent de l’implémentation amont de translateToUrls pour les versions indiquées. En 26.2.4.2, l’entrée est développée puis transmise directement à la création d’une URL Java. En 26.2.5.2, l’analyse de l’URI est ajoutée et les schémas autres que file sont rejetés avant cette création. Le diff montre la vérification du schéma ; l’avis confirme le chemin Calc/JDBC. Il s’agit d’une analyse de source, pas d’une preuve de concept exécutable.[4], [5], [1]

Extrait source: jvmaccess/source/classpath.cxx — fonction translateToUrls

IMPLÉMENTATION VULNÉRABLE
// LibreOffice 26.2.4.2 — jvmaccess/source/classpath.cxx (version vulnérable)
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 SÉCURISÉ ET ROBUSTE
// LibreOffice 26.2.5.2 — jvmaccess/source/classpath.cxx (version corrigée)
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);
}

Liste de Contrôle de Sécurité pour l'Ingénierie

Sources