zoukankan      html  css  js  c++  java
  • xss常见编码解析

    前言

    其实看这篇文章就差不多懂了:
    https://www.cnblogs.com/b1gstar/p/5996549.html
    这里只是记录一下方便理解

    //1.URL 编码 "javascript:alert(1)"
    <a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29">123</a>
    
    //2.HTML字符实体编码 "javascript" 和 URL 编码 "alert(2)"
    <a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:%61%6c%65%72%74%28%32%29">123</a>
    
    //3.URL 编码 ":"
    <a href="javascript%3aalert(3)">123</a>
    
    //4.HTML字符实体编码 < 和 >
    <div>&#60;img src=x onerror=alert(4)&#62;</div>
    
    //5.HTML字符实体编码 < 和 >
    <textarea>&#60;script&#62;alert(5)&#60;/script&#62;</textarea>
    
    //6.textarea中直接alert
    <textarea><script>alert(6)</script></textarea>
    
    //7.HTML字符实体编码 " ' " (单引号)
    <button onclick="confirm('7&#39;);">Button</button>
    
    //8.Unicode编码 " ' " (单引号)
    <button onclick="confirm('8u0027);">Button</button>
    
    //9.HTML字符实体编码 alert(9);
    <script>&#97;&#108;&#101;&#114;&#116&#40;&#57;&#41;&#59</script>
    
    //10.Unicode 编码 alert
    <script>u0061u006cu0065u0072u0074(10);</script>
    
    //11.Unicode 编码 alert(11)
    <script>u0061u006cu0065u0072u0074u0028u0031u0031u0029</script>
    
    //12.Unicode 编码 alert 和 12
    <script>u0061u006cu0065u0072u0074(u0031u0032)</script>
    
    //13.Unicode 编码 " ' " (单引号)
    <script>alert('13u0027)</script>
    
    //14.Unicode 编码换行符(0x0A)
    <script>alert('14u000a')</script>
    

    以上是一些xss编码解析的例子

    首先需要知道html在解析相应的文档时可能会使用:html解析url解析javascript解析

    html解析:

    一个HTML解析器作为一个状态机,它从输入流中获取字符并按照转换规则转换到另一种状>态。在解析过程中,任何时候它只要遇到一个'<'符号(后面没有跟'/'符号)就会进入“标签开始状态(Tag open state)”。然后转变到“标签名状态(Tag name state)”,“前属性名状态(before attribute name state)”......最后进入“数据状态(Data state)”并释放当前标签的token。>当解析器处于“数据状态(Data state)”时,它会继续解析,每当发现一个完整的标签,就会释放出一个token。

    例如:

    <a href="127.0.0.1">123</a>
    

    首先html匹配到<,进入标签开始状态,然后进入标签名状态,并匹配到a,然后进入前属性名状态,进行一系列属性名、属性值匹配,匹配完href="127.0.0.1"后,进入数据状态,匹配完数据123,结束标签,结束匹配

    这大概就是html解析的简略过程,然后呢下面说一下几个概念

    字符实体、引用

    其实也就是html字符实体编码,例如:&#60;,&#62(<,>),html中也有一些预留的字符实体,称之为html字符实体,如:&lt;这两个都是为了转义用户输入的<或>而用的编码形式,使其不会成为一个新标签的开始或结束,也就是

    解析器在解析这个字符引用后不会转换到"标签开始状态",只会将其当作"数据"处理

    这也是为什么例4不会弹窗的原因

    字符引用包括"字符值引用"和"字符实体引用",在上述例子中,'<'对应的字符值引用为&#60;,对应的字符实体引用为&lt;。字符实体引用也被叫做“实体引用”或“实体”。

    下面有三种情况可以容纳字符实体:
    "数据状态中的字符引用"
    "RCDATA状态中的字符引用"
    "属性值状态中的字符引用"

    "数据状态中的字符引用"

    第一种也就是在数据内容中可以用字符实体,如:

    <a href="127.0.0.1">&#60;</a>
    

    其中&#60;会被解析成<
    在这里插入图片描述

    "RCDATA状态中的字符引用"

    要了解这个,首先需要知道在HTML中有五类元素:

    1. 空元素(Void elements),如<area>,<br>,<base>等等
    2. 原始文本元素(Raw text elements),有<script>和<style>
    3. RCDATA元素(RCDATA elements),有<textarea>和<title>
    4. 外部元素(Foreign elements),例如MathML命名空间或者SVG命名空间的元素
    5. 基本元素(Normal elements),即除了以上4种元素以外的元素

    五类元素的区别如下:

    1. 空元素,不能容纳任何内容(因为它们没有闭合标签,没有内容能够放在开始标签和闭合标签中间)
    2. 原始文本元素,可以容纳文本
    3. RCDATA元素,可以容纳文本和字符引用
    4. 外部元素,可以容纳文本、字符引用、CDATA段、其他元素和注释
    5. 基本元素,可以容纳文本、字符引用、其他元素和注释

    可以看到所谓RCDATA也就是一种html元素,而这种元素的标签为<textarea>或<title>
    这意味着在<textarea>和<title>标签中的字符引用会被HTML解析器解码

    在浏览器解析RCDATA元素的过程中,解析器会进入“RCDATA状态”。在这个状态中,如果遇到“<”字符,它会转换到“RCDATA小于号状态”。如果“<”字符后没有紧跟着“/”和对应的标签名,解析器会转换回“RCDATA状态”。这意味着在RCDATA元素标签的内容中(例如<textarea>或<title>的内容中),唯一能够被解析器认做是标签的就是它本身,即</textarea>或者</title>。因此,在<textarea>和<title>的内容中不会创建标签,就不会有脚本能够执行。所以例5,例6都不能执行,但他还是能解析实体编码:

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

    在这里插入图片描述
    至于外部元素中的,CDATA:

    我们来迅速看一下CDATA元素。任何在CDATA元素中的内容将不会触发解析器创建开始标签。闭合CDATA元素的标志是“]]>”序列。因此如果用户想逃出CDATA元素,就要用未经任何编码的“]]>”序列,不然是不会逃出CDATA元素的。

    "属性值状态中的字符引用"

    这部分将放到url解析中讲述

    url解析

    这个都比较清楚,着重看一下例1:

    //1.URL 编码 "javascript:alert(1)"
    <a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29">123</a>
    

    这里是:不能对协议类型进行任何的编码操作,不然URL解析器会认为它无类型

    例1中对js伪协议(:也是其中一部分)进行了编码,导致url解析其为无类型,于是没有弹窗

    再来看一下例2:

    //2.HTML字符实体编码 "javascript" 和 URL 编码 "alert(2)"
    <a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:%61%6c%65%72%74%28%32%29">123</a>
    

    这里就用到了上面没说的:属性值状态中的字符引用
    由于属性值状态中的字符实体是能被解析的,所以上面的代码首先经过html解析会变成:

    <a href="javascript:%61%6c%65%72%74%28%32%29">123</a>
    

    然后进行url解析,变成

    <a href="javascript:alert(2)">123</a>
    

    由此即可正常弹窗

    例7也是一样:

    //7.HTML字符实体编码 " ' " (单引号)
    <button onclick="confirm('7&#39;);">Button</button>
    

    这里&#39;作为属性值中的字符实体,先被解析成',然后与前面的单引号闭合弹窗

    javascript解析

    HTML五类元素中的第二类:原始文本元素中的<script>

    就与js解析有关,而script块有个有趣的属性:在块中的字符引用并不会被解析和解码
    看到例9

    //9.HTML字符实体编码 alert(9);
    <script>&#97;&#108;&#101;&#114;&#116&#40;&#57;&#41;&#59</script>
    

    由于在script块中的字符实体编码不会被解析,所以不会弹窗

    不过,js还支持unicode解析。根据文章,js是否会解析unicode编码并执行需要:"视情况而定"
    具体要看被编码的序列到底是哪部分,unicode可以放在3个部分:字符串中,标识符名称中和控制字符中

    字符串中

    当Unicode存在于字符串中时,它只会被解释为正规字符,而不是单引号,双引号或者换行符这些能够打破字符串上下文的字符。因此,Unicode转义序列将永远不会破环字符串上下文,因为它们只能被解释成字符串常量。

    标识符名称中

    当Unicode转义序列出现在标识符名称中时,它会被解码并解释为标识符名称的一部分,例如函数名,属性名等等。
    看例10:

    //10.Unicode 编码 alert
    <script>u0061u006cu0065u0072u0074(10);</script>
    

    这里unicode出现在alert这个函数中,允许被解析并执行

    控制字符中

    当用Unicode转义序列来表示一个控制字符时,例如单引号、双引号、圆括号等等,它们将不会被解释成控制字符,而仅仅被解码并解析为标识符名称或者字符串常量。如果你去看ECMAScript的语法,就会发现没有一处会用Unicode转义序列来当作控制字符。例如,如果解析器正在解析一个函数调用语句,圆括号部分必须为“(”和“)”,而不能是u0028和u0029。

    说的已经比较详细了,还是看个例子:
    例11

    //11.Unicode 编码 alert(11)
    <script>u0061u006cu0065u0072u0074u0028u0031u0031u0029</script>
    

    这里本来是alert(11),但是unicode并不能用来表示一个控制字符,如其中的(),所以不会弹窗

    例13也是同样的不能用来表示单引号

    //13.Unicode 编码 " ' " (单引号)
    <script>alert('13u0027)</script>
    

    而例8中有onclick这个属性,所以也会调用js解析,不过也不会用来表示单引号

    //8.Unicode编码 " ' " (单引号)
    <button onclick="confirm('8u0027);">Button</button>
    

    例12看上去没有违背这个规则为什么没有弹窗

    //12.Unicode 编码 alert 和 12
    <script>u0061u006cu0065u0072u0074(u0031u0032)</script>
    

    因为unicode解码之后是ASCII型的数字,需要使用单引号闭合

    <script>u0061u006cu0065u0072u0074('u0031u0032')</script>
    

    在这里插入图片描述

    以上就是html、url、js解析器的简略内容

    最后完善一下上面的例子:

    //1.URL 编码 "javascript:alert(1)"
    <a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29">123</a>
    //不会弹窗,js伪协议被url编码会被url解析器当作无类型
    
    //2.HTML字符实体编码 "javascript" 和 URL 编码 "alert(2)"
    <a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:%61%6c%65%72%74%28%32%29">123</a>
    //会弹窗,经过html解析实体编码后得到javascript:,得到一个js伪协议
    
    //3.URL 编码 ":"
    <a href="javascript%3aalert(3)">123</a>
    //不会弹窗,同1
    
    //4.HTML字符实体编码 < 和 >
    <div>&#60;img src=x onerror=alert(4)&#62;</div>
    //不会弹窗,html实体不能当作新标签开始
    
    //5.HTML字符实体编码 < 和 >
    <textarea>&#60;script&#62;alert(5)&#60;/script&#62;</textarea>
    //不会弹窗,由于是RCDATA 状态中的字符引用
    
    //6.textarea中直接alert
    <textarea><script>alert(6)</script></textarea>
    //不会弹窗,同6
    
    //7.HTML字符实体编码 " ' " (单引号)
    <button onclick="confirm('7&#39;);">Button</button>
    //会弹窗,属于属性值状态的字符引用
    
    //8.Unicode编码 " ' " (单引号)
    <button onclick="confirm('8u0027);">Button</button>
    //不会弹窗,属于控制符中的unicode,不能表示控制字符
    
    //9.HTML字符实体编码 alert(9);
    <script>&#97;&#108;&#101;&#114;&#116&#40;&#57;&#41;&#59</script>
    //不会弹窗,script块中的字符实体编码不会被解析
    
    //10.Unicode 编码 alert
    <script>u0061u006cu0065u0072u0074(10);</script>
    //会弹窗,属于标识符名称中的unicode,用来表示alert
    
    //11.Unicode 编码 alert(11)
    <script>u0061u006cu0065u0072u0074u0028u0031u0031u0029</script>
    //不会弹窗,同8
    
    //12.Unicode 编码 alert 和 12
    <script>u0061u006cu0065u0072u0074(u0031u0032)</script>
    //不会弹窗,unicode解码后为ASCII类型,需要加引号
    
    //13.Unicode 编码 " ' " (单引号)
    <script>alert('13u0027)</script>
    //不会弹窗,同8
    
    //14.Unicode 编码换行符(0x0A)
    <script>alert('14u000a')</script>
    //会弹窗,因为用引号闭合
    
  • 相关阅读:
    20190919-4 单元测试,结对
    20190919-3 效能分析
    20190919-2 功能测试
    git 和conding.net 超详细超简单安装
    html元素contenteditable属性如何定位光标和设置光标
    【分享】WeX5的正确打开方式(6)——数据组件初探
    从零开始开发一款H5小游戏(二) 创造游戏世界,启动发条
    分享一个自己写的基于canvas的原生js图片爆炸插件
    基于 HTML5 的 WebGL 技术构建 3D 场景(一)
    从零开始开发一款H5小游戏(三) 攻守阵营,赋予粒子新的生命
  • 原文地址:https://www.cnblogs.com/W4nder/p/12783678.html
Copyright © 2011-2022 走看看