DOM破坏绕过XSSfilter例题

目录

一、什么是DOM破坏

二、例题1

三、多层关系

1.Collection集合方式

 2.标签关系

3.三层标签如何获取

四、例题2

五、例题3

1.代码审计 

2.payload分析


一、什么是DOM破坏

DOM破坏(DOM Clobbering)指的是对网页上的DOM结构进行不当的修改,导致页面行为异常、性能问题、安全风险或其他不良影响的情况。

就是⼀种将 HTML 代码注⼊⻚⾯中以操纵 DOM 并最终更改页面上 JavaScript 行为的技术

这里我们举一些例子就能更好地解释

可以看到打印的结果如下

通过打印<img>标签中的id或者name属性值,我们获取到了整个<img>标签

从中我们也发现了规律,直接打印x,y不管是id还是name都可以打印出来

而通过document来获取x,y只能打印出name属性的标签

window和直接打印的结果是一样的,都可以打印

下面这个例子可以看到cookie开始是空值,然后创建了一个div元素

在div里面添加了<img name=cookie>标签,然后添加到body里面去

这时候再打印cookie,发现变成了<img name="cookie">

这个例子成功地让本来为空值的cookie有了值,而且是我们可以控制的

然而得到一个标签对象并不是我们想要的,有些函数的参数并不是一个对象,而是字符串

这就需要函数在调用自己时,自己本身有一个ToString函数能够转换为字符串,然后让函数执行

所以我们需要一个自身拥有ToString函数的标签,而不是继承父类Object的ToString函数

可以看到一个对象调用父类的toString函数就会返回[object object],所以我们需要一个本身有toString函数的标签

通过下面的脚本过滤出了自身拥有toString函数的标签

HTMLAreaElement()和HTMLAnchorElement(),也就是<textarea>和<a>标签

所以这两个标签我们可以利用

二、例题1

然后我们来看一道例题Ok, Boomer. | XSS Warmups

XSS Game - Ok, Boomer | PwnFunction

这道题通过get参数将内容写入h2标签内,而且有过滤框架DOMPurify

这个过滤框架由安全团队cure53开发,以我们的技术很难绕过

但是注意setTimeout函数内的ok参数

这里的JS代码是没有任何关于ok参数的定义的,所以我们可以使用DOM破坏

构造ok参数,因为setTimeout函数执行字符串,所以需要用到<a>或者<textarea>标签

payload:

<a id=ok href="tel:alert(1)">a</a>

这里因为DOMPurify框架过滤了javascript,所以我们用tel,也可以执行script脚本

三、多层关系

如果我们需要获取一个标签下的子标签的内容,怎么获取呢?可以直接x.y吗?

显然不行,返回undefined 

1.Collection集合方式

既然直接x.y不行,那我们可以用一个集合来做x,然后再获取y

此时x指代了一个集合,既有div也有a标签,然后再获取它的y属性

 

 2.标签关系

要想知道哪些标签能直接调用x.y,可以通过一段代码来获取,但代码有点长,就直接说结果了

  • form---button
  • from---fieldset
  • from---img
  • from---image
  • from---input
  • from---object
  • from---output
  • from---select
  • from---textarea

这九种组合可以直接调用x.y,来获取子标签内容

比如

3.三层标签如何获取

如果有三层标签,就需要要⽤到以上两种技巧来构建了

先分析x.y,x是一个集合,然后获取y,利用了第一种方法--集合方式,获取了第一个form标签

然后x.y.z,因为form和output标签存在关系,可以直接调用y.z,利用了第二种方法--标签关系

最后x.y.z.value就成功拿到output标签内的内容

四、例题2

首先审计代码,data为URL后的hash值,然后创建了一个div标签,把我们输入的hash值放进了div这个标签里面

第一个for循环拿出了div元素的所有后代元素,用el表示

定义了一个空数组attrs

