flawopen.com/Teardowns/cve-2026-63277-libreoffice-calc-jdbc-classpath-rce
CVE-2026-63277:打开 Calc 表格时的 Java 代码执行
经过构造的 Calc 文档可利用外部数据映射,使 LibreOffice 在有人打开表格时从非本地 Java class path 解析 JDBC 驱动类。LibreOffice 26.2.5 和 26.8.0 限制此类条目只能使用 file scheme。必须有人打开文档,因此这不是零交互网络漏洞。[1], [2], [3]
电子表格可以记录程序应从哪里查找数据库驱动。修复前,这个位置可以指向远程地址,用户打开文件时程序可能从那里加载 Java 代码。修复只接受带有 file: scheme 的地址。这缩小了路径范围,但这个标签本身不能证明每个目标都在物理本地磁盘上。[1], [4], [5]
核心概念与专有名词
框架映射
- 本指南所述弱点的 CWE 参考: CWE-829
根本原因剖析 (Root Cause)
存在漏洞的 jvmaccess::ClassPath::translateToUrls 路径会展开每个 Java class path 条目,并在未先限制 scheme 的情况下将其交给 Java URL 构造器。26.2.5.2 源码加入 URI 解析,并在构造 Java URL 前拒绝 scheme 不是 file 的条目。厂商公告将该路径与 Calc 外部数据映射及 JDBC 驱动加载关联起来。需要有人打开经过构造的文档才能触发该路径;所引用资料没有证明零交互可达或存在实战利用。保护措施检查的是 scheme:不要把它说成通用授权策略,也不要声称它拒绝所有远程文件共享。[1], [4], [5]
CVE-2026-63277:Calc 触发 Java 加载的条件
攻击执行流程分解
Java class path 被转换为 URL
修复前,translateToUrls 会把展开后的条目交给 Java URL 构造器,却不检查 scheme 是否为本地文件。[4]
源代码对比:漏洞与安全实现
这些精简代码片段来自指定版本的上游 translateToUrls 实现。26.2.4.2 会展开条目,然后直接创建 Java URL;26.2.5.2 加入 URI 解析,并在创建 URL 前拒绝 file 以外的 scheme。源码差异证明了 scheme 校验;厂商公告确认 Calc/JDBC 文档路径。此处是源码分析,不是可运行的利用代码。[4], [5], [1]
源码摘录: jvmaccess/source/classpath.cxx — translateToUrls 函数
// LibreOffice 26.2.4.2 — jvmaccess/source/classpath.cxx(存在漏洞的版本)
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);
}
// LibreOffice 26.2.5.2 — jvmaccess/source/classpath.cxx(修复后的版本)
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);
}
工程与系统安全加固清单
- ✓升级到 26.2 分支的 LibreOffice 26.2.5 或更高版本,或 26.8 分支的 26.8.0 或更高版本;核实发行版实际软件包及 backport。[1], [2]
- ✓盘点会打开不可信来源 Calc 文档的工作流,以及依赖 JDBC 驱动的外部数据映射。
- ✓添加回归测试,确认
file以外的 class path scheme 会在创建 Java URL 前被拒绝,同时受支持的本地文件条目仍能工作。[5] - ✓不要把宏警告当成此 Java class path 路径的防护;分别评估文档打开行为和 Java 配置。[1]
- ✓Apache 公告称,LibreOffice 将同一问题报告为
CVE-2026-63277,而 Apache OpenOffice 使用CVE-2026-59265跟踪该问题。请确认 AOO 自身的受影响/已修复版本和缓解措施;不要套用 LibreOffice 的版本信息。[8], [1] - ✓测试时不要复现流传的文档或远程 Java 载荷;请使用受控且不执行代码的断言来验证 scheme 检查。[1]