XSS 跨站脚本攻击

简介

XSS,即 Cross Site Script,中译是跨站脚本攻击
其原本缩写是 CSS,但为了和层叠样式表(Cascading Style Sheet)有所区分,因而在安全领域叫做 XSS。

攻击者通过在HTML上注入恶意<script>脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。

XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。
而由于直接在用户的终端执行,恶意代码能够直接获取用户的信息,或者利用这些信息冒充用户向网站发起攻击者定义的请求。


分类

根据攻击的来源,XSS 攻击可分为存储型反射型DOM 型三种。

类型存储区(恶意代码存放的位置)插入点(由谁取得恶意代码)责任方
存储型 XSS后端数据库HTML服务端
反射型 XSSURLHTML服务端
DOM 型 XSS后端数据库/前端存储/URLJavaScript前端

1. 存储型(持久型)XSS

黑客将代码存储到漏洞服务器中,用户浏览相关页面发起攻击

存储型 XSS 的攻击步骤:

  1. 黑客将恶意脚本代码上传或存储到漏洞服务器
  2. 服务器把恶意脚本保存到服务器
  3. 当正常客户访问服务器时,服务器会读取恶意数据并且直接使用
  4. 服务器会返回含有恶意脚本的页面

tips:

  • 这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。

.

2. 反射型(非持久型)XSS

服务器没有对恶意的用户输入进行安全处理就直接反射响应内容,导致恶意代码在浏览器中执行

反射型 XSS 的攻击步骤:

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

tips:

  • 反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。
  • 反射型XSS攻击是一次性的,必须要通过用户点击链接才能发起,攻击者往往会结合多种手段诱导用户点击。
  • 一些浏览器如Chrome其内置了一些XSS过滤器,可以防止大部分反射型XSS攻击
  • 反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。

.

3. DOM 型 XSS

不需要服务器端支持,是由于DOM结构修改导致的,基于浏览器DOM解析的攻击

DOM 型 XSS 的攻击步骤:

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL。
  3. 浏览器在DOM解析的时候,前端 JavaScript 取出 URL 中的恶意代码并执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

tips:

  • 常见的触发场景就是在修改innerHTML outerHTML document.write的时候
  • DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。

预防

通过前面的介绍可以得知,XSS 攻击有两大要素:

  1. 攻击者提交恶意代码
  2. 浏览器执行恶意代码

预防存储型和反射型 XSS 攻击

存储型和反射型 XSS 都是在服务端取出恶意代码后,插入到响应 HTML 里的,攻击者刻意编写的“数据”被内嵌到“代码”中,被浏览器所执行。

预防这两种漏洞,有两种常见做法:

  1. 改成纯前端渲染,把代码和数据分隔开。
  2. 对 HTML 做充分转义。

1. 纯前端渲染

前后端数据分离,通过ajax请求后端数据,再由前端渲染

纯前端渲染的过程:

  1. 浏览器先加载一个静态 HTML,此 HTML 中不包含任何跟业务相关的数据。
  2. 然后浏览器执行 HTML 中的 JavaScript。
  3. JavaScript 通过 Ajax 加载业务数据,调用 DOM API 更新到页面上。

但纯前端渲染还需注意避免 DOM 型 XSS 漏洞(例如 onload 事件和 href 中的 javascript:xxx 等,请参考下文”预防 DOM 型 XSS 攻击“部分)。

在很多内部、管理系统中,采用纯前端渲染是非常合适的。但对于性能要求高,或有 SEO 需求的页面,我们仍然要面对拼接 HTML 的问题。

2. 转义 HTML

如果拼接 HTML 是必要的,就需要采用合适的转义库,对 HTML 模板各处插入点进行充分的转义。

常用的模板引擎,如 doT.js、ejs、FreeMarker 等,对于 HTML 转义通常只有一个规则,就是把 & < > " ' / 这几个字符转义掉,确实能起到一定的 XSS 防护作用,但并不完善。

.

预防 DOM 型 XSS 攻击

DOM 型 XSS 攻击,实际上就是网站前端 JavaScript 代码本身不够严谨,把不可信的数据当作代码执行了。

在使用 .innerHTML、.outerHTMLdocument.write()时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用 .textContent.setAttribute() 等。

DOM 中的内联事件监听器,如 locationonclickonerroronloadonmouseover 等,<a> 标签的 href 属性,JavaScript 的 eval()setTimeout()setInterval() 等,都能把字符串作为代码运行。如果不可信的数据拼接到字符串中传递给这些 API,很容易产生安全隐患,请务必避免。

<!-- 内联事件监听器中包含恶意代码 -->
<img onclick="UNTRUSTED" onerror="UNTRUSTED" src="data:image/png,">

<!-- 链接内包含恶意代码 -->
<a href="UNTRUSTED">1</a>

<script>
// setTimeout()/setInterval() 中调用恶意代码
setTimeout("UNTRUSTED")
setInterval("UNTRUSTED")

// location 调用恶意代码
location.href = 'UNTRUSTED'

// eval() 中调用恶意代码
eval("UNTRUSTED")
</script>

如果项目中有用到这些的话,一定要避免在字符串中拼接不可信数据。


其他防范措施

CSP

CSP(内容安全策略)通过指定有效域——即浏览器认可的可执行脚本的有效来源——使服务器管理者有能力减少或消除XSS攻击所依赖的载体。一个CSP兼容的浏览器将会仅执行从白名单域获取到的脚本文件,忽略所有的其他脚本 (包括内联脚本和HTML的事件处理属性)。

CSP本质上就是建立白名单,开发者明确告诉浏览器哪些外部资源可以进行加载和执行,我们只需要配置规则,如何拦截是由浏览器自己实现的,我们可以通过这种方式来尽量减少XSS攻击

对于这种方式来说,这要开发者配置了正确的规则,那么即使网站存在漏洞,攻击者也不能执行它的攻击代码,而且CSP的兼容性不错。

输入检查

不要相信用户的任何输入。 对于用户的任何输入要进行检查、过滤和转义。建立可信任的字符和 HTML 标签白名单,对于不在白名单之列的字符或者标签进行过滤或编码。

验证码

防止脚本冒充用户提交危险操作。

posted @ 2022-07-20 18:15  猫老板的豆  阅读(118)  评论(0编辑  收藏  举报