HTML与JavaScript的暗面:当DOM操作成为渗透测试的武器"

admin 2026-10-16 13:06:37 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

HTML与JavaScript的暗面:当DOM操作成为渗透测试的武器

原创

KLSEC
KLSEC

昆仑AI安全实验室

2026年10月15日 00:00
广东

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

你打开一个网页,看到的是一个漂亮的界面。按钮、表单、图片、下拉菜单。但在渗透测试工程师眼里,这些元素背后藏着一整套可以被武器化的逻辑。

2026年9月,GitHub Enterprise Server披露了一个存储型XSS漏洞,编号CVE-2026-77912,CVSS评分7.4。攻击者通过Markdown渲染管线注入任意HTML属性,利用同源JavaScript gadget绕过内容安全策略,最终控制了受害者的页面DOM。成功的利用可以读取受害者可见的内容、窃取CSRF令牌、以受害者身份执行状态变更操作,并通过同源写入外传数据。

这个漏洞的精髓不在XSS本身,在于它揭示了一个事实:HTML和JavaScript的每一个设计特性,在攻击者手里都可能变成一条攻击链的起点。

一、HTML基础:为什么“安全”的标签也能被武器化

HTML的设计初衷是描述文档结构。`是链接,

是表单,`是输入框。这些标签本身没有恶意。但HTML标准里有一个被大多数人忽略的特性,它是DOM Clobbering攻击的根基。

命名属性查找。 当你在HTML元素上设置id或name属性时,浏览器会自动把这个元素暴露为document对象和window对象上的一个命名属性。这不是浏览器的一个“bug”,是HTML标准明确规定的行为。

这意味着什么?你在页面上写了一个`,然后你的JavaScript代码里可以直接用x来访问这个元素,不需要document.getElementById('x')`。看起来是个便利特性。但它的副作用是:攻击者可以通过注入HTML,覆盖你代码里已经存在的全局变量。

考虑一个常见的代码模式:

var config = window.config || { debug: false };if (config.debug) loadDebugger(config.endpoint);

如果攻击者能在这段代码运行之前注入HTML,一个就足以让`window.config`变成一个真实的DOM节点(truthy值),`config.debug`解析为元素,config.endpoint解析为攻击者控制的URL。应用的逻辑被无声地劫持了。

这就是DOM Clobbering的核心:不需要执行一行JavaScript,只需要注入“安全”的HTML,就能改变页面的逻辑。 传统的HTML净化器会拦截<script>、onerror、javascript:这些明显的攻击特征,但``看起来完全无害。它只是一个带ID的链接元素,任何净化器都会放行。

二、DOM Clobbering实战:从“无害HTML”到控制页面逻辑

DOM Clobbering的完整攻击链比上面那个例子复杂得多。2026年3月,Intigriti的CTF挑战展示了一条典型的链式利用路径。

挑战目标是一个“安全搜索门户”,部署了严格的CSP和DOMPurify净化器。CSP策略中script-src 'self'意味着只有同源脚本能执行,内联脚本完全被阻断。DOMPurify版本3.0.6,并且配置了FORBID_ATTR: ['id', 'class', 'style'],明确禁止了id和class属性。

乍一看,XSS在这个环境下几乎不可能。内联脚本被CSP阻断,DOMPurify禁止了id属性(DOM Clobbering的标准入口),剩下的注入面极其有限。

但攻击者找到了绕过路径。DOMPurify的FORBID_ATTR只禁止了id,没有禁止name属性。而命名属性查找的规则是:任何带有name属性的元素,也会被暴露为window和document上的命名属性。<form name=\"config\">和``在命名属性查找中效果完全一样。

攻击者利用这个遗漏构建了clobbering gadget,覆盖了页面代码中的关键变量,最终引导同源脚本执行了攻击者控制的操作。CSP没有被“绕过”,它仍然在正常工作——内联脚本依然被阻断。但攻击者根本不需要内联脚本,他劫持了已经存在的、被CSP允许的同源脚本的执行逻辑。

这个案例的教学意义在于: DOM Clobbering攻击的是应用的逻辑,不是浏览器的安全机制。CSP、SRI、Trusted Types这些防护措施针对的是“脚本注入”,但DOM Clobbering注入的是“数据”。数据可以被信任的脚本读取,然后被信任的脚本执行。

三、2026年的新战场:DOM Clobbering + CVE链

2026年最值得关注的DOM Clobbering案例是CVE-2026-64638,一个WordPress的预认证反射型XSS,最终演变成完整的远程代码执行。

