CVE-2026-91085 Apache Karaf 权限绕过漏洞
影响低权限认证用户可向配置目录写入任意文件,可能导致敏感信息泄露或配置篡改
Apache Karaf 的 shell/SSH 命令安全依赖按 scope 划分的 ACL 配置文件。当某条命令没有匹配到任何 ACL 规则时,SecuredSessionFactoryImpl.checkSecurity() 会默认放行(fail open),而用于兜底强制角色的 karaf.secured.command.compulsory.roles 在 system.properties 中默认被注释掉。随发行版提供的 config scope ACL 缺少 install 条目,导致 config:install 命令对任意已认证用户开放。
影响范围
Apache Karaf 使用默认 ACL 配置的版本(config scope ACL 未包含 install 条目、且 compulsory.roles 未启用)。具体受影响版本范围暂无公开信息。
漏洞详情
漏洞类型为访问控制缺失(ACL 规则遗漏导致的越权)。成因是 ACL 解析器在 NO_MATCH 时设置 passCheck=true 的 fail-open 设计,加上 config:install 未被任何规则覆盖,且强制角色开关默认关闭。利用方式是任意已认证用户(包括仅有 viewer 角色者)执行 config:install <url> <finalname>,从远程拉取内容并写入 ${karaf.etc} 目录。
利用条件与风险
利用前提是攻击者已获得任意有效账号(含最低权限的 viewer)。实战中可借此写入配置文件,可能篡改服务行为或植入恶意配置,风险较高。
修复建议
官方修复方案暂无公开信息。临时缓解措施:在 etc/system.properties 中启用 karaf.secured.command.compulsory.roles 设置强制角色,并在 config scope ACL 中为 install 命令显式添加角色限制。
Apache Karaf’s shell/SSH command security is enforced by per-scope ACL configuration files (etc/org.apache.karaf.command.acl..cfg). SecuredSessionFactoryImpl.checkSecurity() resolves the roles required for an invocation and, when no ACL rule matches the command, fails open: ACLConfigurationParser.Specificity.NO_MATCH sets passCheck = true. The safety valve for this, karaf.secured.command.compulsory.roles, ships commented out in etc/system.properties, so an unmatched command is allowed for any authenticated user.
The shipped org.apache.karaf.command.acl.config ACL (assemblies/features/standard/src/main/feature/feature.xml, mirrored into instance/…/etc/org.apache.karaf.command.acl.config.cfg) has no install entry. It restricts delete to admin, restricts edit/property-*/update on the jmx.acl.*, org.apache.karaf.command.acl.* and org.apache.karaf.service.acl.* PIDs to admin, and allows manager for everything else, but config:install was simply unmatched, and therefore allowed for any authenticated user, including one holding only the viewer role.
config:install fetches url and writes it into ${karaf.etc} as finalname. It calls PathUtils.checkWithin() to block .. traversal outside karaf.etc, but that folder holds every security-relevant file Karaf ships: users.properties, keys.properties, host.key, and all org.apache.karaf.*.acl.* files, including the very ACL file that (mis)governs this command. With -o/–override, an existing file is overwritten with attacker-controlled bytes fetched from an arbitrary URL.
Because felix.fileinstall.dir = ${karaf.etc} (etc/config.properties), Felix FileInstall also watches and reloads any .cfg file dropped there, closing the loop without requiring a restart.
By contrast, bundle:install, feature:install and kar:install are all admin-only in their own ACLs, and config:delete is admin in this same ACL, config:install was the outlier.
MitigationAdd install = admin in etc/org.apache.karaf.command.acl.config.cfg (create the file is absent), and/or set karaf.secured.command.compulsory.roles=admin in etc/system.properties (and restart) to make unmatched commands fail closed by default.