深入讲解XSS利用编码绕过的原理

网页的解码过程

简单说一下,编码就是将字符变为二进制数,而解码就是将二进制数还原为字符。从浏览器请求url到在页面上显示出来也会经历一些编码和解码的过程,我们来具体看一下。

URL编码

URL编码是为了允许URL中存在汉字这样的非标准字符,本质是把一个字符转为%加上UTF-8编码对应的16进制数字。
在服务端接收到请求时,会自动对请求进行一次URL解码。

HTML编码/解码

当浏览器接收到服务端发送来的二进制数据后,首先会对其进行HTML解码,呈现出来的就是我们看到的源代码。具体的解码方式依具体情况而定,所以我们需要在页面中指定编码,防止浏览器按照错误的方式解码,造成乱码。

但是在HTML中有些字符是和关键词冲突的,比如<、>、&。
为了正确地显示预留字符,我们需要在HTML源代码中使用字符实体,比如我们常见的空格&nbsp;,字符实体以&开头+预先定义的实体名称表示,但不是所有的字符都有实体名称,但是它们都有实体编号,也可以用&#开头+实体编号+分号表示。

浏览器对HTML解码之后就开始解析HTML,将标签转化为内容树中的DOM节点,此时识别标签的时候,HTML解析器是无法识别那些被实体编码的内容的,只有建立起DOM树,才能对每个节点的内容进行识别,如果出现实体编码,则会进行实体解码,只要是DOM节点里属性的值,都可以被HTML编码和解析。

所以在PHP中,使用htmlspecialchars()函数把预定义的字符转换为HTML实体,只有等到DOM树建立起来后,才会解析HTML实体,起到了XSS防护作用。

JS解码(只支持UNIDODE)

当HTML解析产生DOM节点后,会根据DOM节点来做接下来的解析工作,比如在处理诸如<script> <style>这样的标签,解析器会自动切换到JS解析模式,而src、 href 后边加入的javascript 伪URL,也会进入JS 的解析模式。

比如<a href="javascript:alert('<\u4e00>')">test</a>,javascript 出发了JS 解释器,JS会先对内容进行解析,里边有一个转义字符\u4e00,前导的 \u 表示他是一个unicode 字符,根据后边的数字,解析为一,于是在完成JS的解析之后变成了:href=“javascript:alert(‘<一>’)”>test
由此可见,想要字符编码后能够被JS识别,可以对字符进行unicode编码。

用实例来讲解xss编码

<a href="javascript:alert('xss')">test</a>

浏览器对其解析的过程大致为:
首先HTML解析器开始工作,并对href中的字符做HTML解码,接下来URL解析器对href值进行解码,正常情况下URL值为一个正常的URL链接,如:https://www.baidu.com,那么URL解析器工作完成后是不需要其他解码的,但是该环境中URL资源类型为Javascript,因此该环境中最后一步Javascript解析器还会进行解码操作,最后解析的脚本被执行。
归纳一下就是:HTML解码 -->URL解码 -->JS解码

对其进行以下变形,都可顺利弹窗

(1)

对alert做JS编码,因为当HTML打算对<a>DOM节点进行HTML实体解析时,发现URL资源类型为Javascript,因此会调用JS解析器来对JS代码进行解析

<a href="javascript:\u0061\u006c\u0065\u0072\u0074('xss')">test</a>

(2)

也可以利用解码顺序进行混合编码:

1. 原代码
<a href="javascript:alert('xss')">test</a>
2. 对alert进行JS编码(unicode编码)
<a href="javascript:\u0061\u006c\u0065\u0072\u0074('xss')">test</a>
3. 对href标签中的\u0061\u006c\u0065\u0072\u0074进行URL编码
<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('xss')">test</a>
4. 对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('xss')进行HTML编码:
<a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3a;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x33;&#x31;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x36;&#x33;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x33;&#x35;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x37;&#x25;&#x33;&#x32;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x37;&#x25;&#x33;&#x34;&#x28;&#x27;&#x78;&#x73;&#x73;&#x27;&#x29;">test</a>
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值