前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浏览器解析与编码顺序及xss挖掘绕过全汇总

浏览器解析与编码顺序及xss挖掘绕过全汇总

作者头像
Jayway
发布2019-09-29 17:28:53
4.6K0
发布2019-09-29 17:28:53
举报
文章被收录于专栏:卓文见识卓文见识

在以往的培训和渗透过程中,发现很多渗透人员尤其是初学者在挖掘xss漏洞时,很容易混淆浏览器解析顺序和解码顺序,对于html和js编码、解码和浏览器解析顺序、哪些元素可以解码、是否可以借助编码绕过等情况也基本处于混沌的状态,导致最终只能扔一堆payload上去碰碰运气。这篇文章就把浏览器解析顺序、编码解码的类型、各种解码的有效作用域以及在xss里的实战利用技巧做一个系统总结,让你深度掌握xss挖掘和绕过。


文章结构如下:

1、前提:编码相关

1.1 URL编码

标准的url结构我们都清楚,像这样:

scheme://login:password@address:port/path?query_string#fragment

比如:

http://example.com/test.php?uid=27&content=on#main

可以看到,像:?/=这些字符是浏览器用来解析URL用于语义分隔的保留字符,那么问题来了,如果URL中某个部分的名称用到了这些字符,就会破坏语法,影响正常解析,于是就有了url编码,它以一个百分号%和该字符的ASCII对应的2位十六进制数去替换这些字符,如常见的空格编码为%20,百分号%编码为%20,等于号=编码为%3d,等等。

1.2 HTML编码

跟url的问题类似,一些字符在 HTML 中也是是预留的,像<这样的对于HTML来说有特殊意义的字符,在浏览器中会被解析成各种标签,如果要作为纯文本输出这个字符,就需要用到字符实体。

HTML编码类型

说到编码的时候,大多数初学者看到&#x;这些字符通常会一头雾水,其实我们见到的所谓“编码”有两种,共同点是以连接符&开头以分号;结尾,中间字符有:

  • 英文字符;
  • #后接十进制数或#x后接十六进制数。

如&lt;、&#60;和&#x3c;都可以被解码成常见的尖括号<:

再具体一点,lt叫做实体名称,60和x3c叫做实体编号,效果其实是一样的,只是实体名称更容易记忆,但就浏览器的支持性来说实体编码要好一些。常见的实体如下:

(注:在<被过滤的场景下很多人会尝试使用&lt;来绕过,这样输出的尖括号会被解析成文本格式,而不是作为标签执行,很少的情况下可以利用成功,下面会有案例讲到。

1.3 JS编码

道理同上,js常见的反斜杠方式编码处理

  • \b退格符,\t制表符,\v垂直制表符等;
  • 三位数字,不足位数用0补充,按8位原字符八进制字符编码;
  • 两位数字,不足位数用0补充,按8位原字符16进制字符编码,前缀 x
  • 四位数字,不足为数用0补充,按16位原字符16进制Unicode数值编码,前缀 u 。

如\145、\x65和\u0065都代表字符e。

2、浏览器解析顺序:

2.1 数据包处理过程:

首先要了解我们在构造xss包的时候发生了什么:

1、在浏览器的地址栏中输入url,发送http请求头和数据;

2、数据包通过网络传输到达远程web服务器,服务器接收到url,分析请求头,根据它找到对应资源,经过后端代码进行处理(过滤,校验),然后给前端返回响应头和数据;

3、浏览器接收到响应的数据后,对数据进行解析(下面要说的事)

2.2 浏览器解析顺序

主要分为两个过程:

1、 浏览器接收到响应数据后,解析器先对HTML之类的文档进行解析,构建成DOM节点树,同时,CSS会被CSS解析器解析生成样式表。

2、 解析html标签过程中遇到<script>标签,则暂停HTML标签解析,控制权转交给JavaScript引擎,执行完后继续解析html,js可以对DOM进行修改。

因此js所处的位置会影响DOM的操作顺序,js若在header中会立即执行,若放在body的最尾部则可以在DOM生成后对DOM进行处理,若在DOM结构生成之前就调用DOM,JavaScript会报错。但使用defer属性也可以让浏览器在DOM加载完成后,再执行指定脚本。

2.3 实例解析

例1:纯html代码:

代码语言:javascript
复制
<html>
代码语言:javascript
复制
    <h1>Main Title</h1>
代码语言:javascript
复制
    <div>
代码语言:javascript
复制
        <h2>Second Title</h2>
代码语言:javascript
复制
        <p>Content</p>
代码语言:javascript
复制
    </div>
代码语言:javascript
复制
</html>

通过解析器的解析后生成DOM树:

如果在这个时候,如果修改一下,比如说把<h1>Main Title</h1>用html编码成:

<&#104;1>Main Title</h1>

<h1>M&#97;inT&#105;tle</h1>

前者对标签名编码,后者对标签内容编码,结果会发现前者没有了html标签的作用,而后者正常显示。由此可以明白HTML解码的时机:它是在浏览器构建完DOM树以后才进行解码的,当解析器对前者进行解析时,无法识别为html标签,所以构建不了DOM节点,后者在顺利构建完DOM树之后对节点内容进行解码。

例2:包含js和html的代码:

代码语言:javascript
复制
<div id="content"></div>
代码语言:javascript
复制
 
代码语言:javascript
复制
<img src="y.com" onerror="alert(2)"/>
代码语言:javascript
复制
<p>Hello Parser!</p>
代码语言:javascript
复制
 
代码语言:javascript
复制
<script>
代码语言:javascript
复制
var content = document.getElementById("content");
代码语言:javascript
复制
var img = document.createElement("img");
代码语言:javascript
复制
img.src =   "x.com";
代码语言:javascript
复制
img.setAttribute("onerror","&#97;lert(1)");
代码语言:javascript
复制
 
代码语言:javascript
复制
content.appendChild(img);
代码语言:javascript
复制
</script>

尾部的script脚本中改变了DOM节点树,通过对<div>操作新增了一个<img>,所以通过调换<script>和img的先后顺序,会使得弹框的顺序不同。

3、浏览器解码顺序:

3.1 URL解码:

url解码过程较为简单,服务器对接收到用户传输过来的URL进行解析,遇到%便自动进行解码。

3.2 HTML解码:

首先了解一下HTML解析器的工作原理:

HTML解析器其实是一个状态机,在对HTML资源从上而下进行解析时遇到一个‘<‘符号就会进入标签开始状态(Tag Open State),然后搜寻标签,img可以被识别为正确的标签,img1则不会识别,最后在读到最近的一个‘>’时,结束标签状态进入数据状态(Data State)。

哪些HTML字符实体会被解析?

一般来说,HTML编码要在Data state(标签外部和标签的text段),标签内的属性值的位置才能被解析。可以对各个部分进行测试,是否可以使用实体替换以及执行效果如何:

3.3 Js解码:

Js解码就简单很多,js的脚本处理模型是按照源码处理-函数解析-代码执行这个执行流来的,不管是外部引用还是直接写在script标签里,又或者是在html标签的属性里,对于js编码的解码都是相同的,所以分别对函数编码:

<script>

\u0061lert("HelloWorld");

</script>

对value值进行编码:

<script>

alert("\u0048elloWorld");

</script>

效果都是一样的,xss挖掘中这样的编码适用于js代码环境中alert等函数被过滤的情况。

3.4 浏览器的解码顺序:

首先要强调是一点是:浏览器的解码顺序和解析顺序是两码事。浏览器一般的解码顺序是先进行html解码,再进行javascript解码,最后再进行url解码,需要注意的是这里的url解码和我们发送到服务器的url解码不同,那个过程是由服务器来完成的,而不是浏览器。

明白了这个顺序,我们就可以理解<script>alert&#40;'1')</script>是无法弹框的,因为script标签内无法解析HTML实体编码。

2个tips:

1、 在<textarea>和<title>的内容中不会创建标签,不会有脚本能够执行,结果是这样:

所以遇到输出在<textarea>之间的情况,如果不能使用</textarea>闭合,就要提早放弃。

2、 <svg>属于外部标签,是一种特殊的标签,它使用XML格式定义图像,支持XML解析。因为xml支持在标签内解析HTML实体字符,所以在XML中&#40;会被解析成(,<svg><script>alert&#40;'1')</script>是可以被解析的。

前端技术繁多,还有很多其他小tips,在这里不一一列举。

3.5 实例解析

例1:

根据上面讲的浏览器解码顺序,我们可以提交payload:

<img src="1"onerror=&#92;&#117;&#48;&#48;&#54;&#49;&#92;&#117;&#48;&#48;&#54;&#99;&#92;&#117;&#48;&#48;&#54;&#53;&#92;&#117;&#48;&#48;&#55;&#50;&#92;&#117;&#48;&#48;&#55;&#52;&#40;&#39;&#92;&#117;&#48;&#48;&#51;&#49;&#39;&#41;>

第一步 在html中所以解析成:

<img src="1"onerror=\u0061\u006c\u0065\u0072\u0074('\u0031')>

第二步 因为事件触发函数后的字符串也是js代码,经过js解码成:

<img src="1" onerror=1>

例2:

当下大多数网站对xss的防御是对用户输入使用html实体编码,大多数情况下可以达到效果,但有些场景下并不能生效,一种经典的情况就是,服务器将用户输入的htmlencoded值直接动态输出到客户端javascript(事件处理器)中:

<input value=<%= HtmlEncode(input)%> id=textbox>

如果input处用户输入a onclick=alert(document.cookie),结果会输出为:

<input value=aonclick=alert(document.cookie) id=textbox>

很容易理解,根据上述讲到的浏览器解析顺序,用户输入——>后台代码编码——>浏览器(HTML解析器)解析——>传到js代码执行。

下面这个也是在现实渗透中发现的一个案例,核心也是在经过<input>解码为value值后传递给了innerHTML,将其二次解析成HTML格式内容。所以总结起来绕过这种编码的关键就是需要注意输入输出的上下文,看输入是否进行了二次传递、处理。

4、xss的挖掘和绕过思路

xss的挖掘思路的核心是:关注“输入”和“输出“”,也是大多数漏洞产生和挖掘的核心。基本的思路和流程如下:

简单来讲分为三步:

1、探测输出点

输入处使用容易辨识的特征值明确输出点,如“aaaaa”,“11111”等等都可以,确定是单点输出、多点输出,以及是否存在二次输出的情况。

2、根据HTML结构构造payload

这一步需使用第二章的内容,明确输出点的位置在HTML标签文本内、标签属性中、标签事件中、<script>标签内、function函数变量中等等。这里需要清楚DOM结构和标签的优先级,有时候输出可能在不同层级的标签内,就像下面的输出就既可以选择闭合内部的function()函数,也可以直接闭合更高一级的<script>。

通常构造payload流程也有三步:

  • 闭合输入前的标签;
  • 使弹框语句正常执行;
  • 处理剩下的字符;

对应上面这个案例,对function函数进行处理:

  • 闭合前面的成对字符串:123";}
  • 输入弹框语句,因为在<script>内,所以输入confirm(/Jayway/);
  • 遗留“;无法注释,可以复制之前的结构语句使其正确: function b(){a=",最终payload为123";}confirm(/Jayway/);function b(){a="z

最终构造成功的结构其实为<script>标签内并列的两个自定义function和一个confirm,当然这里直接对<script>进行处理更为简便。

3、检测过滤及绕过

如果系统对输入做了过滤,我们可以通过各种方法进行绕过,当然这篇文章说的编码绕过只是其中一种方法,过滤的情况也不尽相同,有对尖括号、圆括号、引号等字符的过滤,有对alert、script关键字的过滤,还有对于组合的正则过滤。

在黑盒测试的时候,可以通过intruder模块对于各种关键字进行fuzzing测试,确定后端的过滤机制,然后对于不同的过滤采取不同的绕过手段,但前提是要根据浏览器的解析和解码原理针对性地进行构造。

比如过滤了()可以用反引号``代替;过滤了script用img等标签;过滤了<>看是不是可以用事件触发,过滤了alert可以用confirm、throw、prompt。这部分涉及内容太多,有空再集中做个汇总。

对xss的精通程度取决于对浏览器机制和HTML、JS的了解程度,在理解本文的基础上对常见的标签和事件进行学习补充,在xss练习平台上加以练习,一般的xss都可以挖掘得到。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 卓文见识 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、前提:编码相关
    • 1.1 URL编码
      • 1.2 HTML编码
        • 1.3 JS编码
        • 2、浏览器解析顺序:
          • 2.1 数据包处理过程:
            • 2.2 浏览器解析顺序
              • 2.3 实例解析
              • 3、浏览器解码顺序:
                • 3.1 URL解码:
                  • 3.2 HTML解码:
                    • 3.3 Js解码:
                      • 3.4 浏览器的解码顺序:
                        • 3.5 实例解析
                        • 4、xss的挖掘和绕过思路
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档