目录
一、OK,Boomer
一、网址:
二、源码分析:
三、 解决思路:
1.页面中的元素可以通过id和name直接取出来
2.覆盖
3.覆盖方法
四、ToString
五、setTimeout函数
六、使用框架白名单
七、成功绕过
编辑 二、案例分析
一、源码分析:编辑
二、属性未全部移除
三、原因
四、成功绕过
五、修复
六、解决方法:
一、OK,Boomer
一、网址:
XSS Game - Learning XSS Made Simple! | Created by PwnFunction
二、源码分析:
<!-- Challenge -->
<h2 id="boomer">Ok, Boomer.</h2>
<script>
boomer.innerHTML = DOMPurify.sanitize(new URL(location).searchParams.get('boomer') || "Ok, Boomer")
setTimeout(ok, 2000)
</script>
通过源码分析,用户可控参数为boomer,那我们首先试着在该参数上使用img标签
?boomer=<img%20src=1%20οnerrοr="alert(1)">
但是没有任何反应,通过F12查看,发现img标签里面只有“src=1”,οnerrοr=”alert(1)”被丢弃了,原因是存在DOMPurify.sanitize过滤框架,并且该框架绕过几率几乎很小。
setTimeout(ok, 2000)---定时器,正常情况下 2秒后执行一个ok,但在这里执行不了,没有这个ok,执行了一个完全不存在的。
三、 解决思路:
1.页面中的元素可以通过id和name直接取出来
Document.cookie
<img name=”cookie”>
本来是想通过Document.cookie取出cookie,但是却取出来了一个标签
说明:页面中的元素可以通过id和name直接取出来
2.覆盖
- 首先使用Document.cookie取出cookie,但这里没有cookie所以没取到。
- 创建div元素,并在div元素中写入<img name=cookie>
- 将div元素插入到body中去
- 重新获取cookie,发现取出的是img标签
可以看到Document.cookie已经被我们用img标签覆盖了
3.覆盖方法
实际上Document.body取到的是<img id=”appendChild”>,说明我们通过多层覆盖掉了Document.body.appendChild方法。
既然我们可以通过这种⽅式去创建或者覆盖 document 或者 window 对象的某些值,但是看起来我们 举的例⼦只是利⽤标签创建或者覆盖最终得到的也是标签,是⼀个HTMLElment 对象。
但是对于⼤多数情况来说,我们可能更需要将其转换为⼀个可控的字符串类型,以便我们进⾏操作。
四、ToString
所以我们可以通过以下代码来进⾏fuzz 得到可以通过toString ⽅法将其转换成字符串类型的标签:
Object.getOwnPropertyNames(window) // 拿到window下面所有属性名称
.filter(p => p.match(/Element$/)) //过滤,只要后缀为Element的
.map(p => window[p]) //取值,map一个一个的取
.filter(p => p && p.prototype && p.prototype.toString
!== Object.prototype.toString)//必须具有自身prototype属性,并且自身具有tostring方法,并且不是继承object的
我们可以得到两种标签对象:HTMLAreaElement (<area>) & HTMLAnchorElement (<a>),这两个 标签对象我们都可以利⽤href 属性来进⾏字符串转换
五、setTimeout函数
可以吧函数当字符串放进去,那么就可以用a标签来解决
?Boomer=<a id=ok href=”javascript:alert(1)”>
六、使用框架白名单
但是同样没有任何反应,原因是还是没有绕过这个框架,javascript对于这个框架是一个黑名单,所以使用框架里面的白名单即可。
七、成功绕过
二、案例分析
一、源码分析:
将data插到div里, 获取div里面的子函数,拿到标签里面的所有属性,然后将属性进行移除。
二、属性未全部移除
但是并没有将所有属性移除,为什么会出现这种情况
三、原因
这是因为它的属性移除是在同一个数组上操作的,假如这个数组里有a、b、c三个 属性,当将a删除后,指针会往下走一步,但是由于第一位的a被删除,那么b会往上移一位,所以b不会被删除。
四、成功绕过
那么想绕过这个过滤就很简单了,将paylod写在第二位或者第四位上就能成功绕过。
五、修复
现在上面的做法就不能实现了。
六、解决方法:
1.dom破坏
2.在删除之前就执行
<svg><svg οnlοad=alert(1)>
在删除之前就执行
SVG标签能成功的原因:
1.嵌套的 SVG 标签:虽然代码试图删除所有元素的属性,但 SVG 标签的嵌套特性让它有机会绕过。举个例子,<svg><svg onload=alert(1)>
,在解析时,第一个 <svg>
会被当作一个普通的 SVG 元素,而内层的 <svg onload=alert(1)>
也会被当作一个有效的 SVG 元素。外层的 SVG 即使属性被移除,但内层的 SVG 仍然存在,并且 onload
属性会触发。
2.过滤方法的局限性:代码通过遍历所有元素并删除其属性来达到过滤目的,但对于某些元素的嵌套结构,它无法完全处理。例如,即使外层的 SVG 标签属性被删除,内部的 SVG 标签仍然能够被解析并执行。
3.解析顺序问题:浏览器在解析 HTML 时,会先生成 DOM 树,然后再应用 JavaScript 来操作 DOM。即使 JavaScript 在之后移除了属性,浏览器在初次解析时已经触发了嵌套的 SVG 标签的 onload
事件。
单一的 <svg>
标签因为缺少执行代码的属性而不会触发 XSS。然而,嵌套结构中,内层的 <svg>
标签仍可能包含恶意代码或事件处理程序,并绕过简单的属性移除过滤逻辑。