XSS编码绕过之浏览器解析顺序
一.编码解码发生顺序
浏览器最早开始解析HTML,将标签转化为内容树中的DOM 节点,此时识别标签的时候,HTML 解析器是无法识别哪些被实体编码的内容的,只有建立起DOM 树,才能对每个节点的内容进行识别,如果出现实体编码,则会进行实体解码。
基本的解析顺序是这样的,URL 解析器,HTML 解析器, CSS 解析器,JS解析器,
(服务器)URL解析:例如input 内容参数为:%26lt%5cu4e00%26gt
该值构造在URL 里,浏览器直接发送给服务器,服务器接收之后,先进行URL 解析,看到了% 这个符号,于是URL 解码,input 内容变成了<\u4e00>
1.HTML解析(&#dex,&#xhex.只要是DOM节点里属性的值,都可以被HTML编码和解析)
浏览器接收到页面数据,于是开始进行HTML 解析,构造DOM树。
所以,HTML 的分析器只能识别特定的词法规则,才能构建起DOM 树,这一块,HTML 不会做解码的工作,因为它做不了。所以,试图这样构造利用漏洞,是不可能的:
HTMl 解析器构建DOM Tree,在DOM 树构建完毕之后,这些HTML 实体编码的内容就会被解码,如果识别为实体编码的,会透明的解码,于是:
例如:
会解析为:
2.CSS解析(CSS的属性和值都可以进行CSS编码和解析,冒号:不可以)
CSS 解析器并不会等到所有的html都解析完成之后再去构建和布局render树。它是解析完一部分内容就显示一部分内容,同时,可能还在通过网络下载其余内容。
CSS 编码解析是用了一套不太正统的转义策略:用一个反斜杠,后边跟1~6位十六进制数字构成。,所以字母e 可以编码为 \65, \065,\000065。而因为这样,后边就不能直接紧跟数字或字母,否则会被当成转义里的内容处理,所以CSS 选择了空格作为终止标识,在解码的时候,再将空格去除。
3.JS解析(\uxxxx)只支持UNICODE
3.JS解析(\uxxxx)只支持UNICODE
在处理诸如< script> < style> 这样的标签,解析器会自动切换到特殊解析模式,而src href 后边加入的JavaScript 伪URL,也会进入JS 的解析模式。而进入该解析模式的时候,该DOM节点已经建立起来了。
还是上边的例子,经过HTML 的解码,代码已经变成这样:
href="javascript:alert('<\u4e00>')">test
javascript 出发了JS 解释器,JS会先对内容进行解析,里边有一个转义字符\u4e00,前导的 \u 表示他是一个Unicode 字符,根据后边的数字,解析为'一',于是在完成JS的解析之后变成了:
href="javascript:alert('<一>')">test
然后JS 解释器执行alert("<一>"),这句话会交给浏览器渲染,最终弹窗。
转义编码应当只出现在标示符部分,不能用于对语法有真正影响的符号,也就是括号,或者是引号。(不包含使用DOM操作的情况),DOM操作中括号和引号可以进行JS转义。
在一个页面中,可以触发JS 解析器的方式有这么几种:
直接嵌入< script> 代码块。
javascript:xxx
通过< script sr=... > 加载代码。
各种HTML CSS 参数支持JavaScript:URL 触发调用。
CSS expression(...) 语法和某些浏览器的XBL 绑定。
事件处理器(Event handlers),比如 onload, onerror, onclick等等。
定时器,Timer(setTimeout, setInterval)
eval(...) 调用。
4.DOM操作
在进行DOM操作时,会触发JS解析器,例如:
document.getElementById("pic1").innerHTML = "";
DOM 操作实际上是js强势介入 HTML 和CSS 的结果,导致HTML标签的属性和值都可以做JS编码和解析。