Clobbering DOM attributes to bypass HTML filters

news2024/9/22 1:11:31

目录

寻找注入点

代码分析

payload构造

注入结果


寻找注入点

DOM破坏肯定是出现在js文件中,我们首先来看源码

 /resources/labheader/js/labHeader.js这个源码没什么问题我们重点关注在下面两个源码上

/resources/js/loadCommentsWithHtmlJanitor.js这个源码中重要的输入输出都被Htmlhanitor进行了一个过滤,也没有办法,接下来我们把目光移到最后一个代码上

/resources/js/htmlJanitor.js

代码分析

/resources/js/htmlJanitor.js代码分析

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
      define('html-janitor', factory);
    } else if (typeof exports === 'object') {
      module.exports = factory();
    } else {
      root.HTMLJanitor = factory();
    }
  }(this, function () {
  
    /**
     * @param {Object} config.tags Dictionary of allowed tags.
     * @param {boolean} config.keepNestedBlockElements Default false.
     */
    function HTMLJanitor(config) {
  
      var tagDefinitions = config['tags'];
      var tags = Object.keys(tagDefinitions);
  
      var validConfigValues = tags
        .map(function(k) { return typeof tagDefinitions[k]; })
        .every(function(type) { return type === 'object' || type === 'boolean' || type === 'function'; });
  
      if(!validConfigValues) {
        throw new Error("The configuration was invalid");
      }
  
      this.config = config;
    }

  //   config: 配置对象,包含允许的标签及其属性定义。
// tagDefinitions: 从配置中提取的标签定义。
// tags: 标签定义的键名数组。
// validConfigValues: 检查所有标签定义的值是否为合法的类型(object、boolean 或 function)。
// 如果配置无效,则抛出错误。否则,将配置存储在实例中
    var blockElementNames = ['P', 'LI', 'TD', 'TH', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'PRE'];
    function isBlockElement(node) {
      return blockElementNames.indexOf(node.nodeName) !== -1;
    }
//   blockElementNames: 规定了哪些标签是块级元素。
//   isBlockElement: 判断节点是否为块级元素。
 
    var inlineElementNames = ['A', 'B', 'STRONG', 'I', 'EM', 'SUB', 'SUP', 'U', 'STRIKE'];
    function isInlineElement(node) {
      return inlineElementNames.indexOf(node.nodeName) !== -1;
    }
  
   // inlineElementNames: 规定了哪些标签是行内元素。
   // isInlineElement: 判断节点是否为行内元素。

    HTMLJanitor.prototype.clean = function (html) {
      const sandbox = document.implementation.createHTMLDocument('');
      const root = sandbox.createElement("div");
      root.innerHTML = html;
  
      this._sanitize(sandbox, root);
  
      return root.innerHTML;
    };
 // 处理 HTML 字符串,将其插入到一个新的 HTML 文档中,然后调用 _sanitize 方法来清理 HTML,最后返回处理后的 HTML 字符串
    HTMLJanitor.prototype._sanitize = function (document, parentNode) {
      var treeWalker = createTreeWalker(document, parentNode);
//创建一个 TreeWalker 实例,用于遍历 parentNode 的子节点。
      var node = treeWalker.firstChild();
  //获取第一个节点
      if (!node) { return; }
  //如果没有节点就返回
      do {
        if (node.nodeType === Node.TEXT_NODE) {
          // If this text node is just whitespace and the previous or next element
          // sibling is a block element, remove it
          // N.B.: This heuristic could change. Very specific to a bug with
          // `contenteditable` in Firefox: http://jsbin.com/EyuKase/1/edit?js,output
          // FIXME: make this an option?
          if (node.data.trim() === ''
              && ((node.previousElementSibling && isBlockElement(node.previousElementSibling))
                   || (node.nextElementSibling && isBlockElement(node.nextElementSibling)))) {
            parentNode.removeChild(node);
            this._sanitize(document, parentNode);
            break;
          } else {
            continue;
          }
        }
//对于空白文本节点(tirm就是用来处理字符串让其没有空白节点),检查其是否位于块级元素的前后。如果是,则移除该文本节点,并递归调用 _sanitize 以处理 parentNode 重新遍历。处理完后,停止当前循环(break)
  
        // Remove all comments
        if (node.nodeType === Node.COMMENT_NODE) {
          parentNode.removeChild(node);
          this._sanitize(document, parentNode);
          break;
        }
//移除注释节点,并递归调用 _sanitize 处理 parentNode。处理完后,停止当前循环
        var isInline = isInlineElement(node);
        var containsBlockElement;
        if (isInline) {
          containsBlockElement = Array.prototype.some.call(node.childNodes, isBlockElement);
        }
  
        // Block elements should not be nested (e.g. <li><p>...); if
        // they are, we want to unwrap the inner block element.
        var isNotTopContainer = !! parentNode.parentNode;
        var isNestedBlockElement =
              isBlockElement(parentNode) &&
              isBlockElement(node) &&
              isNotTopContainer;
        var nodeName = node.nodeName.toLowerCase();
  
        var allowedAttrs = getAllowedAttrs(this.config, nodeName, node);
  
        var isInvalid = isInline && containsBlockElement;
  //   检查节点是否为行内元素(isInline)。
//   如果是行内元素,检查其子节点是否包含块级元素(containsBlockElement)。
//   检查节点是否为非顶级容器(isNotTopContainer)。
//   检查是否为嵌套的块级元素(isNestedBlockElement)。
//   获取节点的允许属性列表(allowedAttrs)。
//   判断是否无效(isInvalid):如果是行内元素且包含块级元素。
        if (isInvalid || shouldRejectNode(node, allowedAttrs)
            || (!this.config.keepNestedBlockElements && isNestedBlockElement)) {
          // Do not keep the inner text of SCRIPT/STYLE elements.
          if (! (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE')) {
            while (node.childNodes.length > 0) {
              parentNode.insertBefore(node.childNodes[0], node);
            }
          }
          parentNode.removeChild(node);
  
          this._sanitize(document, parentNode);
          break;
        }
  
//   如果节点无效、应该被拒绝,或是嵌套的块级元素且配置不允许嵌套,则:

//   如果节点不是 SCRIPT 或 STYLE,将其子节点移到 parentNode 中。
//   移除该节点。
//   递归调用 _sanitize 处理 parentNode,然后停止当前循环(break)
        // Sanitize attributes
        for (var a = 0; a < node.attributes.length; a += 1) {
          var attr = node.attributes[a];
  
          if (shouldRejectAttr(attr, allowedAttrs, node)) {
            node.removeAttribute(attr.name);
            // Shift the array to continue looping.
            a = a - 1;
          }
        }
  //遍历节点的所有属性,并根据允许的属性列表决定是否移除属性。如果属性应该被拒绝,则移除该属性,并调整索引以重新检查移除后的属性
        // Sanitize children
        this._sanitize(document, node);
  
      } while ((node = treeWalker.nextSibling()));
    };
  
    function createTreeWalker(document, node) {
      return document.createTreeWalker(node,
                                       NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT,
                                       null, false);
    }
  // node: 指定 TreeWalker 遍历的起始节点。

// NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT: 这是一个位掩码(bitmask),指定了 TreeWalker 应该包括哪些类型的节点。它包括:
//     NodeFilter.SHOW_TEXT: 过滤文本节点。
//     NodeFilter.SHOW_ELEMENT: 过滤元素节点。
//     NodeFilter.SHOW_COMMENT: 过滤注释节点。

// 使用 | 运算符将这些常量合并成一个位掩码,使 TreeWalker 可以遍历这些节点类型。

// null: 这是一个 NodeFilter 对象,用于定义哪些节点应该被包含或排除。设置为 null 表示不使用自定义的过滤条件,即所有符合上述类型的节点都会被遍历。

// false: 指定 TreeWalker 是否应处理实体(例如字符实体)。设置为 false 表示不处理实体,这通常在处理普通文本和节点时不需要考虑。
    function getAllowedAttrs(config, nodeName, node){
      if (typeof config.tags[nodeName] === 'function') {
        return config.tags[nodeName](node);
      } else {
        return config.tags[nodeName];
      }
    }
 // 获取允许的属性集合
    function shouldRejectNode(node, allowedAttrs){
      if (typeof allowedAttrs === 'undefined') {
        return true;
      } else if (typeof allowedAttrs === 'boolean') {
        return !allowedAttrs;
      }
  
      return false;
    }
  // 判断节点是否应该被拒绝
    function shouldRejectAttr(attr, allowedAttrs, node){
      var attrName = attr.name.toLowerCase();
  
      if (allowedAttrs === true){
        return false;
      } else if (typeof allowedAttrs[attrName] === 'function'){
        return !allowedAttrs[attrName](attr.value, node);
      } else if (typeof allowedAttrs[attrName] === 'undefined'){
        return true;
      } else if (allowedAttrs[attrName] === false) {
        return true;
      } else if (typeof allowedAttrs[attrName] === 'string') {
        return (allowedAttrs[attrName] !== attr.value);
      }
  
      return false;
    }
  //判断属性是否应该被拒绝
    return HTMLJanitor;
  
  }));

