xss编码绕过详解(更像是在介绍实体编码和JS编码的解析过程)

原文:https://blog.csdn.net/qq_41631096/article/details/104747992

怕作者删除,先保留

---------------------------------------------------------------------------------------

注:本文通过研究各种情况下实体编码和JS编码是否生效,进而总结了哪些情况下能够进行编码后,javascript代码依然能够正常执行。

解析顺序是这样的,URL 解析器,HTML 解析器, CSS 解析器,JS解析器

URL的解码是在后台服务检测之前的,可以理解为后台收到URL后会自动进行解码,
然后才是执行开发人员编写的对URL中的值的检测函数,首先URL编码作用不在于绕过后台检测,但是当我们是GET方式提交数据时,而我们提交的数据中进行了实体编码,也就意味着存在&,#这样的特殊字符,这时就需要对这些特殊字符进行URL编码,这样才会保证正常解析,如果不进行URL编码的话,就会把+认为是空格了,而&也会是被认为用来连接URL中参数的连接符,故需要进行URL编码。如果是以POST方式传递值,就不需要进行URL编码了。

着重谈
实体编码(HTML解析器)&#十进制; 或者&#x十六进制;
JS编码(JS解析器) \u00十六进制

一、HTML解析(只要是DOM节点里属性的值,都可以被HTML编码和解析)

浏览器接收到页面数据,于是开始进行HTML 解析,构造DOM树。HTML 的分析器只能识别特定的词法规则,才能构建起DOM 树,这一块,HTML 不会做解码的工作,因为它做不了。
<img src%26%23x3d%3B"test"> (对=号进行了一次实体编码后再进行了一次URL编码)
因为正确的语法是 src=value 只有这样的时候,HTML解析器才会认为src是标签img的一个属性,而value是这个属性的值。
举例:(注意:以下列子都是以GET方式传递值,所以需要进行URL编码)

http://192.168.149.143/xss/example1.php?name=

在这里我们通过GET方式传给name参数的值:
编码前:

对字符串test先进行一次实体编码,再进行一次URL编码(进行URL编码的原因已经在文章开头讲述过了)
于是就成了如下形式

进行访问,查看结果:

在这里插入图片描述
我们审查元素(审查元素所看到的就是经过解码后的结果)

在这里插入图片描述
查看网页源码:
可以看到src的值都是实体编码,这也证实

在这里插入图片描述
这也证实URL解码是在后台服务器上做的,而不是在浏览器,然后浏览器构建完DOM树后,进行了实体编码解析,于是看到了我们审查元素时所看到的结果

如果我们对"test"(包括test两边的双引号)进行一次实体编码再进行一次JS编码会怎么样
审查元素如下,发现多了一对双引号

在这里插入图片描述查看网页源代码却是正常的,并没有多双引号,双引号的实体编码是"

在这里插入图片描述
这里应该是因为浏览器存在一个自动纠错的功能

在这里插入图片描述
现在我们对="test"这一部分进行一次实体编码再进行一次JS编码

没有像正常那样出现一个图片访问错误的图标
审查元素,发现实体编码都未进行解析

在这里插入图片描述
查看源码

在这里插入图片描述
这里就说明img的标签是已经正常构成的,但是它的src属性却并没有正常构成,因为=号被编码后,导致构造DOM树时,属性src不符合语法规则,无法被识别,所以src的值也无法进行实体编码解析

如果对src进行上述编码,经测试也无法进行实体编码解析,在这就不在赘述

小结:所以如果想要能够进行实体编码解析,就必须不能破坏语法结构,比如不能对标签名称、<>=等具有语法结构的特殊字符进行实体编码,可以对比如对标签之间的文本进行实体编码、对标签的属性的值进行实体编码

二、JS解析器,只有进入JS解析环境,才会进行JS编码解析,并且位于JS解析环境的,不会进行实体编码解析

测试:
编码前:
http://192.168.149.143/xss/example1.php?name=
进行访问,结果如下:

在这里插入图片描述
触发了弹框,但是发现内容依然是实体编码
说明了test并没有进行实体编码解析
查看源码:

在这里插入图片描述
下面我们对test进行JS编码(只能是unicode编码,即\u00十六进制)
编码前
http://192.168.149.143/xss/example1.php?name=
进行访问,结果如下:
可以看到正常显示为了test,说明JS编码被解析了

在这里插入图片描述

script之间的就是JS解析环境

对alert进行JS编码