第二个for循环拿出了后代元素的所有属性,用attr表示

然后将属性添加到attrs数组里

第三个for循环拿出了attrs数组里面的属性,用name表示

然后移除掉这个元素的该属性

最后将div添加到body里面去

const data = decodeURIComponent(location.hash.substr(1));
const root = document.createElement('div');
root.innerHTML = data;// 这里模拟了XSS过滤的过程,方法是移除所有属性
for (let el of root.querySelectorAll('*')) {let attrs = [];for (let attr of el.attributes) {attrs.push(attr.name);}for (let name of attrs) {el.removeAttribute(name);}
}document.body.appendChild(root); 

可见这道例题是移除掉我们输入标签的所有属性

既然不能有属性,那直接输入<script>alert(1)</script>不就行了吗

答案是不可以的,因为innerHTML考虑到安全问题将script过滤掉了

这道题可以使用DOM破坏和CSS来触发XSS

直接来看payload

 <style>@keyframes x{}</style><form style="animation-name:x" onanimationstart="alert(1)"><input id=attributes><input id=attributes></form>

首先定义了一个CSS动画@keyframes x{},然后form表单里面调用这个样式

然后属性onanimationstart执行alert,意思是当animation动画开始时执行alert

CSS样式我已经忘得差不多了,但是大概是这样一个意思

我们再看后面的内容,一个form表单内包含两个id属性为attributes的input标签

看到这个id属性值应该能猜到这是什么作用了,没错,它就是用来破坏el.attributes属性的

上面我们说了,form和input标签是由关系的,可以直接调用x.y

所以代码中的el.attributes正好是我们的input标签,那为什么不用一个input标签,而是两个呢?

因为在for循环中el.attributes需要是可迭代的,而一个input标签只是一个对象,所以是不可迭代的

报错如下:

所以我们需要两个input标签来组成一个集合,这时,集合就是可迭代的了

根据代码,首先到style标签,没有属性可删,然后到form标签

因为迭代对象变成了input标签集合,此时attr就变成了undefined,所以attr.name也就不存在

此时attrs数组获取不到form标签里的任何属性,自然下面的for循环也不会删除form表单的任何属性

最后到我们的两个input标签,因为此时目的已经达到,删除了属性也无妨

最后成功绕过

五、例题3

XSS Game - Jason Bourne | PwnFunction

<script>/* Helpers */const bootstrapAlert = (msg, type) => {return (`<div class="alert alert-${type}" role="alert">${DOMPurify.sanitize(msg)}</div>`)}document.getAlert = () => document.getElementById('alerts');
</script><script>/* Welcome */let name = (new URL(location).searchParams.get('name')) || "Pamela Landy";document.write(bootstrapAlert(`<b>Operation Treadstone</b>: Welcome <u>${name}</u>.`, 'info'))
</script><!-- alerts -->
<div id="alerts"></div><script>/* Handle to `#alert` */let alerts = document.getAlert();/* Treadstone Credentials */let identification = Math.random().toString(36).slice(2);let code = Math.floor(Math.random() * 89999 + 10000);/* Default Credentials */DEFAULTS = {};DEFAULTS[identification] = code;
</script><script>/* Optional Comment */if (location.hash) {let comment = document.createComment(decodeURI(location.hash).slice(1));document.querySelector('#alerts').appendChild(comment);}
</script><script>/* Use `DEFAULTS` to init `SECRETS` */SECRETS = DEFAULTS/* Increment the `code` before the check */let secretKey = new URL(location).searchParams.get('key') || "TREADSTONE_WEBB";SECRETS[secretKey] += 1;/* Authorization Check */if (SECRETS[secretKey] === SECRETS[identification]) {confirm(`Jesus Christ, it's Jason Bourne!`)} else {confirm(`You ain't David Webb!`)}
</script>

1.代码审计 

首先代码审计一波

第一个script块

