一、预备知识
背景:本文主要介绍html编码、url编码、js编码在浏览器端的解析过程,以及编码对js执行的影响
URL编码:
一个百分号和该字符的ASCII编码所对应的2位十六进制数字,例如“/”的URL编码为%2F(一般大写,但不强求)
HTML实体编码:
命名实体:以&开头,分号结尾的,例如“<”的编码是“<”
字符编码:十进制、十六进制ASCII码或unicode字符编码,样式为“&#数值;”,例如“<”可以编码为“<”和“<”
JS编码:js提供了四种字符编码的策略,
1、三个八进制数字,如果不够个数,前面补0,例如“e”编码为“\145”
2、两个十六进制数字,如果不够个数,前面补0,例如“e”编码为“\x65”
3、四个十六进制数字,如果不够个数,前面补0,例如“e”编码为“\u0065”
4、对于一些控制字符,使用特殊的C类型的转义风格(例如\n和\r)
5、其他编码,例如JSFUCK
二、解析过程
1.接收响应-->html decode-->url decode-->js decode(根据具体情况,可能是url解码在前,也可能是js解码在前)
三.解析实例--对JS解析的影响
1、源码:
<a href="javascript:alert(1)">test0</a>
2、全部进行html编码:
<a href="javascript:alert(1)">test0</a>
根据解析过程,先进行html解码,转换为(<a href="javascript:alert(1)">test0</a>)字符串输出,但是只是字符串,所以无法执行url解码、js解码,为什么无法执行url、js解码呢,因为url、js解析器,未在html解码过程中识别出协议类型、js函数。
3、全部进行js解码:
\u0026\u006c\u0074\u003b\u0061\u0020\u0068\u0072\u0065\u0066\u003d\u006a\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070\u0074\u003a\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029\u0026\u0067\u0074\u003b\u006a\u0073\u0026\u006c\u0074\u003b\u002f\u0061\u0026\u0067\u0074\u003b
未符合html解码,所以直接输出相同的字符串,浏览器解析过程,先进行html解码,这里未发现需要html解码的编码。
4、对href属性内容进行url编码
<a href="%6a%61%76%61%73%63%72%69%70%74%3a%61%6c%65%72%74%28%30%29">test</a>
注:url编码不能对协议类型进行任何编码操作,这里对javascript协议类型进行编码,导致url解析器认为它是无类型,被编码的javascript没有解码,所以不会被url识别。
5、<a href=javascript:%61%6c%65%72%74%28%31%29>test1</a>
未对javascript进行编码,url解析器识别后调用js解析器进行解析,造成弹窗
6、<a href="javascript:\u0061\u006c\u0065\u0072\u0074\u0028\u0032\u0029">test</a>
注:像圆括号、双引号、单引号等等这些控制字符,在进行JavaScript解析的时候仅会被解码为字符串文本或者标识符名称
7、<a href="javascript:\u0061\u006c\u0065\u0072\u0074(1)">test</a>
正常弹窗
8、符合编码
<a href="javascript:%61%6c%65%72%74%28%31%29">test</a>
<a href="javascript:\u0061\u006c\u0065\u0072\u0074(1)">test</a>
参考:
https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/
https://security.yirendai.com/news/share/26
http://www.freebuf.com/articles/web/100675.html
http://taligarsiel.com/Projects/howbrowserswork1.htm
https://www.jianshu.com/p/cfdf1747d30e