在这里插入图片描述
结果能够正常触发弹框
笔者还作了如下尝试:
1、将alert(“test”);中的(进行JS编码
结果无法触发弹框
2、将alert(“test”);中的"进行JS编码
结果无法触发弹框
3、将alert(“test”);中的;进行JS编码,事实上把这个;去掉一样能触发弹框
结果无法触发弹框
可以发现对这几个特殊字符进行JS编码后,却无法触发弹框(这里为什么无法触发弹框,本人暂时也不太清楚,这里到底是否进行JS编码解析,也不太清楚)

因为这里的alert可以算作是之间的文本节点(文本节点这种说法可能不太准确,但是这里因为是JS解析环境只能进行JS编码解析),就像是位于

 

之间的文本节点
笔者还进行了如下尝试:(这里有点偏向 文章所述 的第一条 实体编码解析 的验证)
1、对script中的任意几个字母进行实体编码+URL编码,比如cr
这种情况下,浏览器不会对实体编码解析,但是却会认为<script>这是一个标签,还自动给加了一个闭合标签</script>
2、对script这整个字符进行实体编码+URL编码
这种情况下,

在这里插入图片描述
3、对script前的<进行实体编码+URL编码
这种情况的结果与第2种情况一样

触发JS解析环境的还有javascript伪协议、onerror等

下面再测试下javascript伪协议
正常的一个标签a通过javascript触发JS弹框

在这里插入图片描述
现做如下尝试:
1、对javascript:alert(/test/);中的test进行JS编码

在这里插入图片描述
发现JS未进行解码,这就有点神奇了,这不应该是JS解析环境吗,继续往下看
补充:这里未能进行JS解码解析,感觉有点困惑,于是尝试了
javascript:alert(‘test’);即将test两侧的/换成了单引号,再对test部分进行JS编码

在这里插入图片描述
结果正常显示成test

在这里插入图片描述
审查下元素

在这里插入图片描述
看来上面无法进行JS编码解析的原因是test两侧的/造成的,但为什么会造成这种情况,暂时不太清楚

2、对javascript:alert(/test/);中的test进行实体编码+URL编码

在这里插入图片描述
发现实体编码进行了正常解析

3、对javascript:alert(/test/);中的alert进行JS编码

在这里插入图片描述

alert进行了JS编码解析,审核元素看下

在这里插入图片描述
4、对javascript:alert(/test/);中的alert进行实体编码+URL编码

在这里插入图片描述
进行了实体编码解析,审查元素看下
在这里插入图片描述
根据3,4两个测试,发现alert既可以JS编码解析又可以实体编码解析

5、对javascript:alert(/test/);中的javascript进行JS编码

在这里插入图片描述
直接报了这样一个错误,相当于是把编码部分也当成了链接的一部分,而不是javascript协议

6、对javascript:alert(/test/);中的javascript进行实体编码+URL编码
在这里插入图片描述

进行了实体编码解析,触发JS弹框
7、对javascript:alert(/test/);这一个整体进行实体编码+URL编码
在这里插入图片描述

进行了实体编码解析,触发JS弹框,这是不是说明这里虽然是用到了javascript伪协议,但是
javascript:alert(/test/);这一部分却依然是看做标签a属性href的值,从而能进行实体编码解析

小结:因为javascript:alert(/test/);这一部分依然可以看做是标签a属性href的值,于是当我们对其任意字符进行实体编码后,依然能够正常实体编码解析,并触发javascript伪协议;
可以对javascript:后面的部分做js编码,因为当触发javascript伪协议后,就会进入JS解析环境,
然后对alert(/test/);的编码解析情况就像是位于之间那样

测试on事件

举例:

现做如下尝试:
1、将alert(1)整个部分进行实体编码+URL编码
结果:成功弹窗
2、将alert(1)的整个部分进行JS编码
结果:不弹窗
3、将alert(1)的alert进行JS编码
结果:成功弹窗

小结:这里的情况就像是位于javascript伪协议冒号后面一样,同样都可以进行实体编码或JS编码,
但是进行JS编码时,不能对括号、引号都具有构成函数特殊意义的特殊字符进行JS编码,但可以对函数的名称比如alert进行JS编码。

总结:实体编码要在不破坏DOM树的构成,对于有语法结构的标签名、属性名、标签名就不能进行实体编码,对属性的值,标签之间的文本节点能够进行实体编码,而JS编码只能对位于JS解析环境内字符进行编码且不能是括号、双引号、单引号等构成特殊意义的特殊字符,比如alert(1)中的括号就不能进行实体编码,而且在JS编码环境中不会进行实体编码解析,但有一个例外,在javascript伪协议中,比如test,即可以把javascript:alert(‘test’);这一部分看成是标签a的属性href的值,从而能够进行实体编码会被正常实体编码解析,又可以对alert或alert中的字符进行JS编码,但对alert中的字符编码没什么实际作用,如果是javascript:alert(document.domain);这样的,对document.domian进行JS编码是不可行的,会报JS上的语法错误,不过能够进行实体编码,因为是先进行实体编码解析,后再进入js解析环境。

那么对于XSS编码绕过以上的编码解析该如何起作用:
1、如果过滤了javascript,则可以考虑将javascript进行实体编码绕过
(待补充)

参考:https://www.jianshu.com/p/5b72458a5258

posted @ 2020-11-26 10:35  mrhonest  阅读(1588)  评论(0编辑  收藏  举报