漏洞点在wp-login.php。当用户提交一个无效的用户名时,错误信息会反射这个用户名,没有做HTML编码。攻击者在用户名中提交``,这个标签通过了WordPress的过滤,并在错误页面中被渲染。

`的巧妙之处在于:WordPress的wp-adminJavaScript代码依赖ajaxurl这个全局变量来决定AJAX请求的发送地址。攻击者通过clobbering把ajaxurl`覆盖成了一个攻击者控制的URL。当管理员访问这个错误页面时,wp-admin的JS代码自动向攻击者的服务器发送了一个包含管理员凭证的请求。

但这只是第一步。攻击者的完整攻击链更长:

第一步,利用反射型XSS和DOM Clobbering劫持ajaxurl,自动提交一个表单。第二步,将管理员重定向到authorize-application.php页面,诱导管理员授权一个恶意的Application Password。第三步,利用获取的Application Password通过WordPress REST API激活一个恶意插件。第四步,恶意插件包含PHP WebShell,服务器权限到手。

从“一个没有HTML编码的错误信息”到“服务器RCE”,中间串联了DOM Clobbering、Application Password窃取和REST API滥用三个环节。任何一个环节单独看都不足以造成严重危害,但组合起来就是一条完整的攻击链。

四、JavaScript基础:原型链为什么是攻击面

理解DOM Clobbering之后,需要理解JavaScript的另一个核心概念:原型链。它是JavaScript继承机制的基础,也是原型污染漏洞的根源。

JavaScript中,每个对象都有一个原型。当你访问一个对象上不存在的属性时,JavaScript会沿着原型链往上找,直到找到这个属性或者到达链的顶端(Object.prototype)。如果攻击者能污染Object.prototype,那么所有对象都会继承这个被污染的属性。

2026年7月披露的CVE-2026-65913就是一个典型的原型污染导致XSS的案例。DOMPurify在USE_PROFILES模式下存在原型污染漏洞,攻击者可以污染Array.prototype的属性(比如把onclick设置为true),导致DOMPurify把事件处理器当作允许的属性放行,最终在渲染被“净化”的HTML时触发DOM-based XSS。

漏洞的技术细节值得拆开看。DOMPurify在USE_PROFILES模式下进行属性过滤时,会检查属性是否在允许列表中。但这个检查是通过原型链查找完成的——如果Array.prototype上存在一个被污染的属性,这个属性会被所有数组继承,包括DOMPurify用于存储允许属性的数组。攻击者污染Array.prototype.onclick = true之后,DOMPurify的允许列表中“凭空多出”了onclick,所有带onclick的标签都被放行。

同样的模式在另一个DOMPurify漏洞(GHSA-V9JR-RG53-9PGP)中再次出现,这次的污染点是CUSTOM_ELEMENT_HANDLING的fallback对象。当配置中没有指定CUSTOM_ELEMENT_HANDLING时,DOMPurify回退到{},这个空对象继承自Object.prototype。攻击者污染Object.prototype.tagNameCheck = /.*/和Object.prototype.attributeNameCheck = /.*/之后,DOMPurify会允许所有自定义元素和所有属性,包括事件处理器。

这两个漏洞的共同教训是:净化器的安全性取决于它运行的环境是否干净。 如果攻击者能在同一个执行上下文中利用另一个原型污染漏洞(比如lodash、jQuery.extend、或者一个不安全的查询字符串解析器),净化器本身的安全保证就会瓦解。

五、渗透测试方法论:如何系统性地挖掘客户端漏洞

了解了这些攻击技术的原理之后,接下来是方法论。如何在授权测试中系统性地发现这类漏洞?

第一步,识别DOM sink。 打开浏览器的开发者工具,搜索JavaScript代码中所有直接操作DOM的位置。重点搜索这些关键词:innerHTML、outerHTML、document.write、insertAdjacentHTML、eval、setTimeout(传入字符串时)、location.href、location.assign、postMessage。

第二步,追踪数据流。 找到sink之后,反向追踪数据来源。数据是否来自location.hash、location.search、document.referrer、window.name、postMessage事件、或者任何用户可控的存储(localStorage、sessionStorage)?如果数据从可控来源流向危险sink且没有经过净化,就是一个DOM XSS候选点。

