xss过滤器无法处理ajax请求_信息安全中之XSS的危害

b66678c9f9bc8b0a31770c58e7d2c29b.png

通过 XSS 攻击,黑客能做什么?

我们知道,这 3 种 XSS 攻击,都是因为黑客在用户的浏览器中执行了恶意的 JavaScript 脚本。那么执行这些 JavaScript 脚本有什么样的危害呢?我把这些危害总结了一下,可以分为下面几种。

1. 窃取 Cookie

从上面的例子中,我们可以看到,黑客可以窃取用户的 Cookie。因为黑客注入的 JavaScript 代码是运行在 http://server.com 这个域名下的,因此,黑客可以在 JavaScript 中通过 document.cookie 获得 Cookie 信息。

另外,需要我们注意的是,受SOP(Same Origin Policy,同源策略)保护,我们在 http://server.com 中是无法直接向 http://hacker.com 发送 GET 或者 POST 请求的。这也是为什么,在上面的例子中,我们需要通过 window.location 来执行跳转操作,间接地将 Cookie 信息发送出去。除了 window.location 之外,我们还可以通过加载 JavaScript 文件、图片等方式,向 http://attacker.com 发送带有 Cookie 的 GET 请求。

2. 未授权操作

除了窃取敏感信息以外,黑客还可以利用 JavaScript 的特性,直接代替用户在 HTML 进行各类操作。

在文章开头,我们提到的微博 XSS 攻击事件中,黑客就利用 JavaScript 脚本,让用户发送了一个微博,微博中同时还带有反射型 XSS 的链接。这样一来,每个点击链接的用户都会通过微博的形式,诱导更多的用户点击链接,一传十、十传百,造成大范围的传播。

3. 按键记录和钓鱼

窃取 Cookie 和未授权操作都是我们很容易想到的危害,除此之外,JavaScript 还能做什么呢?

JavaScript 的功能十分强大,它还能够记录用户在浏览器中的大部分操作。比如:鼠标的轨迹、键盘输入的信息等。也就是说,你输入的账号名和密码,都可以被 JavaScript 记录下来,从而被黑客获取到。

另外,即使某个存在 XSS 漏洞的页面不具备任何输入框,黑客还可以通过修改 DOM,伪造一个登录框,来诱导用户在本不需要登录的页面,去输入自己的用户名和密码。这也是“钓鱼”的一种形式,在这个过程中用户访问的域名是完全正常的,只是页面被篡改了,所以具备更高的迷惑性。


如何进行 XSS 防护?

认识到 XSS 的危害之后,作为开发人员,我们最应该掌握的是,如何避免在开发过程中出现 XSS 漏洞。接下来我们就来看一看,具体有哪些防护方法。

1. 验证输入 OR 验证输出

防护的核心原则是:一切用户输入皆不可信。你的第一反应一定是,这很好实现啊,当接收到用户的输入时,我们就进行验证,这不就做到了吗?实际上并不是这么简单的,我们还是通过搜索这个例子来看。在用户点击“搜索”按钮之后,如果我们马上对他输入的内容进行验证,这样就会产生两个问题。

1. 你将无法保存用户的原始输入信息。这样一来,当出现了 Bug 或者想要对黑客行为进行溯源时,你只能“推断”,而不能准确地获取用户的原始输入。

2. 用户的内容可能会被多种语言获取和使用,提前编码或者处理,将产生未知的问题。比如,在旧版本的 PHP 中,就存在“magic quotes”的漏洞,因为 PHP 无法处理某些编码的字符而导致崩溃。

因此,我更推荐在需要输出的时候去进行验证,即当需要展示的时候,我们再对内容进行验证,这样我们就能够根据不同的环境去采取不同的保护方案了。

在 HTML 中,常见的 XSS 注入点我已经总结好了,你可以看下面这个表格:

8e4c3f5c25ea0d85e3394f4d2915d215.png

2. 编码

现在,我们已经理解了,XSS 防护的核心原则就是验证,那具体该怎么去做验证呢?我认为,我们可以优先采用编码的方式来完成。所谓编码,就是将部分浏览器识别的关键词进行转换(比如 < 和 >),从而避免浏览器产生误解。对于客户端来说,编码意味着,使用 JavaScript 提供的功能对用户内容进行处理。具体的方法我也总结了一下,你可以看这个表格。

63faab9de4d3f1e767d01b7eefb39b63.png

对于最后一个注入点,即在 JavaScript 中进行注入,目前还没有内置的编码方式来对它提供保护。你当然可以通过诸如 URL 编码等方式进行编码,但这有可能对应用的自身逻辑产生影响。因此,JavaScript 中的注入并不适合通过编码来进行保护。