首先定义了一个函数bootstrapAlert(msg,type),返回值是一个div标签里面包含着msg输入的东西,还使用了DOMPurify框架进行过滤

之后又定义了一个函数get.Alert,获取id为alerts的元素

第二个script块

首先通过GET传入name参数,如果没有传,默认Pamela Landy

然后调用bootstrapAlert函数,相当于这样

<div class="alert alert-info" role="alert"><b>Operation Treadstone</b>: Welcome <u>${name}</u>
</div>

然后一个id属性为alerts的div标签

第三个script块

首先将函数getAlert()的返回值赋给alerts

之后生成一个0,1的随机数,再将其转换为36进制的字符串,然后切片,去掉前两个字符

再使用Math.random()*89999+10000生成一个10000到89999的随机数赋给code

然后定义了一个DEFAULTS空对象

最后将code赋值给DEFAULTS对象里的identification属性

第四个script块

如果存在location.hash值

那就去掉前面的#号,将hash值取出来,然后以改内容创建注释赋值给comment

最后找到id属性为alerts的标签,将comment添加为它的子元素

第五个script块

首先把对象DEFAULTS赋给SECRETS

之后找到GET参数key,将它赋给secretKey,如果不存在默认为"TREADSTONE_WEBB"

并将secretKey值加1作为属性赋给SECRETS对象

然后if判断SECRETS[secretKey]与SECRETS[identification]是否相等

2.payload分析

初步分析下来我们可以传入三个参数,name、key、location.hash值

由于太菜,自己想了几十分钟没头绪,只有看答案来分析

?name=<img name=getAlert><form id=alerts name=DEFAULTS>&key=innerHTML#--><img src onerror=alert(1337)>

首先传入了一个<img name=getAlert>标签,上面提到getAlert是一个函数

然后传入了一个<form id=alerts name=DEFAULTS>,id和name属性都存在

key传入了innerHTML,可能是想构造.innerHTML,让标签传入

最后传入--><img src οnerrοr=alert(1337)>,前面的-->很有可能是用来闭合注释的

首先解释为什么要传入一个name属性为函数名的标签,是因为想让第三个script块报错

我们是先传入的name,getAlert函数在后面被调用,所以我们可以直接覆盖getAlert函数

此时getAlert就不是一个函数了,而是我们传入的标签,所以就会报错

这样一来整个第三个script代码块就都不会执行

那为什么要让它报错呢?因为报错后,DEFAULTS对象就定义不了

这样一来SECRETS变量就不会被赋值,而是接到我们的form标签,接到我们的标签那就简单了

传入的key值的主要作用是让SECRETS[secretKey]=form.innerHTML,触发我们的弹窗

这段代码很关键,作用是让我们的comment成为id属性为alerts的标签的子标签

document.querySelector('#alerts').appendChild(comment);

而此时的alerts有两个,一个是我们传入的form,还有一个是代码中的div,但是我们是先传入的form,标签顺序在div之前,所以appendChild只会将内容添加到第一个标签内

比如这里,拥有同样id属性的form和div标签,因为form标签在div标签前面,所以被添加了子节点

comment被添加到form后还有一个问题,我认为也是最难理解的,看下面两张图

这张图是没有添加key=innerHTML参数的

这张图是添加了key=innerHTML参数的

前面讲到SECRETS[secretKey]=form.innerHTML,那按照代码来是这样的

form.innerHTML=form.innerHTML+1,关键是这个1的作用是什么?

我的理解是当传入--><img src οnerrοr=alert(1)>时,前面的注释确实是闭合了,但是后面还有一个-->

此时如果没有1,那么-->就会跟在标签后面,而注释会选择最后的-->,所以img标签还是注释没有生效

如果有1,html会认为"-->1"是一个字符串,会换行到下一行,这样img标签就不会被注释掉了

最后触发弹窗

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go实现LogAgent:海量日志收集系统【上篇——LogAgent实现】

