HTML环境下如何实现插入的JavaScript代码执行以搭建XSS测试站点
问题原因
浏览器遵循HTML5规范默认拦截通过innerHTML、insertAdjacentHTML等API插入的<script>标签解析执行,这是内置的基础安全防护逻辑。你之前尝试的appendChild()、insertAdjacentElement()如果直接传入字符串内容而非构造好的可执行DOM节点,同样无法触发脚本执行;eval()未生效是因为没有正确提取待执行的脚本内容传入。
可实现脚本执行的方案
无需额外处理,直接用innerHTML即可触发的XSS向量
绝大多数真实场景的XSS攻击不需要插入<script>标签,利用HTML元素的事件属性即可直接执行代码,你直接用现有innerHTML逻辑插入以下payload就会触发执行:
- 图片加载错误触发:
<img src="null" onerror="alert('XSS触发')"> - SVG加载触发:
<svg onload="alert('XSS触发')"> - 伪链接触发:
<a href="javascript:alert('XSS触发')">点击触发</a> - body事件触发:
<body onload="alert('XSS触发')">
强制让插入的script标签执行的实现
注意:以下实现存在严重安全风险,仅可用于本地漏洞测试场景,绝对不能部署到公网可访问的环境中
如果你需要让用户输入的<script>标签内容也能正常执行,不能直接插入HTML字符串,需要手动构造可执行的script DOM节点替换原有静态标签,参考实现代码:
// 不安全的渲染函数,仅用于XSS测试场景 function unsafeRender(container, userInput) { container.innerHTML = userInput; // 提取所有插入的script标签,替换为可执行的真实DOM节点 const scriptList = container.querySelectorAll('script'); scriptList.forEach(oldScript => { const newScript = document.createElement('script'); // 复制原script标签的所有属性(比如src、type等) Array.from(oldScript.attributes).forEach(attr => { newScript.setAttribute(attr.name, attr.value); }); // 复制内联脚本内容 newScript.textContent = oldScript.textContent; // 替换节点后脚本会立即执行 oldScript.replaceWith(newScript); }); }
你现有的渲染逻辑只需要把原来的post.innerHTML += localStorage.key(0);替换为unsafeRender(post, localStorage.key(0));即可。
补充说明
如果要通过eval()实现执行,需要手动提取用户输入中所有script标签的文本内容、以及带javascript:伪协议的属性内容传入eval,处理逻辑比上面的节点替换方案繁琐很多,不推荐使用。
内容的提问来源于stack exchange,提问作者teres
相关产品推荐
相关产品推荐

