XSS编码之我见

Posted by 跳跳龙 on May 17, 2019

直接上我自己理解的干货

  • 在浏览器发送请求的时候都会被浏览器使用URL编码的,这样做主要是为了避免你的参数里存在 & 受到影响。
  • 浏览器里解析器的工作顺序为:HTML解析器 –> js解析器 –> url解析器 其中js解析器和url解析器是动态灵活对dom节点进行解析。所以准确的说,js解析器和url解析器是灵活变化 顺序是不固定的。但是一般都是html解析器先与js解释器工作。
  • html解析器工作,最重要的工作是形成dom树。本身是一个状态机,随着不同的输入导致状态的切换。一旦dom树形成,会对各个节点进行html解码。(在此dom树形成之前,是不会做html解码的)
  • 关于js解析器我有4点要说:
    • 控制字符是不能用js编码的 比如(单引号,双引号,左括号,右括号)
    • 字符串是要以引号包含的,如果引号被js编码,那么浏览器不会认为他是一个字符串。换个高大上的说法就是引号编码之后是不能改变字符串的上下文的。
    • 属性名 函数名可以被js编码 比如alert() alert这5个字母你可以随意编码
    • 如果使用javascript:伪协议的话 是不能url编码的,这样url解码之后他就不会再调用js解释器了。(但是可以使用html编码,因为html解析器在js之前,那个时候还没运行js解析器)
  • URL编码没什么说的

后面用几个例子来说明一下我的理解吧:

<a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:%61%6c%65%72%74%28%32%29">test</a>

首先说这个会形成dom树,然后对href节点进行html解码,这样会把javascript伪协议解析出来。因为js伪协议已经解析出来了,所以调用js解析器 然后发现后面是url编码就调用url解码 url解码:alert(2),正常执行 没有问题。

2.

<a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29"></a>

先说结论,这个不行。因为js伪协议被url编码了。没法再次调用js解析器了。和上一个对比着看。

3.

<a href="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#54;&#37;&#51;&#49;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#54;&#37;&#54;&#51;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#54;&#37;&#51;&#53;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#55;&#37;&#51;&#50;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#55;&#37;&#51;&#52;&#40;&#51;&#41;">test3</a>

常规操作 html解码 解完之后如下:

<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(3)">test3</a>

这个时候js协议解析出来 开始调用js解释器 发现后面被url编码了 于是解码:

<a href="javascript:\u0061\u006c\u0065\u0072\u0074(3)">test3</a>

没有问题 弹起来。有人会问为什么html对js伪协议编码就可以,url就不可以。这里我理解的是一个顺序问题。html编码的时候浏览器是不知道里面有什么的,解完之后才发现是js伪协议,于是去调用js解释器。但是如果是url编码的话就不行,也就是说url解码之后是不能再去掉用js解释器了。基于html>js>url。

4.

<img src&#x3d;"http://www.example.com">
<img s&#x72;c="http://www.example.com">

这2个都不行,为什么?我理解的是html就算是要解码也是形成dom树之后对节点进行解码,这样编码的话,浏览器根本没法按照字符来形成dom结构,只能当成字符串去显示到浏览器上。

5.

<a onclick="window.open('value1')" href="javascript:window.open('value2')"></a>

value1和value2这俩个解码的顺序应该是(编码的顺序应该是和这个正好相反的): value1:html>js>url 为什么是这样?其实这个应该算是最好理解的,咱们从外层一点点分析,最开始是html没有什么问题,然后到onclick,发现这个节点里应该是js代码 所以第二步是js解码。发现是windows.open函数,这个函数是打开一个地址,地址肯定是可以url编码的。

value2:html>url>js>url 这个我就不分析了,大家可以自己理解 和上面思路一样。

6.

<div>&#60;img src=x onerror=alert(4)&#62;</div>

这个也不可以 原因我的理解是和4是一样的。

7.

<textarea>&#60;script&#62;alert(5)&#60;/script&#62;</textarea>

这种的也是不会执行的 textarea title这种标签就算你里面不编码都是不会执行的。原因在于它属于RCDATA 永远不会进入创建标签状态的。

以上都是我个人的一些理解,由于浏览器解析本身是一门十分复杂的技术,涉及到不限于编译原理等综合知识,解释的比较偏向于个人理解,如果错误十分明显希望大家可以对我提意见。wx:tangtianlong123