payload构造

重点在这里,如果传递的参数是黑名单就删掉,只有form和input在,然后我们可以看一下这道题portswigger的Exploiting DOM clobbering to enable XSS-CSDN博客里面的第二道题有一块和下面的漏洞点很是相像。接着往下看

分析过后整体代码中行内元素的内嵌不可以是用那我们使用不是行内元素的元素,

使用这个元素<from><input>,我们就逃过了,然后我们构造的这个标签又没有父类,又绕过了

然后我们到这里看,我们构造<form><input id=attributes>,然后我们绕过以后form的attributes属性就是<input id=attributes>这个然后如果这个没有length属性就会跳出下面循环,然后就不删除了

然后经过上面的分析我们就要找一个标签没有length属性,让他跳出上面的for循环,所以就使用我们这个喽,然后在form里面构造我们的注入语句

<form tabindex=0 onfocus=alert(123)><input id=attributes>

注入结果

上面的payload是点击tab才可以触发,使用tabindex属性,已经插入进去了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2051537.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从关键新闻和最新技术看AI行业发展(第二十九期2024.7.29-8.11) |【WeThinkIn老实人报】

写在前面 【WeThinkIn老实人报】旨在整理&挖掘AI行业的关键新闻和最新技术&#xff0c;同时Rocky会对这些关键信息进行解读&#xff0c;力求让读者们能从容跟随AI科技潮流。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&#x1f4aa; 欢迎大家关注Rocky的公众号&…