Go实现LogAgent 项目架构图&#xff1a; 0 项目背景与方案选择 背景 当公司发展的越来越大&#xff0c;业务越来越复杂时&#xff0c;每个业务系统都有自己的日志。此时我们就应该将不同业务线的日志进行实时收集&#xff0c;存储到一个日志收集中心&#xff0c;最后再通过…

Qt应用开发(基础篇)——错误提示框 QErrorMessage

一、前言 QErrorMessage类继承于QDialog&#xff0c;是一个用来显示错误信息的对话框。 提示框QDialog 消息对话框 QMessageBox QErrorMessage错误消息对话框提供了一个主文本窗口、一个复选框、一个图标和按钮。文本框用来显示错误信息&#xff0c;复选框用来让用户选择未来是…

【100天精通python】Day50:python web编程_Django框架使用

目录 1 安装Django Web框架 2 创建一个Django 项目 3 数据模型 3.1 在应用程序的 models.py 文件中定义数据模 3.2 创建模型的迁移文件并应用 3.2.1 查询模型对象&#xff1a; 3.2.2 创建新模型对象&#xff1a; 3.2.3 更新模型对象&#xff1a; 3.2.4 删除模型对象&a…

Uniapp笔记(五)uniapp语法4

本章目标 授权登录【难点、重点】 条件编译【理解】 小程序分包【理解】 一、授权登录 我的模块其实是两个组件&#xff0c;一个是登录组件&#xff0c;一个是用户信息组件&#xff0c;根据用户的登录状态判断是否要显示那个组件 1、登录的基本布局 <template><…

Redis功能实战篇之Session共享

1.使用redis共享session来实现用户登录以及token刷新 当用户请求我们的nginx服务器&#xff0c;nginx基于七层模型走的事HTTP协议&#xff0c;可以实现基于Lua直接绕开tomcat访问redis&#xff0c;也可以作为静态资源服务器&#xff0c;轻松扛下上万并发&#xff0c; 负载均衡…

Revit SDK 介绍:AutoStamp 自动水印 AutoUpdate 自动更新 CancelSave

前言 这三个例子都是通过注册事件来完成相应的工作&#xff0c;内容比较简单。 内容 事件参考博客&#xff1a;Revit API&#xff1a;Events 事件总览 AutoStamp 自动水印 使用到的事件&#xff1a; application.ControlledApplication.ViewPrinting application.Controll…

数据结构之树型结构

相关概念树的表示二叉树二叉树性质二叉树储存 实现一颗二叉树创建遍历&#xff08;前中后序&#xff09;获取树中节点个数获取叶子节点个数获取第k层节点个数获取二叉树高度检测值为value元素是否存在层序遍历&#xff08;需要队列来实现&#xff09;判断是否为完全二叉树&…

使用Spring Boot和Kafka实现消息发送和订阅

文章目录 一&#xff0c;新建Spring Boot1&#xff0c;Maven配置2&#xff0c;无法识别为SpringBoot项目3&#xff0c;无效的源发行版4&#xff0c;无法访问SpringApplication5&#xff0c;运行直接Finish6&#xff0c;服务运行成功 二&#xff0c;安装启动Kafka1&#xff0c;下…

ROS 2官方文档(基于humble版本)学习笔记(二)

ROS 2官方文档&#xff08;基于humble版本&#xff09;学习笔记&#xff08;二&#xff09; 理解节点&#xff08;node&#xff09;ros2 runros2 node list重映射&#xff08;remap&#xff09;ros2 node info 理解话题&#xff08;topic&#xff09;rqt_graphros2 topic listr…

visual studio编写DLL,python调用

选择第一个c DLL&#xff0c; 然后项目源文件下右击新建项&#xff0c;这里名字随便取&#xff0c;在代码中输入一下内容&#xff1a; #include <iostream>#define EXPORT extern "C" __declspec(dllexport)EXPORT int sub(int a, int b) {return a - b; } 在…

