由xss引发的对于浏览器解码和编码流程认识

前言:

看到xss的编码绕过写法后,其实感觉很懵, 不知道为啥他要这样写,故决定去学习一下浏览器解码和编码的过程

浏览器的大致工作流程

浏览器最早开始解析html,将标签转化为内容树上的DOM节点,然后此时还是无法识别出哪些被实体编码,接下来建立起DOM树,才可以识别哪些为实体编码,并将其解码,在此基础上,javascript DOM API参与进来,可以对DOM树进行修改,改变DOM树的结构和内容,而CSS主要负责解析外部CSS文件和style 的样式标签

DOM树参考:https://zh.javascript.info/dom-nodes

在知道大致的一个工作流程后,分析其中的编码解码过程:

解析流:

在知道完大致工作流程后,我们理一下各个解析器发挥作用的顺序:

html->url->javascript

1
<a href="UserInput"></a>

在这个例子中:首先html解析器进行解析,并进行实体编码的解码,接下来如果在这个userinput中设计URL内容,那么url解析器会发先发挥作用,进行URL解码,如果URL资源是JavaScript类型,JavaScript解析器将会发挥作用,进行解码

html->javascript->url

1
<a href=#   onclick="window.open('UserInput')"></a>

在这里 还是先html进行解析,接下来onclick的值是有JavaScript解析器进行解析处理的,处理的是window.open中的input,此时设计URL的参数,URL解析器就会对其中的内容进行解码,并将其结果传回给JavaScript

HTML解析

HTML解析器作为一个状态机,它从输入流中获取字符并按照转换规则转换到另一种状态。在解析过程中,任何时候它只要遇到一个‘<’符号(后面没有跟‘/’)符号就会进入标签开始符号,然后转变到标签名状态,最后是数据状态并释方当前标签的token,当解析器处于数据状态时,它会继续解析,每当发现一个完整的标签,就会释放一个token。
在前面的工作流程中我们说到,在建立起DOM树后会识别哪些为实体编码,并将其解码。
这里我们将深入讲解一下整个过程:
字符实体分为三种:
1.数据状态中的字符引用
2.RCDATA状态中的字符引用
3.属性值状态中的字符引用

数据状态中的字符引用

这些状态中HTML字符实体将会从”&#..”形式编码,对应的解码字符会被放入数据缓冲区中,例如:”<”被编码为“&#60”。当解析器遇到&字符,它会知道这是”数据状态的字符引用”,因此会消耗一个字符引用,并释放出相应的token,但是这里的<的token不会被理解是标签的开始,原因是解析器解析这个这个字符引用后不会转换到标签开始状态。
字符实体:字符实体是一个转义序列,它定义了一般无法在文本内容中输入的单个字符或符号。一个字符实体以一个&符号开始,后面跟着一个预定义的实体的名称,或是一个#符号以及字符的十进制数字
HTML字符实体

img

一点思考:当我们输入的xss脚本语句中<>被转义成&#60;的时候,那么我们的xss脚本将不起作用。

RCDATA状态中的字符引用:

这里要提一下RCDATA的概念。要了解什么是RCDATA,我们先要了解另一个概念。在HTML中有五类元素:

1空元素(Void elements),如<area>,<br>,<base>等等

2原始文本元素(Raw text elements),有<script><style>

3RCDATA元素(RCDATA elements),有<textarea><title>

4外部元素(Foreign elements),例如MathML命名空间或者SVG命名空间的元素

5基本元素(Normal elements),即除了以上4种元素以外的元素
五类元素的区别如下:

1空元素,不能容纳任何内容(因为它们没有闭合标签,没有内容能够放在开始标签和闭合标签中间)。

2原始文本元素,可以容纳文本。

3RCDATA元素,可以容纳文本和字符引用。

4外部元素,可以容纳文本、字符引用、CDATA段、其他元素和注释

5基本元素,可以容纳文本、字符引用、其他元素和注释

在RCDATA状态中,唯一能够被解析进入标签开始状态的只有<textarea><text>等RCDATA元素,以为这如果有一个语句是:

1
<textarea><script>alert(6)</script></textarea>

这个语句当中的alert是不会被执行的,因为<script>不会被解析为标签开始状态

CDATA元素。任何在CDATA元素中的内容将不会触发解析器创建开始标签。闭合CDATA元素的标志是“]]>”序列。因此如果用户想逃出CDATA元素,就要用未经任何编码的“]]>”序列,不然是不会逃出CDATA元素的。

URL解析

1
2
 <a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29"></a>
URL encoded "javascript:alert(1)"
1
2
3
4
<a
href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:%61
%6c%65%72%74%28%32%29">
Character entity encoded "javascript" and URL encoded "alert(2)"
1
2
<a href="javascript%3aalert(3)"></a>
URL encoded ":"

上面这三段代码中 只有中间那段会成功弹窗,原因是:
URL资源类型必须是ASCII字母,不然就会进入无类型状态,该规则同样适应于那个“:”号,我们知道html经过解析文本,并会对其字符实体进行解码,而在第一段和第三段JavaScript没有被解码,所以不会被URL解析器所识别,所以不会被解码。

javascript解析

在script块中的字符实体编码不会被解析:

1
2
<script>&#97;&#108;&#101;&#114;&#116&#40;&#57;&#41;&#59</script>
Character entity encoded alert(9);

js支持Unicode解析所在位置

字符串中

当Unicode转义序列存在于字符串中时,它只会被解释为正规字符,而不是单引号,双引号或者换行符这些能够打破字符串上下文的字符。这项内容清楚地写在ECMAScript中。因此,Unicode转义序列将永远不会破环字符串上下文,因为它们只能被解释成字符串常量。

标识符名称中

什么是标识符?
java语言中,对于变量,常量,函数,语句块也有名字,我们统统称之为标识符Java标识符类似于我们C语言中定义的变量,定义规则如下:
https://blog.csdn.net/shuaigexiaobo/article/details/86617080
如果unicode转义序列出现在标识符中,它会被解码并解释为标识符的一部分

1
2
<script>\u0061\u006c\u0065\u0072\u0074(10);</script>
Unicode Escape sequence encoded alert
控制字符中

什么是控制字符?
例如单引号、双引号、圆括号等,这里可以简单理解为C语言中我们打printf(“”)里面的这个双引号
https://www.netinbag.com/cn/internet/what-is-a-control-character.html
在unicode转义序列表示一个控制字符时,它们将不会被解释成一个控制字符,而是被解码解析为标识符名称或者字符串常量。
例子:

1
2
3
<script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script>
Unicode Escape sequence encoded alert(11)
//这里不会弹窗是因为,这里的控制字符()被解码后失去其控制字符的属性了
1
2
3
<script>alert('13\u0027)</script>
Unicode escape sequence encoded ’
//这里的是因为控制字符''被转义了
1
2
3
<button onclick="confirm('8\u0027);">Button</button>
Unicode escape sequence encoded '
同样单引号
1
2
3
4
<script>\u0061\u006c\u0065\u0072\u0074(\u0031\u0032)</script>
Unicode Escape sequence encoded alert and 12
这个也不许 解码后缺少单引号<script>\u0061\u006c\u0065\u0072\u0074('\u0031\u0032')</script>
这样就对了

参考http://test.attacker-domain.com/browserparsing/answers.txt
http://bobao.360.cn/learning/detail/292.html
https://www.hackersb.cn/hacker/85.html
https://xz.aliyun.com/t/5863
https://zh.javascript.info/dom-nodes
http://xuelinf.github.io/2016/05/18/%E7%BC%96%E7%A0%81%E4%B8%8E%E8%A7%A3%E7%A0%81-%E6%B5%8F%E8%A7%88%E5%99%A8%E5%81%9A%E4%BA%86%E4%BB%80%E4%B9%88/

小结

身为一个菜鸟,感觉理清楚这些以后,对于之前XSS博客写的编码绕过终于能体会一些了,果然学东西还是不能学的不清不楚的

Author

vague huang

Posted on

2021-01-29

Updated on

2021-02-12

Licensed under

Comments