3. 检测和过滤

但是,在很多时候,编码会对网页实际的展现效果产生影响。比如,原本用户可能想展示一个 1>0,却被编码展示成了 1&gt0。尽管网络环境安全了,却对用户造成了困扰。那么,我们还可以采取哪些方法进行验证呢?接下来我就为你介绍一下检测和过滤。

首先,我们需要对用户的内容进行检测。在这里,我们可以采用黑名单和白名单的规则。黑名单往往是我们最直接想到的方法:既然黑客要插入<javascript>标签,那么我们就检测用户内容中是否存在<javascript>标签就好了。

但是,黑客的攻击方法是无穷无尽的。你检测了<javascript>,黑客就可以改成<JavaScript>(HTML 标签对大小写不敏感),甚至有些时候还能够编码成&#106;avascript等等。另外,HTML5 的发展速度很快,总是有新的标签被开发出来,这些新标签中也可能包含新的注入点。因此,黑名单的更新和维护过程,是需要我们和黑客进行长期对抗的过程。

所以,在检测中,更推荐使用白名单的规则。因为白名单的规则比较简单,并且十分有效。比如,在只输入一个分数的地方,规定只有整型变量是合法的。这样一来,你就能够检测出 99.99% 的攻击行为了。

说完了检测,那当发现某个用户的内容可能存在 XSS 攻击脚本时,我们该怎么处理呢?这个时候,处理选项有两个:拒绝或者过滤。毫无疑问,拒绝是最安全的选项。一旦你发现可能的 XSS 攻击脚本,只要不将这段用户内容展现出来,就能避免可能的攻击行为。

但是,拒绝会阻碍用户的使用流程,从用户体验的角度上来考虑的话,过滤会更被用户所接受。上面提到的编码就属于一种过滤的方式。除此之外,我们也可以直接对敏感字符进行替换删除等。需要注意的是,在替换的时候,一定不能采取黑名单的形式(比如:将 javascript 进行删除,那黑客就可以通过 JavaScript 来绕过),而是应该采取白名单的形式(比如,除了 div 之外的标签全部删除)

同样地,过滤的流程也必须彻底。比如,我看到过有人采用下面这行字符串来过滤 javascript 标签:

 $str=str_replace('<javascript>','',$str);

但黑客只需要将 str 的值变成<java<javascript>script>就可以了,因为str_replace('<javascript>','','<java<javascript>script>')的结果就是<javascript>。

4.CSP

面对 XSS 这样一个很普遍的问题,W3C 提出了 CSP(Content Security Policy,内容安全策略)来提升 Web 的安全性。所谓 CSP,就是在服务端返回的 HTTP header 里面添加一个 Content-Security-Policy 选项,然后定义资源的白名单域名。浏览器就会识别这个字段,并限制对非白名单资源的访问。

配置样例如下所示:

Content-Security-Policy:default-src ‘none’; script-src ‘self’; 
connect-src ‘self’; img-src ‘self’; style-src ‘self’;

那我们为什么要限制外域资源的访问呢?这是因为 XSS 通常会受到长度的限制,导致黑客无法提交一段完整的 JavaScript 代码。为了解决这个问题,黑客会采取引用一个外域 JavaScript 资源的方式来进行注入。除此之外,限制了外域资源的访问,也就限制了黑客通过资源请求的方式,绕过 SOP 发送 GET 请求。目前,CSP 还是受到了大部分浏览器支持的,只要用户使用的是最新的浏览器,基本都能够得到很好的保护。


写在最后

预防 XSS 主要通过对用户内容的验证来完成。首先,我推荐在需要展示用户内容的时候去进行验证,而不是当用户输入的时候就去验证。在验证过程中,我们优先采用编码的方式来完成。如果编码影响到了业务的正常功能,我们就可以采用白名单的检测和过滤方式来进行验证。除此之外,我们可以根据业务需要,配置合适的 CSP 规则,这也能在很大程度上降低 XSS 产生的影响。

7c35c20b6df2a7b9373edbe87f0ca9e5.png

可能有人会问了,前端请求中,出于安全问题,为什么浏览器会对ajax 请求有跨域安全限制,但是像<script src='xxx'><img src='xxx'>这样的标签请求过来的数据,却没有跨域安全限制呢?这其实算是一种妥协。网页中经常需要引用一些外部的资源,比如说图片。如果一律禁止的话,那相当于每个网站都得自己维护一套完整的资源,会很麻烦。因此,对于静态资源的访问,是一律允许的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值