六个漏洞翻完,问题都出在同一个地方
原创
niuko
niuko
Ncko
2026年11月1日 09:42
安徽
去阅读
题图 / 六条记录,五个产品,四条不需要账号
昨天夜里翻 NVD 的新条目,0 点 18 分那一批里同时冒出两个编号。一个写着 ZITADEL,一个写着 Frappe。
一个在登录页,一个在上传框。前者不用密码,后者只要一个普通员工的账号。
我一开始以为这是两个独立的故事。往下翻完六条公告,发现不是。
它们错在同一个地方。系统在错误的位置做了信任,信任文件名,信任默认配置,信任客户端算出来的值,信任静态目录,信任“已登录”三个字。
| 编号 | 门槛 | 能拿到什么 | 影响版本 |
| CVE-2026-61730 | 不用账号 | 云审计报告与临时密钥 | CoPilot < 0.1.77 |
| CVE-2026-119660 | 不用账号 | 管理员会话 | MuseBot < 2.0.0 |
| CVE-2026-119128 | 知道用户 ID | 账号接管 | ZITADEL 4.0.0–4.19.4 |
| CVE-2026-110732 | 管理员点一次 | 管理员 MCP token | AI Engine ≤ 3.8.6 |
| CVE-2026-61738 | admin 或 analyst | root 写文件 | CoPilot < 0.1.77 |
| CVE-2026-119145 | 普通登录账号 | 路径穿越写文件 | Frappe < 15.121.0;16.x < 16.34.0 |
PART 01
不用登录的四个
这四个不需要任何账号。系统把“能访问”当成了“有权限”。
CVE-2026-61730 · 一个地址栏就能读报告
CoPilot 是 SOC 团队的安全运营面板,把 Wazuh、Velociraptor、ScoutSuite 的报告收在一个界面里。
它把报告目录挂成了静态文件服务,代码只有一行。
app.mount(\"/scoutsuite-report\", StaticFiles(directory=...))
Starlette 的静态挂载不经过路由依赖。/api 上那层 JWT 检查,管不到这个目录。
报告名也不用猜。调用方填的 report\_name 默认就是 aws-report、gcp-report。
把地址栏从 /api/scoutsuite/available-reports 换成 /scoutsuite-report/aws-report.html,JWT 不用带。前者返回 401,后者直接给你一份 AWS 审计报告。
复现只要一条 curl。
curl -i \"https://target/scoutsuite-report/aws-report.html\"
返回 200,正文里带 ScoutSuite 的结果,就说明报告在裸奔。把 aws 换成 gcp 再试一次,覆盖另一份默认报告。
能拿走的东西比“一份报告”多。里面有云资产清单、IAM 配置、安全组和审计发现。
更麻烦的是 GCP 扫描。管理员上传的服务账号 JSON 也存在这个目录,扫描结束才删。那几分钟里,匿名请求 /scoutsuite-report/<文件名> 就能把云账号私钥拿走。
影响面是 CoPilot 0.1.77 以前的所有版本。实例能访问就行,不需要账号。
SOC 面板常被放到公网方便值班,这条把内网工具变成了公开报表站。
修复有个坑。0.1.77 只把密钥移出了 Web 目录,报告目录的匿名访问没有完整修复。升级之后,历史报告还是可能被匿名读走。
鉴权写在路由上,静态挂载绕过路由。这条缝,很多框架都有。
模板只请求三个默认路径,看到 ScoutSuite 内容就停。
id: CVE-2026-61730
info:
name: SOCFortress CoPilot < 0.1.77 scoutsuite-report 未授权静态文件暴露
author: security-notes
severity: critical
description: |
backend/copilot.py 把 scoutsuite-report 目录挂成无认证的 StaticFiles,
/api 路由要求 JWT,静态目录不要求。默认报告名为 aws-report /
gcp-report,匿名访问可读取云资产、IAM 与配置审计结果;GCP 扫描期间
该目录还会短暂保存上传的服务账号密钥。
classification:
cvss-score: 9.3
cve-id: CVE-2026-61730
cwe-id: CWE-552
reference:
- https://github.com/socfortress/CoPilot/security/advisories/GHSA-pm2w-mmc3-h8hc
- https://nvd.nist.gov/vuln/detail/CVE-2026-61730
tags: cve,cve2026,copilot,scoutsuite,exposure,unauth
http:
- method: GET
path:
- \"{{BaseURL}}/scoutsuite-report/aws-report.html\"
- \"{{BaseURL}}/scoutsuite-report/gcp-report.html\"
- \"{{BaseURL}}/scoutsuite-report/scoutsuite-results/scoutsuite\_results\_aws-report.js\"
stop-at-first-match: true
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: regex
part: body
regex:
- '(?i)(scoutsuite|aws-report|gcp-report)'
CVE-2026-119660 · 默认密钥,管理员会话自己签
MuseBot 是 Telegram 机器人管理后台,默认监听 18080。启动参数 -session\_key 的默认值是 muse\_bot\_session\_key,示例配置里也写着。
它用 gorilla/sessions 的 CookieStore,cookie 名 MuseBot-session。登录成功时写入 session.Values[\"user\_id\"]。
RequireLogin 只检查这个值在不在。不查库,也不看这次会话是不是真的登录过。
密钥是公开的,签名就能自己算。构造一个带 user\_id 的 cookie,后台就当成管理员。
能读密码哈希、聊天记录、机器人配置,也能把机器人停掉。CVSS 9.8。
复现要用脚本。对 gob 编码的 session 值做 HMAC-SHA256,写进 MuseBot-session,再请求后台任意需登录页面。
公开 PoC 是脚本,不是 HTTP 模板。nuclei 的 DSL 做不了这套签名。
影响面是 MuseBot 2.0.0 以前,且没改过 SESSION\_KEY 的实例。18080 直接暴露在公网的,最危险。
弱口令还能被撞出来,默认密钥连撞都不用撞。
CVE-2026-119128 · 一张没有服务端秘密的 cookie
ZITADEL 是统一身份入口。新员工被邀请进来,账号已经建好,密码还没设。
Login V2 为了记住“这个人刚验证过邮箱”,发了一个 verificationCheck cookie。
它的值是用户 ID 和浏览器指纹 cookie 的 SHA-256。
两个输入都没有服务端秘密。用户 ID 能从登录名推出来,指纹 cookie 在客户端自己手里。
也就是说,这个“证明”谁都能算。
Login V2 在用户设置第一份凭据时接受它。攻击者可以给一个还没有任何认证方式的用户设密码、注册 passkey,或者绑上自己控制的外部 IdP。
三条路都通向账号接管。CVSS 3.1 记 7.4,CVSS 4.0 记 9.1。
复现要先知道用户 ID,再按目标浏览器指纹离线算 cookie,然后走设置密码、注册 passkey 或绑定 IdP 的多轮流程。
公开材料没有 HTTP PoC,这条写不出模板。
影响面是 ZITADEL 4.0.0 到 4.19.4,只在 Login V2 下成立。入口是“已被邀请、还没设凭据”的用户,这类账号在入职流程里很常见。
没有服务端秘密的“证明”,只能证明客户端会算 SHA-256。
CVE-2026-110732 · 注册不要权限,同意页不要边框
WordPress 站点装 AI Engine,多半是为了聊天机器人和 MCP。MCP 开着,OAuth 的动态客户端注册端点也就开着。
/wp-json/mcp/v1/oauth/register 的 permission\callback 是 \\_return\_true。
未认证就能注册一个客户端,redirect\_uri 填攻击者自己的地址。
注册只是第一步。同意页没有 X-Frame-Options,也没有 CSP 的 frame-ancestors。
它可以被嵌进攻击者的页面。管理员点一次“允许”,攻击者拿到一张绑定管理员的 MCP token。
MCP 能建用户、改选项。管理员能做的事,这张 token 也能做。CVSS 7.5,复杂度高在“要人点”,不在技术。
复现是未认证注册,拼出授权链接,把同意页嵌进自己的页面,回调地址收 code 换 token。
模板只做未授权探测,发一个缺少 redirect\_uris 的请求,不会创建可用的客户端。
id: CVE-2026-110732
info:
name: AI Engine <= 3.8.6 MCP OAuth 动态客户端注册未授权探测
author: security-notes
severity: high
description: |
MCP 模块的 /wp-json/mcp/v1/oauth/register 使用 permission\callback
\\_return\_true,未认证用户可注册 OAuth 客户端。本模板只发送一个缺少
redirect\_uris 的注册请求:端点开放时返回参数错误,受保护时返回
401/403,不会创建可用的 OAuth 客户端。
classification:
cvss-score: 7.5
cve-id: CVE-2026-110732
cwe-id: CWE-862
reference:
- https://www.wordfence.com/threat-intel/vulnerabilities/id/eb115a8a-35f8-426f-bb67-4a523f67cb34
- https://nvd.nist.gov/vuln/detail/CVE-2026-110732
tags: cve,cve2026,wordpress,ai-engine,mcp,oauth,unauth
http:
- raw:
- |
POST /wp-json/mcp/v1/oauth/register HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{\"client\_name\":\"nuclei-probe\"}
matchers-condition: and
matchers:
- type: status
status:
- 400
- type: regex
part: body
regex:
- '(?i)(redirect\_uri|invalid\_client\_metadata|invalid\_request|rest\_invalid\_param)'
影响面是 AI Engine 3.8.6 及以前,MCP 开启。WordPress 站点多,插件部署散,这条的门槛是管理员的一次点击。
PART 02
登录之后的两个
这两个要账号。它们说明,登录只是门票,权限才是边界。
CVE-2026-61738 · 一个文件名,root 写文件
CoPilot 的 POST /api/scoutsuite/generate-gcp-report 只允许 admin 和 analyst,请求体也按 GCPScoutSuiteJSON 校验过。
校验只管 JSON。file.filename 从 multipart 头里原样取出来,直接进了 os.path.join(directory, filename)。
文件名写成 ../../../../tmp/x,文件落到 /tmp。写成 ../x,落到应用根目录。
后端以 root 跑。写到哪里,攻击者说了算。CVSS 10.0。
这个分数不在“谁能打”,在“打完能拿到什么”。
复现要一个 admin 或 analyst 的 JWT,一份能过校验的 JSON,再把 multipart 的 filename 改成带 ../ 的路径。
公开公告给的是 curl 脚本。不做模板,因为要登录态,而且请求会真的写文件,扫一遍就在目标上留痕。
影响面是 CoPilot 0.1.77 以前。能进来的人不多,但权限从面板管理员跳到主机 root,一台实例后面的云账号一起暴露。
CVE-2026-119145 · 文件名不是标签,是路径
Frappe 是 ERPNext 的底座,采购、库存、人事都跑在上面。上传附件是日常动作。
公告说,某些上传处理在写盘前没有校验目标路径。
攻击者已经登录,剩下的只是把文件名写成一段路径。文件被写到存储目录之外。
落到 Web 可执行路径、模板目录或者计划任务,就能接 RCE。CVSS 9.9。
复现要一个普通账号,找到上传入口,把 multipart 的 filename 写成带 ../ 的路径,再访问落盘文件确认。
公开公告没给可复用的 HTTP 脚本。模板一旦写文件就会改目标状态,不适合批量验证。
影响面是 Frappe 15.121.0 以前,16.x 的 16.34.0 以前。ERP 通常整家公司都在用,能上传的账号很多。
从低权限员工到一个可执行文件,只隔一个文件名。
PART 03
六条漏洞,五种信任错位
翻完六条,我最想说的不是哪个 CVSS 最高,是五个重复出现的习惯。
机制示意 / 六条 CVE 的公告、代码路径与修复记录整理
第一条,默认值被当成安全配置。MuseBot 的会话密钥、CoPilot 的默认报告名,都是装完就能用的东西。装完就能用,通常也意味着装完就能被打。
第二条,文件名被当成标签。61738 和 119145 都在 os.path.join 这一步出事。开发者把它当拼接,攻击者把它当写入地址。
第三条,客户端算出来的值被当成证明。119128 的 cookie 没有服务端秘密,用户 ID 加浏览器指纹就能算出来。
第四条,静态目录被当成不需要鉴权的地方。61730 的鉴权写在路由上,静态挂载在路由外。
第五条,已登录被当成有权限,点过同意被当成真同意。61738 和 119145 卡在权限,110732 卡在同意页。
每一层单独看都没错。连起来看,缝就在层与层之间。
PART 04
怎么查,怎么修
先查,再修。下面这些信号,比公告更能说明你有没有被人踩过。
— CoPilot,看访问日志里 /scoutsuite-report/ 的 200,请求有没有带 Authorization。
— Frappe,看上传接口的 multipart 文件名里有没有 ../,再看站点目录外有没有新文件。
— MuseBot,看 18080 上的 MuseBot-session,同一个 IP 有没有对应的登录请求。
— ZITADEL,看有没有用户在没走过邮箱验证的情况下设了首份凭据。
— AI Engine,看 /wp-json/mcp/v1/oauth/register 有没有未认证请求,OAuth 客户端列表里有没有陌生的 redirect\_uri。
处置顺序按“谁能进来”排。
| 顺序 | 动作 | 原因 |
| 1 | 封掉 CoPilot 报告目录 | 不用账号,最容易被批量扫描 |
| 2 | 换掉 MuseBot 的 SESSION\_KEY | 默认值,直接接管管理员 |
| 3 | 升级 Frappe | 普通登录用户就能写文件 |
| 4 | 升级 CoPilot 并降权 | root 写文件,后果最重 |
| 5 | 清理 ZITADEL 无凭据用户并升级 | 账号接管,影响下游应用 |
| 6 | 关掉或升级 AI Engine 的 MCP | 需要一次管理员点击 |
六条里,四条不需要账号。剩下两条要登录,但登录之后也没被权限拦住。
这六个洞修完,真正值得留下的不是六个编号,是写代码时的三个习惯。
默认值要改。文件名要当输入处理。鉴权要写在所有入口上。
边界不是画在登录页上。边界画在每一个“我以为它已经检查过”的地方。
模板只负责验证,不负责利用。所有请求只对自有资产或书面授权的目标发送。
参考来源:NVD(CVE-2026-61730、61738、119145、119660、119128、110732);SOCFortress CoPilot GHSA-pm2w-mmc3-h8hc、GHSA-q3g8-3cf7-744f;Frappe GHSA-9pp9-wgp9-3p3j;ZITADEL GHSA-84fg-x5h4-w8xv;Wordfence Threat Intelligence;VulnCheck;MuseBot 仓库提交与公开分析;CVE.org。
CVE 编号、影响版本与修复版本以厂商公告和 NVD 记录为准;模板仅用于授权测试。
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论