You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于BeautifulSoup4区分文本与HTML元素,拆分XSS payload结构

可行的拆分方案:基于DOM解析的结构化提取

你遇到的核心问题其实是字符串匹配无法区分“属性内的HTML内容”和“真正的DOM元素”,直接用正则或者字符串切割很容易被payload里的特殊字符(比如<>)或者嵌套结构坑。靠谱的做法是先把这段HTML转换成DOM树,再按规则遍历提取,这样能精准区分元素、属性、属性值(包括带HTML的payload)。

核心思路

  1. 用DOM解析替代字符串处理:不管payload里是纯文本还是包含HTML片段,DOM解析都会把属性值当成完整的字符串,不会把属性里的<script>之类的当成新的DOM节点。
  2. 遍历DOM树的规则:
    • 遇到元素节点:先提取标签名(统一小写,符合HTML规范)
    • 遍历元素的所有属性:依次提取属性名和属性值
    • 只遍历元素子节点中的元素节点:元素内的文本节点(比如<div>xxx</div>里的xxx)如果不是你需要的,可以直接跳过,避免干扰属性值的提取。

具体实现示例(JavaScript)

不管是在浏览器控制台还是Node.js环境(用jsdom模拟DOM),都可以用这个思路实现:

浏览器环境代码

function extractXssStructure(html) {
  const parser = new DOMParser();
  const doc = parser.parseFromString(html, 'text/html');
  const output = [];

  // 递归遍历DOM节点
  function traverse(node) {
    if (node.nodeType === Node.ELEMENT_NODE) {
      // 加入元素标签名
      output.push(node.tagName.toLowerCase());
      
      // 遍历所有属性,加入属性名和属性值
      Array.from(node.attributes).forEach(attr => {
        output.push(attr.name.toLowerCase());
        output.push(attr.value);
      });

      // 只遍历子元素节点,跳过文本节点(避免提取元素内的无关文本)
      Array.from(node.childNodes).forEach(child => {
        if (child.nodeType === Node.ELEMENT_NODE) {
          traverse(child);
        }
      });
    }
  }

  // 从解析后的body第一个子节点开始遍历
  traverse(doc.body.firstChild);
  return output.join(' ');
}

// 测试示例1:基础payload
const basicHtml = '<picture><source srcset="x"><img onerror="***payload***"></picture>';
console.log(extractXssStructure(basicHtml));
// 输出:picture source srcset x img onerror ***payload***

// 测试示例2:payload包含HTML片段
const htmlWithHtmlPayload = '<picture><source srcset="x"><img onerror="<script>alert(1)</script>"></picture>';
console.log(extractXssStructure(htmlWithHtmlPayload));
// 输出:picture source srcset x img onerror <script>alert(1)</script>

Node.js环境(需要安装jsdom)

先安装依赖:npm install jsdom,然后代码:

const { JSDOM } = require('jsdom');

function extractXssStructure(html) {
  const dom = new JSDOM(html);
  const doc = dom.window.document;
  const output = [];

  function traverse(node) {
    if (node.nodeType === node.ELEMENT_NODE) {
      output.push(node.tagName.toLowerCase());
      Array.from(node.attributes).forEach(attr => {
        output.push(attr.name.toLowerCase());
        output.push(attr.value);
      });
      Array.from(node.childNodes).forEach(child => {
        if (child.nodeType === node.ELEMENT_NODE) {
          traverse(child);
        }
      });
    }
  }

  traverse(doc.body.firstChild);
  return output.join(' ');
}

// 测试同浏览器环境

关键注意点

  • 不要解析属性值内的HTML:DOM解析会自动把属性值当成字符串,所以就算payload里有<>这类字符,也会完整保留,不会被当成新的DOM节点处理,完美解决你说的“追加子元素内容异常”的问题。
  • 统一大小写:HTML标签和属性名不区分大小写,转换成小写后输出更规范。
  • 跳过无关文本节点:如果你的payload结构里偶尔有元素内的文本(比如<div>test <img onerror="..."></div>),可以根据需求决定是否提取文本——只需要在遍历子节点时加入文本节点的处理逻辑即可。

内容的提问来源于stack exchange,提问作者Login

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:34:53