docker 安装mino服务,启动报错: Fatal glibc error: CPU does not support x86-64-v2

背景 docker 安装mino服务&#xff0c;启动报错&#xff1a; Fatal glibc error: CPU does not support x86-64-v2 原因 Docker 镜像中的 glibc 版本要求 CPU 支持 x86-64-v2 指令集&#xff0c;而你的硬件不支持。 解决办法 降低minio对应的镜像版本 经过验证&#xff1a;qu…

sanic + webSocket:股票实时行情推送服务实现

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

Linux中的内核编程

Linux内核是操作系统的核心组件&#xff0c;负责管理系统的资源、提供硬件抽象和执行系统调用。内核编程是一项涉及操作系统核心的高级任务&#xff0c;它允许开发人员直接与系统内核进行交互&#xff0c;实现更高效、更特定的功能。本文将深入探讨Linux中的内核编程&#xff0…

2021年上半年网络工程师考试上午真题

2021年上半年网络工程师考试上午真题 网络工程师历年真题含答案与解析 第 1 题 以下关于RISC和CISC计算机的叙述中&#xff0c;正确的是&#xff08; &#xff09;。 (A) RISC不采用流水线技术&#xff0c;CISC采用流水线技术(B) RISC使用复杂的指令&#xff0c;CISC使用简…

事件驱动架构的事件版本管理

有一种办法&#xff1a;发送会议邀请给所有团队&#xff0c;经过101次会议后&#xff0c;发布维护横幅&#xff0c;所有人同时点击发布按钮。或... 可用适配器&#xff0c;但微调。没错&#xff01;就像软件开发中90%问题一样&#xff0c;有种模式帮助你找到聪明解决方案。 1…

C Primer Plus(中文版)第13章编程练习,仅供参考

第十三章编程练习 对于文件的操作是程序开发过程中必不可少的。首先&#xff0c;来看一下第一题&#xff0c;对13.1程序进行修改&#xff0c;输入文件名&#xff0c;而不是命令行参数。完整程序代码以及运行结果如下&#xff1a; #include<stdio.h> #include<stdlib…

【数据结构篇】~单链表(附源码)

【数据结构篇】~链表 链表前言链表的实现1.头文件2.源文件 链表前言 链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 1、链式机构在逻辑上是连续的&#xff0c;在物理结构上不一定连续​ 2、结点一般是从…

Java二十三种设计模式-命令模式(18/23)

命令模式&#xff1a;将请求封装为对象的策略 概要 本文全面探讨了命令模式&#xff0c;从基础概念到实现细节&#xff0c;再到使用场景、优缺点分析&#xff0c;以及与其他设计模式的比较&#xff0c;并提供了最佳实践和替代方案&#xff0c;旨在帮助读者深入理解命令模式并…