第三步,检查净化器版本和配置。 如果应用使用了DOMPurify,检查版本号。3.3.2之前的版本存在USE_PROFILES模式的原型污染漏洞,3.3.3之前存在CUSTOM_ELEMENT_HANDLING的fallback漏洞。检查配置中是否禁用了id和name属性——只禁用id是不够的,name同样可以用于DOM Clobbering。

第四步,测试DOM Clobbering。 提交一段看似无害的HTML:`或者

。然后在浏览器控制台中检查window.x和window.config是否变成了你注入的DOM节点。如果页面代码中有window.config || {}`这样的模式,clobbering就成功了。

第五步,检查CSP策略。 在响应头中查看Content-Security-Policy。script-src 'self'意味着内联脚本被阻断,但同源脚本仍然可以执行。攻击策略要从“注入新脚本”转向“劫持已有脚本的执行逻辑”。script-src 'unsafe-inline'则简单得多,直接注入<script>alert(1)</script>就能验证。

六、一个完整的实战案例:从JS文件到DOM XSS

去年我在一个授权SaaS测试中遇到一个场景。主站防护做得很严密,CSP策略完整,DOMPurify版本较新,没有明显的注入点。

但我在他们的JS bundle里搜索postMessage时,发现了一段代码:

window.addEventListener('message', function(e) {    if (e.data.type === 'render') {        document.getElementById('preview').innerHTML = e.data.html;    }});

这个message事件监听器没有校验e.origin,任何来源的postMessage都可以触发它。而且它直接把e.data.html写入innerHTML。

接下来要解决的问题是:如何让受害者的浏览器执行这个postMessage?答案是找到一个能被攻击者控制的页面,用window.open打开目标站点,然后通过postMessage发送恶意数据。

我在目标站点上找到了一个用户可自定义的个人主页功能。攻击者可以在自己的个人主页上嵌入JavaScript(站点允许用户自定义页面样式,但过滤了脚本)。虽然直接注入<script>被过滤了,但<iframe>没有被过滤。攻击者可以在个人主页上嵌入一个<iframe src=\"https://target.com/app\">,然后通过postMessage向这个iframe发送恶意数据。

完整的攻击链:攻击者创建恶意个人主页 → 诱导受害者访问 → 页面中的iframe加载目标应用 → 攻击者的JS通过postMessage发送包含XSS payload的消息 → 应用的message监听器把payload写入innerHTML → DOM XSS触发。

写在最后

HTML和JavaScript是Web安全的“原材料”。大多数开发者把它们当作搭建界面的工具,安全测试人员如果把视角停留在“有没有<script>标签”的层面,就会漏掉一整类攻击。

DOM Clobbering的武器是“命名属性查找”这个HTML标准特性,它不需要脚本。原型污染的原型链是JavaScript继承机制的基础,它污染的是所有对象的“基因”。CSP绕过不需要破解CSP算法,只需要劫持一个已经被CSP信任的同源脚本。

2026年的客户端安全,攻击面不在“有没有过滤”,在“过滤的假设是否成立”。DOMPurify的FORBID_ATTR: ['id']假设了id是DOM Clobbering的唯一入口,但HTML标准说name也可以。CUSTOM_ELEMENT_HANDLING的fallback假设了{}是干净的,但原型链说Object.prototype可能已经被污染。

下次你审JavaScript代码的时候,不要只看“有没有做输入过滤”。看数据从哪来、到哪去、中间经过了谁的信任。攻击链就藏在信任传递的缝隙里。

严正声明

本文所述所有技术内容仅用于已获得明确书面授权的安全测试、研究和教育场景。DOM Clobbering、原型污染、XSS等客户端攻击技术的测试必须在SRC平台或客户授权的资产范围内进行。靶场环境应部署在隔离网络中。未授权扫描、测试、攻击行为违反《中华人民共和国网络安全法》第27条及《刑法》第285条,将承担法律责任。技术无罪,边界是法律。

HTML与JavaScript的暗面:当DOM操作成为渗透测试的武器" 网络安全文章

HTML与JavaScript的暗面:当DOM操作成为渗透测试的武器"

本文深入剖析DOMClobbering与原型污染两类客户端攻击技术,通过CVE-2026-77912、CVE-2026-64638及CVE-2026-65913等真实漏洞案例,揭示HTML标准特性与JavaScript原型链如何被武器化利用,并给出系统性的渗透测试方法论,包括识别DOMsink、追踪数据流、检查净化器配置及测试Clobbering等可操作步骤,强调安全测试须在授权范围内进行。
评论:0   参与:  0