XSS 跨站脚本攻击
文章目录
简介
XSS,即 Cross Site Script,中译是跨站脚本攻击
;
其原本缩写是 CSS,但为了和层叠样式表(Cascading Style Sheet)有所区分,因而在安全领域叫做 XSS。
攻击者通过在HTML上注入恶意<script>脚本,使之在用户的浏览器上运行
。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。
XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。
而由于直接在用户的终端执行,恶意代码能够直接获取用户的信息,或者利用这些信息冒充用户向网站发起攻击者定义的请求。
分类
根据攻击的来源,XSS 攻击可分为存储型
、反射型
和 DOM 型
三种。
类型 | 存储区(恶意代码存放的位置) | 插入点(由谁取得恶意代码) | 责任方 |
---|---|---|---|
存储型 XSS | 后端数据库 | HTML | 服务端 |
反射型 XSS | URL | HTML | 服务端 |
DOM 型 XSS | 后端数据库/前端存储/URL | JavaScript | 前端 |
1. 存储型(持久型)XSS
黑客将代码存储到漏洞服务器中,用户浏览相关页面发起攻击
存储型 XSS 的攻击步骤:
- 黑客将恶意脚本代码上传或存储到漏洞服务器
- 服务器把恶意脚本保存到服务器
- 当正常客户访问服务器时,服务器会读取恶意数据并且直接使用
- 服务器会返回含有恶意脚本的页面
tips:
- 这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
.
2. 反射型(非持久型)XSS
服务器没有对恶意的用户输入进行安全处理就直接反射响应内容,导致恶意代码在浏览器中执行
反射型 XSS 的攻击步骤:
- 攻击者构造出特殊的 URL,其中包含恶意代码。
- 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
- 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
tips:
- 反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。
- 反射型XSS攻击是一次性的,必须要通过用户点击链接才能发起,攻击者往往会结合多种手段诱导用户点击。
- 一些浏览器如Chrome其内置了一些XSS过滤器,可以防止大部分反射型XSS攻击
- 反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。
.
3. DOM 型 XSS
不需要服务器端支持,是由于DOM结构修改导致的,基于浏览器DOM解析的攻击
DOM 型 XSS 的攻击步骤:
- 攻击者构造出特殊的 URL,其中包含恶意代码。
- 用户打开带有恶意代码的 URL。
- 浏览器在DOM解析的时候,前端 JavaScript 取出 URL 中的恶意代码并执行。
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
tips:
- 常见的触发场景就是在修改
innerHTML
outerHTML
document.write
的时候 - DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。
预防
通过前面的介绍可以得知,XSS 攻击有两大要素:
- 攻击者提交恶意代码
- 浏览器执行恶意代码
预防存储型和反射型 XSS 攻击
存储型和反射型 XSS 都是在服务端
取出恶意代码后,插入到响应 HTML 里的,攻击者刻意编写的“数据”被内嵌到“代码”中,被浏览器所执行。
预防这两种漏洞,有两种常见做法:
- 改成
纯前端渲染
,把代码和数据分隔开。 - 对 HTML 做充分转义。
1. 纯前端渲染
前后端数据分离,通过ajax请求后端数据,再由前端渲染
纯前端渲染的过程:
- 浏览器先加载一个静态 HTML,此 HTML 中不包含任何跟业务相关的数据。
- 然后浏览器执行 HTML 中的 JavaScript。
- 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
、.outerHTML
、document.write()
时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用 .textContent
、.setAttribute()
等。
DOM 中的内联事件监听器,如 location
、onclick
、onerror
、onload
、onmouseover
等,<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 标签白名单,对于不在白名单之列的字符或者标签进行过滤或编码。
验证码
防止脚本冒充用户提交危险操作。