网络安全基础--浏览器解码顺序

当我们在进行XSS测试时,由于服务端进行了过滤等操作,有时候可以尝试通过编码转义的方式进行绕过,常见的方法有URL编码、HTML编码、js转义等。使用编码转义之前,我们首先需要了解浏览器的解码顺序。

URL 解析

对于url来说,因为有些字符会引起歧义,要进行编码处理。例如url参数字符串中使用key=value键值对这样的形式来传参,键值对之间以&符号分隔,如/sq=abc&ie=utf-8。如果你的value字符串中包含了=或者&,那么势必会造成接收url的服务器解析错误,因此必须将引起歧义的&和=符号进行转义,也就是对其进行编码。因此,服务器接收浏览器请求后首先会进行url解析。我们考虑一段简单的代码:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<a href="javascript:alert('<?php echo $_GET['input'];?>');">test</a>
</body>
</html>

input内容参数为:%26lt%5cu4e00%26gt,该值构造在URL里(get请求),浏览器直接发送给服务器,服务器接收之后,先进行URL 解析,看到了%这个符号,于是URL解码,input内容变成了&lt\u4e00&gt,所以对于浏览器从服务器端获取的页面数据来说,此时test 对应的标签变成了如下:

<a href="javascript:alert('&lt\u4e00&gt');">test</a>

HTML解析

HTML解析器的工作是将html标识解析为解析树。HTML解析输出的树,也就是解析树,是由DOM元素及属性节点组成(DOM树)的。DOM是文档对象模型的缩写,它是html文档的对象表示,作为html元素的外部接口供js等调用。对于以下一个最常见的例子:

<html>
    <body>
        <p>
          Hello DOM
        </p>
        <div><img src=”example.png” /></div>
    </body>
</html>

它将转换为下面的DOM 树:

所以,HTML的分析器只能识别特定的词法规则,才能构建起DOM树,这一块,HTML不会做解码的工作,因为它做不了。所以,试图这样构造利用漏洞,是不可能的:

<img src&#61;"http://www.example.com">

 因为在构建DOM树的时候,这样是无法识别的,也就破坏了标签本身的结构。

HTML解码

HTML 解码,是在DOM树结构OK,对节点内容解析的时候。所以,在DOM 树构建完毕之后,这些HTML实体编码的内容就会被解码。浏览器是以自上而下的方式解析html,link、style、script等标签会使解析过程产生阻塞,等待外部资源加载才会继续解析。img标签是通过src导入资源的,而所有通过src属性导入的元素,都会导致页面渲染的堵塞。一般的标签只进行HTML解析,这些标签先进行html解析,随后进行js解析。例如:

<script>&#97;lert(1)</script>

调试提示语法错误,该标签只进行js解析,但存在特殊情况:涉及DOM操作,见下面分析。

CSS 解析

一般来说,html解析后,CSS解析器会做接下来的工作,不过一般来说,为了考虑到更好的体验和性能,并不会等到所有的html都解析完成之后再去构建和布局render树,它是解析完一部分内容就显示一部分内容,同时,可能还在通过网络下载其余内容。

当然CSS不会干扰到DOM树的建立,他会结合CSS文件和style 标签,以及HTML中的指令来构建起reder tree。

CSS 编码解析是用了一套不太正统的转义策略:用一个反斜杠,后边跟1~6位十六进制数字构成。所以字母e 可以编码为 \65, \065,\000065。而因为这样,后边就不能直接紧跟数字或字母,否则会被当成转义里的内容处理,所以CSS 选择了空格作为终止标识,在解码的时候,再将空格去除。

同时,CSS还支持直接使用反斜杠对非十六进制字符进行转义的方式,就按紧跟着反斜杠后边的字符的字面意思进行解释,这种机制可用来转义引号和反斜杠本身,不过不能转义HTML 控制的字符,比如尖括号,那是因为HTML 解析器总是先于CSS 解析器。

由于CSS 转义规定的语焉不详,许多解析器会对本该用引号括起来的字符串进行任意的转义,特别的,在IE 浏览器里,这种转义优先级高于伪函数语法,于是下边两种情况的写法是一样的:

color:expression(alert(1))
color:expression\028 alert \028 1 \029 \029

JS 解析

上边提到了style ,是建立reder tree 的时候使用的,它怎么工作的呢。考虑到我们的浏览器为了让不同的解析器来工作处理不同的内容,实际上,在处理诸如< script> < style> 这样的标签,解析器会自动切换到特殊解析模式,而src href 后边加入的JavaScript 伪URL,也会进入JS 的解析模式。而进入该解析模式的时候,该DOM节点已经建立起来了。

还是上边的例子,经过HTML 的解码,代码已经变成这样:

<a href="javascript:alert('<\u4e00>')">test</a>

javascript 触发了JS 解释器,JS会先对内容进行解析,里边有一个转义字符\u4e00,前导的 \u 表示他是一个Unicode 字符,根据后边的数字,解析为'一',于是在完成JS的解析之后变成了:

<a href="javascript:alert('<一>')">test</a>

然后JS 解释器执行alert("<一>"),这句话会交给浏览器渲染,最终弹窗。这里边会有一个看起来让人有些疑惑的东西,仍以上一段代码为例,假如我们编码的位置不是括号里,而是在alert上,我们知道,js 是会对它进行逆转义的:

<a href="javascript:\u0061lert('<一>')">test</a>

而另一方面,如果想用这种方式来替换掉圆括号,或者引号,会判定为失败。

像圆括号、双引号、单引号等等这些控制字符,在进行JavaScript解析的时候仅会被解码为字符串文本或者上面讲的标识符名称,例如:<script>alert('YISRC\u0027)</script>对控制字符单引号进行js编码,解析时\u0027被解码成文本单引号,无法闭合因此不能成功执行。

DOM 操作

之前,我们说了,基本的解析顺序是这样的,URL 解析器,HTML 解析器,CSS 解析器,JS解析器,如果安安静静的按照这个顺序下去,应该很容易理清楚。然而DOM 操作里我们可以看到可以新增节点,也可以修改节点属性,节点的内容和样式都可以修改。那么假如我们使用innerHTML 修改了某节点的内容,让其构成了一个新的节点,那么会有什么效果呢?看下面代码:

<html>
<body>
<p id="1">hello</p>
<img src=# onerror="&#97;lert(1)" />
<script>
document.getElementById("1").innerHTML = "<img src=&#35; on\u0065rror=&#97;lert&#40;1)>";
</script>
</body>
<html>

一个正常的容易理解的过程是这一行:

<img src=# onerror="&#97;lert(1)" />

HTML 解析到标签,建立DOM 树,然后对节点内容进行实体解码,”&#97;”就变成a, 随后在js 解析阶段,正常的触发了弹窗,先后顺序OK。但对于下面这段代码:

<script>
document.getElementById("1").innerHTML = "<img src=&#35; on\u0065rror=&#97;lert&#40;1)>";  
</script>

使用了DOM 操作,修改前边标签中的内容,添加了一个img 内容,因为进入了script,进入了JavaScript的特殊解析模式,所以此处HTML不得干扰,首先JavaScript解析器,会先对其中编码的内容解码,于是onerror 就还原回来了,于是正常的执行了JS 语句,在HTML 文档中,将hello 变成了img。

那么问题来了,如上那样,对onerror 的内容作了HTML 实体编码,会不会弹窗呢?答案是显然的,该标签传回给HTML,HTML 建立DOM节点,透明的解码节点内容,onerror 又会执行其中的JS 脚本,弹出窗口。

其实,这里也不难理解,因为HTML是从上到下解析,遇到< script> 于是进入了特殊的解析模式,使用JS 解析器,做了一个DOM 操作,该DOM 操作修改了前边的DOM 树,该块内容,需要使用HTML 解析重塑DOM 树,那么节点内容中的实体编码就会被解码,然后onerror中触发脚本,JS 又会对内容进行一次解析。

实际上,DOM 操作是JS强势介入 HTML 和CSS 的结果,使用DOM 操作,对DOM Tree 造成了改变,会调用到HTML 解析器重新对其解析,于是流程又会返回到最开始说的那个解析流程里去。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值