0x00背景
学习了这么久,我才发现根本不会绕过,以前以为就是简单的编码转换就好了,乱编一通。经过大佬分享资料之后,才算弄懂。记录,加深理解。
0x01浏览器解析
浏览器的解析可以分为3步:
1. HTML解析(HTML解析器)
2. JS解析(JavaScript解析器)
3. URL解析(URL解析器器)
这3个解析器协调工作,首先浏览器接收到一个HTMl文档时,会触发HTML解析器对文档进行词法解析,完成HTML解码和DOM树的建立。接下来JavaScript解析器介入开始对内联的脚本进行解析,包括解码操作。如果浏览器遇到需要URL的上下文,URL解析器也会介入开始解析解码。(URL解析会根据文档中URL的实际位置不同而在不同的时间解析,例如遇到Onclick事件需要触发才会执行的代码会跳过,等到事件被触发时才会被解析)
举个栗子:
<html>
<head>
<script type=”text/javascript”>
function open_win()
{
window.open(“javascript:alert(1)”);
}
</script>
<body>
<input type=”button” name=”Open window” onclick=”open_win()”>
</body>
</head>
</html>
在这个html文档中,解析的顺序就是:HTML解析–>JavaScript解析(触发onclick事件)–>URL解析–>JavaScript解析
因此可以看到,如果对以上文档的open函数的参数(“javascript:alert(1)”) 进行编码的话,应该是URL编码(当然,只要JavaScript被正确解码之后,后面的alert也可以使用JavaScript编码)。
0x02 常见编码
HTML字符实体:< 编码为< <
JavaScript编码:<编码为unicode码\u003C
URL编码:%加上字符的ASCII编码对应的2位数字
因此在进行编码绕过的时候,要根据当前输入点的位置与输入的内容进行正确的编码绕过。
以上面的代码为例:
如果只是将javascript:alert(1) 整体全部进行URL编码
window.open(“%6A%61%76%61%73%63%72%69%70%74:%61%6C%65%72%74%28%31%29”);
那么是绕不过去的,因为整体编码就连协议类型(JavaScript)一起编码了,浏览器在进行URL解析的时候就会默认为无类型,所以只会按照URL的规则进行解析,但是不会涉及到JavaScript解析器,所以在这里这一条命令只像是被一句文本而已。
如果只编码 alert(1) 的话就能正确执行,如下:
window.open(“javascript:%61%6C%65%72%74%28%31%29”);
在这里当URL解析器介入开始解析的时候,能够识别出接下来的内容为JavaScript代码,所以就会再由JavaScript解析器进行解析。
如果对整体进行Unicode编码的话也能正常解析执行。因为URL解析器运作时JavaScript解析器已经把javascript:alert(1)解析完成。
window.open(“\u006a\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070
\u0074\u003a\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029”);
如果对整体进行HTML实体编码,一样无法正确解析执行。因为这个函数是在onclick事件之后才会被解析执行,此时参与解析的只有JavaScript和URL解析器,HTML解析器已经不再参与到这个函数内的解码过程了,因此HTML实体编码无法被解析执行。
window.open(“javascrip:alert(1)”);
同样的,类似如下场景,将输⼊入数据编码成HTML字符实体并将其放在script块中,也⽆无
法成功解析alert(1),因为script块中的编码解析不会调用HTML实体解析器。
alert(9);
<script>alert(9);</script>
若是如下情景,那么可以成功执行javascript:alert(1),因为整个编码文本是放在HTML的标签里面的,整个解析过程为HTML解析->URL解析->JavaScript解析,在URL解析器作前,HTML解析器已经把字符实体转换成了javascript:alert(1)。
<a href=”javascript:a&#
108;ert(1)”>tkswifty</a>
同理,如下情景也可以成功执行:
<a href=” javascript:%61%6C%
65%72%74%28%32%29 “>tkswifty</a>
0x04 细节:
(1)在字符串串中,Unicode转义序列列(\uXXXX)将永远不不会破坏字符串串的上下文,因为只能被解析成字符串常量。(JavaScript解析时只有标识符名称不会当字符串解析,控制字符(单双引号、换⾏行行符等)仅会被解析成标示符名称或者字符串串)
Examples:
<input type=”button” name=”demo” onclick=”alert(1)”>
对alert进行Unicode编码:
<input type=”button” name=”demo” onclick=”\u0061\u006c\u0065\u0072\u0074(1)”>
可以解析执行
对alert(1)进行Unicode编码:
<input type=”button” name=”demo” onclick=”\u0061\u006c\u0065\u0072\u0074u0028\u0031\u0029″>
无法解析执行
(2)URL解析过程的一个细节:不能对协议类型进行任何的编码操作,否则URL解析器会认为其无类型。
(3)RCDATA元素有个特殊情况,在浏览器器解析RCDATA元素的过程中,解析器器会进入“RCDATA状态”。在这个状态中,如果遇到”<“字符,会转换到”RCDATA小于号状态”。如果”<“后没有紧跟”/”和对面的标签名,解析器器会转换回”RCDATA状态”。常见的RCDATA元素:<textarea>和<title>
Example:
<textarea>中,唯一能被解析器认作标签的就是</textarea>,在其中新建标签,也不会有脚本可以执行。
<textarea><script type=”text/javascript”>alert(1)</script></textarea>
具体效果:
具体效果:
(4)当某些函数的执行改变了当前页面的DOM树结构,HTML解析器会再次执行解析。