【xr-frame】微信小程序xr-frame典型案例

微信小程序xr-frame典型案例 在之前的工作中&#xff0c;我大量使用XR-Frame框架进行AR开发&#xff0c;并积累了一些案例和业务代码。其中包括2D图像识别、手部动作识别、Gltf模型加载、动态模型加载、模型动画等内容。小程序部分使用TypeScript编写&#xff0c;而XR-Frame组…

利用puppeteer将html网页生成图片

1.什么是puppeteer&#xff1f; Puppeteer是一个Node库&#xff0c;它提供了一个高级API来通过DevTools协议控制Chromium或Chrome。 可以使用Puppeteer来自动化完成浏览器的操作&#xff0c;官方给出的一些使用场景如下&#xff1a; 生成页面PDF抓取 SPA&#xff08;单页应用…

3.Windows Login Unlocker-忘记电脑密码也可以解决

想要解锁Windows系统的开机密码&#xff0c;但官网的传统方法只适合Windows本地账户&#xff0c;对微软账户或PIN码()束手无策&#xff1f;别担心&#xff0c;小编之前推荐过的「Windows Login Unlocker」软件能为您排忧解难。这款出色的工具不仅能够轻松绕过各种Windows密码&a…

C语言-写一个用矩形法求定积分的通用函数,分别求积分区间为[0,1]sinx,cosx,e的x方的定积分

一、题目要求&#xff1a; 二、思路 ①数学方面:矩形法求定积分的公式 将积分图形划分成为指定数量的矩形&#xff0c;求取各个矩形的面积&#xff0c;然后最终进行累加得到结果 1.积分区间: [num1, num2] 2.分割数量:count 每个矩形的边长:dx(num2-num1)/count 3.被积分…

智慧草莓基地管理系统--论文pf

TOC springboot359智慧草莓基地管理系统--论文pf 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xf…

泰安鲁菜根普照店重装开业:传承与创新并举 品味舌尖上的泰安

8月17日&#xff0c;泰安鲁菜根普照店重装开业。店内装修以泰山文化为主题&#xff0c;营造出一种浓郁的地方文化特色氛围。这家以泰山文化为底蕴&#xff0c;以大汶河传统民俗食材为基础的餐饮企业&#xff0c;一直致力于发掘和传承泰山周边及汶河两岸的传统特色美食&#xff…

【漫谈C语言和嵌入式009】探索LVDT:线性可变差动变压器的工作原理与应用

引言 在现代工业和工程领域中&#xff0c;精确的位移测量是许多系统正常运行的关键。线性可变差动变压器&#xff08;LVDT, Linear Variable Differential Transformer&#xff09;是一种广泛使用的位移传感器&#xff0c;因其高精度、可靠性和耐用性在各种应用中得到了普遍认可…

iOS(OC)学习第1天-怎么设置UI

xCode 版本为 新建工程 xCode->iOS->App->输入工程名称 项目结构 storyboard文件&#xff1a;可以通过拖动方式添加UI的UI布局文件&#xff0c;理解为Android的XML布局文件 名字说明Main.storyboard首页LaunchScreen.storyboard引导页 添加布局 引导页 设置组件的属…

复现DOM破坏案例

准备工作&#xff1a; 做好代理然后访问靶场 XSS Game - Learning XSS Made Simple! | Created by PwnFunction 第一关 Ma Spaghet! 这是源代码部分&#xff1a; <!-- Challenge --> <h2 id"spaghet"></h2> <script> spaghet.innerHTM…

【推荐100个unity插件之25】使用Vroid进行二次元建模,并在unity中使用VRM模型——URP-UniVrm插件的使用

最终效果 文章目录 最终效果什么是Vriod官网地址下载安装使用导出模型unity使用VRM模型导入URP-UniVrm插件 Blender使用Blender安装Cats Blender Plugin 插件Blender安装VRM-Addon-for-Blender插件导入VRM模型导出为FBX模型 使用别人的VRM模型完结 什么是Vriod 如果你玩过能捏…

经典动作手机游戏:《艾希》安卓手机游戏下载

《艾希手游》是一款以女性为主角的游戏&#xff0c;玩家在游戏中将扮演主角艾希&#xff0c;在各种场景中进行冒险&#xff0c;探索剧情和解开谜题。这款游戏的画面精美&#xff0c;操作简单易上手&#xff0c;同时提供了丰富的剧情和多样的玩法。 下载地址&#xff1a;https:/…