【JS案例】JS实现积分抽奖(内附源码)

JS案例实现积分抽奖 &#x1f31f;效果展示 &#x1f31f;HTML结构 &#x1f31f;CSS样式 &#x1f31f;实现思路 &#x1f31f;具体实现 1.定义抽奖次数渲染 2.点击抽奖按钮,实现滚动抽奖效果 3.弹窗处理 &#x1f31f;完整代码 &#x1f31f;写在最后 &#x1f3…

docker安装jenkins

1.查看Jenkins LTS 版本 Jenkins官网&#xff1a;https://www.jenkins.io/zh/download/ 2.拉取jenkins镜像 docker pull jenkins/jenkins:2.346.13.创建挂载数据卷 创建/home/software/jenkins/jenkins_home文件夹 mkdir /home/software/jenkins/jenkins_home赋予/home/so…

Ubuntu20以上高版本如何安装低版本GCC

安装了Ubuntu 20.04之后&#xff0c;通过命令行 sudo apt-get install build-essential安装gcc&#xff0c;再通过命令行 gcc -v可查看gcc版本为gcc13 如果想用低版本的gcc&#xff0c;比如gcc4.8&#xff0c;尝试输入命令 sudo apt-get install gcc-4.8会提示找不到gcc4.8的…

0基础学习VR全景平台篇 第93篇:智慧景区教程

一、上传素材 1.上传全景素材 第一步&#xff1a;进入【素材管理】 第二步&#xff1a;选择【全景图智慧景区】分类 第三步&#xff1a;选择相对景区作品分组&#xff0c;上传全景素材 2.素材标注 第一步&#xff1a;选择上传成功后素材&#xff0c;点击【未标注】 第二步&…

HTTP与SOCKS5的区别对比

在互联网世界中&#xff0c;服务器是一种重要的工具&#xff0c;可以帮助我们提高网络安全性等。今天&#xff0c;我们将重点关注两种常见的技术&#xff1a;HTTP和SOCKS5。让我们深入了解它们的工作原理、用途和优缺点&#xff0c;并通过Python代码示例学习如何使用它们。 HT…

微信小程序 - 2023年最新版手机号快捷登录详细教程

前言 最近开发公司手机快捷登录的功能&#xff0c;花费了不少时间&#xff0c;这里附上详细教程。 这里以海底捞小程序的图片为例&#xff0c;如有侵权请联系小编删除。 代码如下 <button open-type"getPhoneNumber" getphonenumber"getPhoneNumber"…

java+springboot+mysql校园跑腿管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的校园跑腿管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;用户管理&#xff08;充值&#xff09;&#xff1b;任…

全新UI站长在线工具箱系统源码带后台开源版

该系统的全开源版本可供下载&#xff0c;并且支持暗黑模式。 系统内置高达72种站长工具、开发工具、娱乐工具等功能。此系统支持本地调用API&#xff0c;同时还自带免费API接口&#xff0c; 是一个多功能性工具程序&#xff0c;支持后台管理、上传插件、添加增减删功能。 环…

【Python】Web学习笔记_flask(7)——Jinja2模板(1)

Jinja2是基于python的模板引擎&#xff0c;功能类似于PHP的amarty、J2ee的Freemarker和velocity&#xff0c;完全支持Unicode&#xff0c;并具有集成的沙箱执行环境&#xff0c;Jinja2使用的事BSD协议&#xff0c;允许使用者修改和重新发布代码&#xff0c;也允许使用或在BSD代…

kafka 命令脚本说明以及在java中使用

一、命令行使用 1.1、topic 命令 1、关于topic,这里用window 来示例 bin\windows\kafka-topics.bat2、创建 first topic,五个分区&#xff0c;1个副本 bin\windows\kafka-topics.bat --bootstrap-server localhost:9092 --create --partitions 5 --replication-factor 1 -…